mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge branch 'dev' into mqtt5
This commit is contained in:
commit
ab4a9e72d4
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -1,5 +1,6 @@
|
||||
name: PublishDockerImage
|
||||
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
@ -27,9 +28,6 @@ jobs:
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: node ./node-red/.github/scripts/update-node-red-docker.js
|
||||
with:
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
- name: Create Docker Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
|
@ -11,5 +11,11 @@ matrix:
|
||||
before_script:
|
||||
- npm install -g coveralls
|
||||
- node_js: "12"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
- node_js: "10"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
- node_js: "8"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
|
2
API.md
2
API.md
@ -10,6 +10,6 @@ Module | Description
|
||||
[@node-red/editor-api](@node-red_editor-api.html) | an Express application that serves the Node-RED editor and provides the Admin HTTP API
|
||||
[@node-red/runtime](@node-red_runtime.html) | the core runtime of Node-RED
|
||||
[@node-red/util](@node-red_util.html) | common utilities for the Node-RED runtime and editor modules
|
||||
@node-red/registry | the internal node registry
|
||||
[@node-red/registry](@node-red_registry.html) | the internal node registry
|
||||
@node-red/nodes | the default set of core nodes
|
||||
@node-red/editor-client | the client-side resources of the Node-RED editor application
|
||||
|
62
CHANGELOG.md
62
CHANGELOG.md
@ -1,3 +1,65 @@
|
||||
### 1.2.8: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Ensure subflow help is picked up for palette tooltip Fixes #2834
|
||||
- Improve Ru locale (#2826) @alexk111
|
||||
- Fix scrollbars (#2825) @alexk111
|
||||
|
||||
Runtime
|
||||
|
||||
- Restrict project file access to inside the project directory
|
||||
- Validate user-provided language parameter before passing to i18n
|
||||
- Fix grunt release mkdir issue on Node.js 14 (#2827) @alexk111
|
||||
- Prevent crash when coreNodesDir is empty (#2831) @hardillb
|
||||
|
||||
Nodes
|
||||
|
||||
- Batch node: Fixing minor typo in node's documentation (#2848) @matthiasradde
|
||||
- Split node: Handle out of order messages as long as one of the messages has msg.parts.count set to the proper value (#2748) @s4ke
|
||||
|
||||
### 1.2.7: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Ensure subflow-scoped config nodes do not get moved on import Fixes #2789
|
||||
- Allow TypedInput to be disabled (#2752) @bartbutenaers
|
||||
- Allow userMenu to be explicitly enabled (#2805) @tfmf
|
||||
- Improvements to DE translation (#2192) @ketzu
|
||||
|
||||
|
||||
Runtime
|
||||
|
||||
- Handle `undefined` error passed to node.error (#2781) @johnwang71
|
||||
- Disable nyc coverage reporting on older node versions
|
||||
- Improve Editor API unit test coverage (#2777) @aaronmyatt
|
||||
|
||||
|
||||
Nodes
|
||||
|
||||
- Trigger: ensure timestamp option sends .now() at point of sending
|
||||
|
||||
|
||||
### 1.2.6: Maintenance Release
|
||||
|
||||
|
||||
Editor
|
||||
|
||||
- Update Japanese translations for 1.2.5 (#2764) @kazuhitoyokoi
|
||||
- Library: properly handle symlinked folders (#2768) @natcl
|
||||
|
||||
Runtime
|
||||
|
||||
- Support Windows paths when installing tarball by path name Fixes #2769
|
||||
- Fix unsecure command usage in GH Action
|
||||
|
||||
Nodes
|
||||
|
||||
- Update MQTT to latest to fix Node 8 URL breakage
|
||||
|
||||
|
||||
|
||||
|
||||
### 1.2.5: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
@ -142,6 +142,7 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/bidi.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/format.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/state.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/plugins.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/nodes.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
||||
@ -461,7 +462,8 @@ module.exports = function(grunt) {
|
||||
'packages/node_modules/@node-red/runtime/lib/hooks.js',
|
||||
'packages/node_modules/@node-red/util/**/*.js',
|
||||
'packages/node_modules/@node-red/editor-api/lib/index.js',
|
||||
'packages/node_modules/@node-red/editor-api/lib/auth/index.js'
|
||||
'packages/node_modules/@node-red/editor-api/lib/auth/index.js',
|
||||
'packages/node_modules/@node-red/registry/lib/index.js'
|
||||
],
|
||||
options: {
|
||||
destination: 'docs',
|
||||
@ -623,6 +625,11 @@ module.exports = function(grunt) {
|
||||
'Builds editor content then runs code style checks and unit tests on all components',
|
||||
['build','verifyPackageDependencies','jshint:editor','nyc:all']);
|
||||
|
||||
grunt.registerTask('no-coverage',
|
||||
'Builds editor content then runs code style checks and unit tests on all components without code coverage',
|
||||
['build','verifyPackageDependencies','jshint:editor','simplemocha:all']);
|
||||
|
||||
|
||||
grunt.registerTask('test-core',
|
||||
'Runs code style check and unit tests on core runtime code',
|
||||
['build','nyc:core']);
|
||||
|
21
package.json
21
package.json
@ -27,7 +27,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"ajv": "6.12.6",
|
||||
"async-mutex": "0.2.4",
|
||||
"async-mutex": "0.2.6",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.0",
|
||||
@ -38,7 +38,7 @@
|
||||
"cookie-parser": "1.4.5",
|
||||
"cors": "2.8.5",
|
||||
"cron": "1.7.2",
|
||||
"denque": "1.4.1",
|
||||
"denque": "1.5.0",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.1",
|
||||
"fs-extra": "8.1.0",
|
||||
@ -54,11 +54,11 @@
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"media-typer": "1.1.0",
|
||||
"memorystore": "1.6.4",
|
||||
"mime": "2.4.6",
|
||||
"mime": "2.4.7",
|
||||
"moment-timezone": "0.5.32",
|
||||
"mqtt": "4.2.5",
|
||||
"mqtt": "4.2.6",
|
||||
"multer": "1.4.2",
|
||||
"mustache": "4.0.1",
|
||||
"mustache": "4.1.0",
|
||||
"node-red-admin": "^0.2.6",
|
||||
"node-red-node-rbe": "^0.2.9",
|
||||
"node-red-node-sentiment": "^0.1.6",
|
||||
@ -73,8 +73,7 @@
|
||||
"request": "2.88.0",
|
||||
"semver": "6.3.0",
|
||||
"tar": "6.0.5",
|
||||
"uglify-js": "3.11.6",
|
||||
"when": "3.7.8",
|
||||
"uglify-js": "3.12.4",
|
||||
"ws": "6.2.1",
|
||||
"xml2js": "0.4.23"
|
||||
},
|
||||
@ -82,7 +81,7 @@
|
||||
"bcrypt": "3.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.2.2",
|
||||
"dompurify": "2.2.6",
|
||||
"grunt": "1.3.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.3.2",
|
||||
@ -97,17 +96,17 @@
|
||||
"grunt-jsdoc": "2.4.1",
|
||||
"grunt-jsdoc-to-markdown": "5.0.0",
|
||||
"grunt-jsonlint": "2.1.3",
|
||||
"grunt-mkdir": "~1.0.0",
|
||||
"grunt-mkdir": "~1.1.0",
|
||||
"grunt-npm-command": "~0.1.2",
|
||||
"grunt-sass": "~3.1.0",
|
||||
"grunt-simple-mocha": "~0.4.1",
|
||||
"grunt-simple-nyc": "^3.0.1",
|
||||
"http-proxy": "1.18.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "1.2.4",
|
||||
"marked": "1.2.7",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "^5.2.0",
|
||||
"node-red-node-test-helper": "^0.2.5",
|
||||
"node-red-node-test-helper": "^0.2.6",
|
||||
"node-sass": "^4.14.1",
|
||||
"nodemon": "2.0.6",
|
||||
"should": "13.2.3",
|
||||
|
@ -22,6 +22,7 @@ var flow = require("./flow");
|
||||
var context = require("./context");
|
||||
var auth = require("../auth");
|
||||
var info = require("./settings");
|
||||
var plugins = require("./plugins");
|
||||
|
||||
var apiUtil = require("../util");
|
||||
|
||||
@ -32,6 +33,7 @@ module.exports = {
|
||||
nodes.init(runtimeAPI);
|
||||
context.init(runtimeAPI);
|
||||
info.init(settings,runtimeAPI);
|
||||
plugins.init(runtimeAPI);
|
||||
|
||||
var needsPermission = auth.needsPermission;
|
||||
|
||||
@ -50,12 +52,14 @@ module.exports = {
|
||||
// Nodes
|
||||
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler);
|
||||
|
||||
if (!settings.editorTheme || !settings.editorTheme.palette || settings.editorTheme.palette.upload !== false) {
|
||||
const multer = require('multer');
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
adminApp.post("/nodes",needsPermission("nodes.write"),upload.single("tarball"),nodes.post,apiUtil.errorHandler);
|
||||
} else {
|
||||
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler);
|
||||
if (!settings.externalModules || !settings.externalModules.palette || settings.externalModules.palette.allowInstall !== false) {
|
||||
if (!settings.externalModules || !settings.externalModules.palette || settings.externalModules.palette.allowUpload !== false) {
|
||||
const multer = require('multer');
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
adminApp.post("/nodes",needsPermission("nodes.write"),upload.single("tarball"),nodes.post,apiUtil.errorHandler);
|
||||
} else {
|
||||
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler);
|
||||
}
|
||||
}
|
||||
adminApp.get(/^\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler);
|
||||
adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler);
|
||||
@ -78,6 +82,10 @@ module.exports = {
|
||||
|
||||
adminApp.get("/settings",needsPermission("settings.read"),info.runtimeSettings,apiUtil.errorHandler);
|
||||
|
||||
// Plugins
|
||||
adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler);
|
||||
adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler);
|
||||
|
||||
return adminApp;
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ module.exports = {
|
||||
runtimeAPI.nodes.addModule(opts).then(function(info) {
|
||||
res.json(info);
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
46
packages/node_modules/@node-red/editor-api/lib/admin/plugins.js
vendored
Normal file
46
packages/node_modules/@node-red/editor-api/lib/admin/plugins.js
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
var apiUtils = require("../util");
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
getAll: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (req.get("accept") == "application/json") {
|
||||
runtimeAPI.plugins.getPluginList(opts).then(function(list) {
|
||||
res.json(list);
|
||||
})
|
||||
} else {
|
||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||
if (/[^a-z\-\*]/i.test(opts.lang)) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
runtimeAPI.plugins.getPluginConfigs(opts).then(function(configs) {
|
||||
res.send(configs);
|
||||
})
|
||||
}
|
||||
},
|
||||
getCatalogs: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
lang: req.query.lng,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (/[^a-z\-\*]/i.test(opts.lang)) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
runtimeAPI.plugins.getPluginCatalogs(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
};
|
@ -76,7 +76,7 @@ module.exports = {
|
||||
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
||||
|
||||
var theme = require("./theme");
|
||||
theme.init(settings);
|
||||
theme.init(settings, runtimeAPI);
|
||||
editorApp.use("/theme",theme.app());
|
||||
editorApp.use("/",ui.editorResources);
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
var apiUtils = require("../util");
|
||||
var fs = require('fs');
|
||||
var fspath = require('path');
|
||||
var when = require('when');
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
|
@ -39,9 +39,12 @@ module.exports = {
|
||||
},
|
||||
get: function(req,res) {
|
||||
var namespace = req.params[0];
|
||||
var lngs = req.query.lng;
|
||||
namespace = namespace.replace(/\.json$/,"");
|
||||
var lang = req.query.lng || i18n.defaultLang; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
|
||||
if (/[^a-z\-\*]/i.test(lang)) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
var prevLang = i18n.i.language;
|
||||
// Trigger a load from disk of the language if it is not the default
|
||||
i18n.i.changeLanguage(lang, function(){
|
||||
|
@ -41,6 +41,10 @@ var theme = null;
|
||||
var themeContext = clone(defaultContext);
|
||||
var themeSettings = null;
|
||||
|
||||
var activeTheme = null;
|
||||
var activeThemeInitialised = false;
|
||||
|
||||
var runtimeAPI;
|
||||
var themeApp;
|
||||
|
||||
function serveFile(app,baseUrl,file) {
|
||||
@ -58,7 +62,7 @@ function serveFile(app,baseUrl,file) {
|
||||
}
|
||||
}
|
||||
|
||||
function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
|
||||
var result = [];
|
||||
if (themeValue) {
|
||||
var array = themeValue;
|
||||
@ -67,7 +71,14 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
}
|
||||
|
||||
for (var i=0;i<array.length;i++) {
|
||||
var url = serveFile(themeApp,directory,array[i]);
|
||||
let fullPath = array[i];
|
||||
if (baseDirectory) {
|
||||
fullPath = path.resolve(baseDirectory,array[i]);
|
||||
if (fullPath.indexOf(baseDirectory) !== 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var url = serveFile(themeApp,directory,fullPath);
|
||||
if (url) {
|
||||
result.push(url);
|
||||
}
|
||||
@ -77,10 +88,12 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(settings) {
|
||||
init: function(settings, _runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
themeContext = clone(defaultContext);
|
||||
themeSettings = null;
|
||||
theme = settings.editorTheme || {};
|
||||
activeTheme = theme.theme;
|
||||
},
|
||||
|
||||
app: function() {
|
||||
@ -169,7 +182,9 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
}
|
||||
themeApp.get("/", function(req,res) {
|
||||
themeApp.get("/", async function(req,res) {
|
||||
const themePluginList = await runtimeAPI.plugins.getPluginsByType({type:"node-red-theme"});
|
||||
themeContext.themes = themePluginList.map(theme => theme.id);
|
||||
res.json(themeContext);
|
||||
})
|
||||
|
||||
@ -185,10 +200,38 @@ module.exports = {
|
||||
themeSettings.projects = theme.projects;
|
||||
}
|
||||
|
||||
|
||||
if (theme.theme) {
|
||||
themeSettings.theme = theme.theme;
|
||||
}
|
||||
return themeApp;
|
||||
},
|
||||
context: function() {
|
||||
context: async function() {
|
||||
if (activeTheme && !activeThemeInitialised) {
|
||||
const themePlugin = await runtimeAPI.plugins.getPlugin({
|
||||
id:activeTheme
|
||||
});
|
||||
if (themePlugin) {
|
||||
if (themePlugin.css) {
|
||||
const cssFiles = serveFilesFromTheme(
|
||||
themePlugin.css,
|
||||
themeApp,
|
||||
"/css/",
|
||||
themePlugin.path
|
||||
);
|
||||
themeContext.page.css = cssFiles.concat(themeContext.page.css || [])
|
||||
}
|
||||
if (themePlugin.scripts) {
|
||||
const scriptFiles = serveFilesFromTheme(
|
||||
themePlugin.scripts,
|
||||
themeApp,
|
||||
"/scripts/",
|
||||
themePlugin.path
|
||||
)
|
||||
themeContext.page.scripts = scriptFiles.concat(themeContext.page.scripts || [])
|
||||
}
|
||||
}
|
||||
activeThemeInitialised = true;
|
||||
}
|
||||
return themeContext;
|
||||
},
|
||||
settings: function() {
|
||||
|
@ -68,8 +68,8 @@ module.exports = {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
editor: function(req,res) {
|
||||
res.send(Mustache.render(editorTemplate,theme.context()));
|
||||
editor: async function(req,res) {
|
||||
res.send(Mustache.render(editorTemplate,await theme.context()));
|
||||
},
|
||||
editorResources: express.static(path.join(editorClientDir,'public'))
|
||||
};
|
||||
|
@ -28,7 +28,6 @@ var express = require("express");
|
||||
var bodyParser = require("body-parser");
|
||||
var util = require('util');
|
||||
var passport = require('passport');
|
||||
var when = require('when');
|
||||
var cors = require('cors');
|
||||
|
||||
var auth = require("./auth");
|
||||
@ -60,8 +59,8 @@ function init(settings,_server,storage,runtimeAPI) {
|
||||
adminApp.use(corsHandler);
|
||||
|
||||
if (settings.httpAdminMiddleware) {
|
||||
if (typeof settings.httpAdminMiddleware === "function") {
|
||||
adminApp.use(settings.httpAdminMiddleware)
|
||||
if (typeof settings.httpAdminMiddleware === "function" || Array.isArray(settings.httpAdminMiddleware)) {
|
||||
adminApp.use(settings.httpAdminMiddleware);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,11 +110,9 @@ function init(settings,_server,storage,runtimeAPI) {
|
||||
* @return {Promise} resolves when the application is ready to handle requests
|
||||
* @memberof @node-red/editor-api
|
||||
*/
|
||||
function start() {
|
||||
async function start() {
|
||||
if (editor) {
|
||||
return editor.start();
|
||||
} else {
|
||||
return when.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,11 +121,10 @@ function start() {
|
||||
* @return {Promise} resolves when the application is stopped
|
||||
* @memberof @node-red/editor-api
|
||||
*/
|
||||
function stop() {
|
||||
async function stop() {
|
||||
if (editor) {
|
||||
editor.stop();
|
||||
}
|
||||
return when.resolve();
|
||||
}
|
||||
module.exports = {
|
||||
init: init,
|
||||
|
@ -25,14 +25,13 @@
|
||||
"express-session": "1.17.1",
|
||||
"express": "4.17.1",
|
||||
"memorystore": "1.6.4",
|
||||
"mime": "2.4.6",
|
||||
"mime": "2.4.7",
|
||||
"multer": "1.4.2",
|
||||
"mustache": "4.0.1",
|
||||
"mustache": "4.1.0",
|
||||
"oauth2orize": "1.11.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"passport": "0.4.1",
|
||||
"when": "3.7.8",
|
||||
"ws": "6.2.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@ -32,7 +32,7 @@
|
||||
"label" : {
|
||||
"view" : {
|
||||
"view" : "Ansicht",
|
||||
"grid" : "Gitter",
|
||||
"grid" : "Raster",
|
||||
"showGrid" : "Raster anzeigen",
|
||||
"snapGrid" : "Am Raster ausrichten",
|
||||
"gridSize" : "Rastergröße",
|
||||
|
@ -38,6 +38,7 @@
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"loadPlugins": "Loading Plugins",
|
||||
"loadPalette": "Loading Palette",
|
||||
"loadNodeCatalogs": "Loading Node catalogs",
|
||||
"loadNodes": "Loading Nodes __count__",
|
||||
@ -337,8 +338,21 @@
|
||||
"output": "outputs:",
|
||||
"status": "status node",
|
||||
"deleteSubflow": "delete subflow",
|
||||
"confirmDelete": "Are you sure you want to delete this subflow?",
|
||||
"info": "Description",
|
||||
"category": "Category",
|
||||
"module": "Module",
|
||||
"license": "License",
|
||||
"licenseNone": "none",
|
||||
"licenseOther": "Other",
|
||||
"type": "Node Type",
|
||||
"version": "Version",
|
||||
"versionPlaceholder": "x.y.z",
|
||||
"keys": "Keywords",
|
||||
"keysPlaceholder": "Comma-separated keywords",
|
||||
"author": "Author",
|
||||
"authorPlaceholder": "Your Name <email@example.com>",
|
||||
"desc": "Description",
|
||||
"env": {
|
||||
"restore": "Restore to subflow default",
|
||||
"remove": "Remove environment variable"
|
||||
@ -385,6 +399,7 @@
|
||||
"icon": "Icon",
|
||||
"inputType": "Input type",
|
||||
"selectType": "select types...",
|
||||
"loadCredentials": "Loading node credentials",
|
||||
"inputs" : {
|
||||
"input": "input",
|
||||
"select": "select",
|
||||
@ -419,7 +434,8 @@
|
||||
},
|
||||
"errors": {
|
||||
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it",
|
||||
"invalidProperties": "Invalid properties:"
|
||||
"invalidProperties": "Invalid properties:",
|
||||
"credentialLoadFailed": "Failed to load node credentials"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@ -1079,6 +1095,7 @@
|
||||
"editor-tab": {
|
||||
"properties": "Properties",
|
||||
"envProperties": "Environment Variables",
|
||||
"module": "Module Properties",
|
||||
"description": "Description",
|
||||
"appearance": "Appearance",
|
||||
"preview": "UI Preview",
|
||||
|
@ -243,19 +243,19 @@
|
||||
"args": "array, function",
|
||||
"desc": "Returns the one and only value in the `array` parameter that satisfies the `function` predicate (i.e. the `function` returns Boolean `true` when passed the value). Throws an exception if the number of matching values is not exactly one.\n\nThe function should be supplied in the following signature: `function(value [, index [, array]])` where value is each input of the array, index is the position of that value and the whole array is passed as the third argument"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.\n\nExample: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character. \n\nExample: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent. \n\nExample: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Decodes a Uniform Resource Locator (URL) previously created by encodeUrl. \n\nExample: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
|
@ -38,6 +38,7 @@
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"loadPlugins": "プラグインを読み込み中",
|
||||
"loadPalette": "パレットを読み込み中",
|
||||
"loadNodeCatalogs": "ノードカタログを読み込み中",
|
||||
"loadNodes": "ノードを読み込み中 __count__",
|
||||
@ -85,7 +86,7 @@
|
||||
"userSettings": "ユーザ設定",
|
||||
"nodes": "ノード",
|
||||
"displayStatus": "ノードのステータスを表示",
|
||||
"displayConfig": "ノードの設定",
|
||||
"displayConfig": "設定ノード",
|
||||
"import": "読み込み",
|
||||
"export": "書き出し",
|
||||
"search": "ノードを検索",
|
||||
@ -203,8 +204,8 @@
|
||||
"replacedNodes_plural": "置換された __count__ 個のノード",
|
||||
"pasteNodes": "JSON形式のフローデータを貼り付け",
|
||||
"selectFile": "読み込むファイルを選択",
|
||||
"importNodes": "フローをクリップボードから読み込み",
|
||||
"exportNodes": "フローをクリップボードへ書き出し",
|
||||
"importNodes": "フローを読み込み",
|
||||
"exportNodes": "フローを書き出し",
|
||||
"download": "ダウンロード",
|
||||
"importUnrecognised": "認識できない型が読み込まれました:",
|
||||
"importUnrecognised_plural": "認識できない型が読み込まれました:",
|
||||
@ -266,7 +267,7 @@
|
||||
"successfulDeploy": "デプロイが成功しました",
|
||||
"successfulRestart": "フローの再起動が成功しました",
|
||||
"deployFailed": "デプロイが失敗しました: __message__",
|
||||
"unusedConfigNodes": "使われていない「ノードの設定」があります。",
|
||||
"unusedConfigNodes": "使われていない設定ノードがあります。",
|
||||
"unusedConfigNodesLink": "設定を参照する",
|
||||
"errors": {
|
||||
"noResponse": "サーバの応答がありません"
|
||||
@ -337,8 +338,21 @@
|
||||
"output": "出力:",
|
||||
"status": "ステータスノード",
|
||||
"deleteSubflow": "サブフローを削除",
|
||||
"confirmDelete": "このサブフローを削除しても良いですか?",
|
||||
"info": "詳細",
|
||||
"category": "カテゴリ",
|
||||
"module": "モジュール",
|
||||
"license": "ライセンス",
|
||||
"licenseNone": "なし",
|
||||
"licenseOther": "その他",
|
||||
"type": "ノードの型",
|
||||
"version": "バージョン",
|
||||
"versionPlaceholder": "x.y.z",
|
||||
"keys": "キーワード",
|
||||
"keysPlaceholder": "カンマ区切りのキーワード",
|
||||
"author": "作者",
|
||||
"authorPlaceholder": "名前 <email@example.com>",
|
||||
"desc": "説明",
|
||||
"env": {
|
||||
"restore": "デフォルト値に戻す",
|
||||
"remove": "環境変数を削除"
|
||||
@ -362,9 +376,9 @@
|
||||
"configDelete": "削除",
|
||||
"nodesUse": "__count__ 個のノードが、この設定を使用しています",
|
||||
"nodesUse_plural": "__count__ 個のノードが、この設定を使用しています",
|
||||
"addNewConfig": "新規に __type__ ノードの設定を追加",
|
||||
"addNewConfig": "新規に __type__ 設定ノードを追加",
|
||||
"editNode": "__type__ ノードを編集",
|
||||
"editConfig": "__type__ ノードの設定を編集",
|
||||
"editConfig": "__type__ 設定ノードを編集",
|
||||
"addNewType": "新規に __type__ を追加...",
|
||||
"nodeProperties": "プロパティ",
|
||||
"label": "ラベル",
|
||||
@ -385,6 +399,7 @@
|
||||
"icon": "記号",
|
||||
"inputType": "入力形式",
|
||||
"selectType": "形式選択...",
|
||||
"loadCredentials": "ノードの認証情報を読み込み中",
|
||||
"inputs": {
|
||||
"input": "入力",
|
||||
"select": "メニュー",
|
||||
@ -419,7 +434,8 @@
|
||||
},
|
||||
"errors": {
|
||||
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします",
|
||||
"invalidProperties": "プロパティが不正です:"
|
||||
"invalidProperties": "プロパティが不正です:",
|
||||
"credentialLoadFailed": "ノードの認証情報の読み込みに失敗"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@ -637,8 +653,8 @@
|
||||
"noHelp": "ヘルプのトピックが未選択"
|
||||
},
|
||||
"config": {
|
||||
"name": "ノードの設定を表示",
|
||||
"label": "ノードの設定",
|
||||
"name": "設定ノードを表示",
|
||||
"label": "設定ノード",
|
||||
"global": "全てのフロー上",
|
||||
"none": "なし",
|
||||
"subflows": "サブフロー",
|
||||
@ -1079,6 +1095,7 @@
|
||||
"editor-tab": {
|
||||
"properties": "プロパティ",
|
||||
"envProperties": "環境変数",
|
||||
"module": "モジュールプロパティ",
|
||||
"description": "説明",
|
||||
"appearance": "外観",
|
||||
"preview": "UIプレビュー",
|
||||
@ -1089,6 +1106,7 @@
|
||||
"en-US": "英語",
|
||||
"ja": "日本語",
|
||||
"ko": "韓国語",
|
||||
"ru": "ロシア語",
|
||||
"zh-CN": "中国語(簡体)",
|
||||
"zh-TW": "中国語(繁体)"
|
||||
}
|
||||
|
@ -243,19 +243,19 @@
|
||||
"args": "array, function",
|
||||
"desc": "`array`の要素のうち、条件判定関数`function`を満たす(`function`に与えた場合に真偽値`true`を返す)要素が1つのみである場合、それを返します。マッチする要素が1つのみでない場合、例外を送出します。\n\n指定する関数は`function(value [, index [, array]])`というシグネチャでなければなりません。ここで、`value`は`array`の要素値、`index`は要素の添字、第三引数には配列全体を渡します。"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Uniform Resource Locator (URL)を構成する文字を1、2、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Uniform Resource Locator (URL)要素を構成する文字を1、2、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "encodeUrlComponentで置換したUniform Resource Locator (URL)をデコードします。\n\n例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "encodeUrlで置換したUniform Resource Locator (URL)要素をデコードします。 \n\n例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
|
@ -246,8 +246,8 @@
|
||||
"import": {
|
||||
"import": "Импортировать в",
|
||||
"importSelected": "Импортировать выбранные",
|
||||
"importCopy": "Импортировать копию",
|
||||
"viewNodes": "Посмотреть узлы...",
|
||||
"importCopy": "Импортировать копии",
|
||||
"viewNodes": "Показать узлы...",
|
||||
"newFlow": "новый поток",
|
||||
"replace": "заменить",
|
||||
"errors": {
|
||||
@ -257,7 +257,7 @@
|
||||
"missingType": "Недопустимый поток - у элемента __index__ отсутствует свойство 'type'"
|
||||
},
|
||||
"conflictNotification1": "Некоторые импортируемые Вами узлы уже существуют в рабочей области.",
|
||||
"conflictNotification2": "Выберите, какие узлы импортировать и следует ли заменить существующие узлы или импортировать их копию."
|
||||
"conflictNotification2": "Выберите, какие узлы импортировать и следует ли заменить ими существующие узлы или импортировать их копии."
|
||||
},
|
||||
"copyMessagePath": "Путь скопирован",
|
||||
"copyMessageValue": "Значение скопировано",
|
||||
@ -373,12 +373,12 @@
|
||||
"configAdd": "Добавить",
|
||||
"configUpdate": "Обновить",
|
||||
"configDelete": "Удалить",
|
||||
"nodesUse": "__count__ узел использует эту конфигурацию",
|
||||
"nodesUse_plural_2": "__count__ узла используют эту конфигурацию",
|
||||
"nodesUse_plural_5": "__count__ узлов используют эту конфигурацию",
|
||||
"addNewConfig": "Добавить новый конфигурационный узел __type__",
|
||||
"nodesUse": "__count__ узел использует этот конфиг",
|
||||
"nodesUse_plural_2": "__count__ узла используют этот конфиг",
|
||||
"nodesUse_plural_5": "__count__ узлов используют этот конфиг",
|
||||
"addNewConfig": "Добавить новый конфиг узел __type__",
|
||||
"editNode": "Изменить узел __type__",
|
||||
"editConfig": "Изменить конфигурационный узел __type__",
|
||||
"editConfig": "Изменить конфиг узел __type__",
|
||||
"addNewType": "Добавить новый __type__...",
|
||||
"nodeProperties": "свойства узла",
|
||||
"label": "Метка",
|
||||
@ -615,7 +615,7 @@
|
||||
"info": {
|
||||
"name": "Информация",
|
||||
"tabName": "Имя",
|
||||
"label": "сведения",
|
||||
"label": "инфо",
|
||||
"node": "Узел",
|
||||
"type": "Тип",
|
||||
"group": "Группа",
|
||||
@ -648,8 +648,8 @@
|
||||
"showTips":"Вы можете открыть советы из панели настроек",
|
||||
"outline": "Структура",
|
||||
"empty": "пусто",
|
||||
"globalConfig": "Узлы глобальной конфигурации",
|
||||
"triggerAction": "Запустить действие",
|
||||
"globalConfig": "Глобальные конфиг узлы",
|
||||
"triggerAction": "Вызвать действие",
|
||||
"find": "Найти в рабочей области",
|
||||
"search": {
|
||||
"configNodes": "Узлы конфигурации",
|
||||
@ -671,8 +671,8 @@
|
||||
},
|
||||
"config": {
|
||||
"name": "Узлы конфигураций",
|
||||
"label": "конфигурация",
|
||||
"global": "На всех потока",
|
||||
"label": "конфиг",
|
||||
"global": "На всех потоках",
|
||||
"none": "нет",
|
||||
"subflows": "подпотоки",
|
||||
"flows": "потоки",
|
||||
@ -690,8 +690,8 @@
|
||||
"none": "ничего не выбрано",
|
||||
"refresh": "обновите, чтобы загрузить",
|
||||
"empty": "пусто",
|
||||
"node": "Узел",
|
||||
"flow": "Поток",
|
||||
"node": "Узловой",
|
||||
"flow": "Потоковый",
|
||||
"global": "Глобальный",
|
||||
"deleteConfirm": "Вы уверены, что хотите удалить этот элемент?",
|
||||
"autoRefresh": "Обновить при изменении выбора",
|
||||
@ -877,7 +877,7 @@
|
||||
"bool": "логический тип",
|
||||
"json": "JSON",
|
||||
"bin": "буфер",
|
||||
"date": "отметка времени",
|
||||
"date": "метка времени",
|
||||
"jsonata": "выражение",
|
||||
"env": "переменная среды",
|
||||
"cred": "учетные данные"
|
||||
|
@ -243,19 +243,19 @@
|
||||
"args": "array, function",
|
||||
"desc": "Возвращает одно-единственное значение из массива `array`, которое удовлетворяет предикату `function` (то есть когда `function` возвращает логическое `true` при передаче значения). Выдает исключение, если число подходящих значений не одно.\n\nФункция должна соответствовать следующей сигнатуре: `function(value [, index [, array]])` где value - элемент массива, index - позиция этого значения, а весь массив передается в качестве третьего аргумента"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Кодирует компонент Uniform Resource Locator (URL), заменяя каждый экземпляр определенных символов одной, двумя, тремя или четырьмя escape-последовательностями, представляющими кодировку UTF-8 символа.\n\nПример: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Кодирует Uniform Resource Locator (URL), заменяя каждый экземпляр определенных символов одной, двумя, тремя или четырьмя escape-последовательностями, представляющими кодировку UTF-8 символа.\n\nПример: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Декодирует компонент Uniform Resource Locator (URL), ранее созданный с помощью encodeUrlComponent.\n\nПример: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Декодирует компонент Uniform Resource Locator (URL), ранее созданный с помощью encodeUrl. \n\nПример: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
|
@ -243,19 +243,19 @@
|
||||
"args": "array, function",
|
||||
"desc": "返回满足参数function谓语的array参数中的唯一值 (比如:传递值时,函数返回布尔值“true”)。如果匹配值的数量不唯一时,则抛出异常。\n\n应在以下签名中提供函数: `function(value [,index [,array []]])` 其中value是数组的每个输入,index是该值的位置,整个数组作为第三个参数传递。"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "通过用表示字符的UTF-8编码的一个,两个,三个或四个转义序列替换某些字符的每个实例,对统一资源定位符(URL)组件进行编码。\n\n示例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "通过用表示字符的UTF-8编码的一个,两个,三个或四个转义序列替换某些字符的每个实例,对统一资源定位符(URL)进行编码。\n\n示例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "解码以前由encodeUrlComponent创建的统一资源定位器(URL)组件。 \n\n示例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "解码先前由encodeUrl创建的统一资源定位符(URL)。 \n\n示例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
|
@ -243,19 +243,19 @@
|
||||
"args": "array, function",
|
||||
"desc": "返回滿足參數function謂語的array參數中的唯一值 (比如:傳遞值時,函數返回布林值“true”)。如果匹配值的數量不唯一時,則拋出異常。\n\n應在以下簽名中提供函數:`function(value [,index [,array []]])`其中value是數組的每個輸入,index是該值的位置,整個數組作為第三個參數傳遞。"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "通過用表示字符的UTF-8編碼的一個,兩個,三個或四個轉義序列替換某些字符的每個實例,對統一資源定位符(URL)組件進行編碼。\n\n示例:`$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "通過用表示字符的UTF-8編碼的一個,兩個,三個或四個轉義序列替換某些字符的每個實例,對統一資源定位符(URL)進行編碼。\n\n示例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "解碼以前由encodeUrlComponent創建的統一資源定位器(URL)組件。 \n\n示例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "解碼先前由encodeUrl創建的統一資源定位符(URL)。 \n\n示例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
|
@ -343,17 +343,29 @@ RED.history = (function() {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
inverseEv.changes[i] = ev.node[i];
|
||||
if (ev.node._def.defaults && ev.node._def.defaults[i] && ev.node._def.defaults[i].type) {
|
||||
// This is a config node property
|
||||
var currentConfigNode = RED.nodes.node(ev.node[i]);
|
||||
if (currentConfigNode) {
|
||||
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
|
||||
RED.events.emit("nodes:change",currentConfigNode);
|
||||
// This property is a reference to another node or nodes.
|
||||
var nodeList = ev.node[i];
|
||||
if (!Array.isArray(nodeList)) {
|
||||
nodeList = [nodeList];
|
||||
}
|
||||
var newConfigNode = RED.nodes.node(ev.changes[i]);
|
||||
if (newConfigNode) {
|
||||
newConfigNode.users.push(ev.node);
|
||||
RED.events.emit("nodes:change",newConfigNode);
|
||||
nodeList.forEach(function(id) {
|
||||
var currentConfigNode = RED.nodes.node(id);
|
||||
if (currentConfigNode && currentConfigNode._def.category === "config") {
|
||||
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
|
||||
RED.events.emit("nodes:change",currentConfigNode);
|
||||
}
|
||||
});
|
||||
nodeList = ev.changes[i];
|
||||
if (!Array.isArray(nodeList)) {
|
||||
nodeList = [nodeList];
|
||||
}
|
||||
nodeList.forEach(function(id) {
|
||||
var newConfigNode = RED.nodes.node(id);
|
||||
if (newConfigNode && newConfigNode._def.category === "config") {
|
||||
newConfigNode.users.push(ev.node);
|
||||
RED.events.emit("nodes:change",newConfigNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
ev.node[i] = ev.changes[i];
|
||||
}
|
||||
|
@ -108,6 +108,31 @@ RED.i18n = (function() {
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
loadPluginCatalogs: function(done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var toLoad = languageList.length;
|
||||
|
||||
languageList.forEach(function(lang) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: apiRootUrl+'plugins/messages?lng='+lang,
|
||||
success: function(data) {
|
||||
var namespaces = Object.keys(data);
|
||||
namespaces.forEach(function(ns) {
|
||||
i18n.addResourceBundle(lang,ns,data[ns]);
|
||||
});
|
||||
toLoad--;
|
||||
if (toLoad === 0) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -164,6 +164,21 @@ RED.nodes = (function() {
|
||||
|
||||
// TODO: too tightly coupled into palette UI
|
||||
}
|
||||
if (def.defaults) {
|
||||
for (var d in def.defaults) {
|
||||
if (def.defaults.hasOwnProperty(d)) {
|
||||
if (def.defaults[d].type) {
|
||||
try {
|
||||
def.defaults[d]._type = parseNodePropertyTypeString(def.defaults[d].type)
|
||||
} catch(err) {
|
||||
console.warn(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RED.events.emit("registry:node-type-added",nt);
|
||||
},
|
||||
removeNodeType: function(nt) {
|
||||
@ -193,6 +208,59 @@ RED.nodes = (function() {
|
||||
return (1+Math.random()*4294967295).toString(16);
|
||||
}
|
||||
|
||||
function parseNodePropertyTypeString(typeString) {
|
||||
typeString = typeString.trim();
|
||||
var c;
|
||||
var pos = 0;
|
||||
var isArray = /\[\]$/.test(typeString);
|
||||
if (isArray) {
|
||||
typeString = typeString.substring(0,typeString.length-2);
|
||||
}
|
||||
|
||||
var l = typeString.length;
|
||||
var inBrackets = false;
|
||||
var inToken = false;
|
||||
var currentToken = "";
|
||||
var types = [];
|
||||
while (pos < l) {
|
||||
c = typeString[pos];
|
||||
if (inToken) {
|
||||
if (c === "|") {
|
||||
types.push(currentToken.trim())
|
||||
currentToken = "";
|
||||
inToken = false;
|
||||
} else if (c === ")") {
|
||||
types.push(currentToken.trim())
|
||||
currentToken = "";
|
||||
inBrackets = false;
|
||||
inToken = false;
|
||||
} else {
|
||||
currentToken += c;
|
||||
}
|
||||
} else {
|
||||
if (c === "(") {
|
||||
if (inBrackets) {
|
||||
throw new Error("Invalid character '"+c+"' at position "+pos)
|
||||
}
|
||||
inBrackets = true;
|
||||
} else if (c !== " ") {
|
||||
inToken = true;
|
||||
currentToken = c;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
currentToken = currentToken.trim();
|
||||
if (currentToken.length > 0) {
|
||||
types.push(currentToken)
|
||||
}
|
||||
return {
|
||||
types: types,
|
||||
array: isArray
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function addNode(n) {
|
||||
if (n.type.indexOf("subflow") !== 0) {
|
||||
n["_"] = n._def._;
|
||||
@ -670,6 +738,7 @@ RED.nodes = (function() {
|
||||
node.in = [];
|
||||
node.out = [];
|
||||
node.env = n.env;
|
||||
node.meta = n.meta;
|
||||
|
||||
if (exportCreds) {
|
||||
var credentialSet = {};
|
||||
@ -780,6 +849,12 @@ RED.nodes = (function() {
|
||||
subflowSet.push(n);
|
||||
}
|
||||
});
|
||||
RED.nodes.eachConfig(function(n) {
|
||||
if (n.z == subflowId) {
|
||||
subflowSet.push(n);
|
||||
exportedConfigNodes[n.id] = true;
|
||||
}
|
||||
});
|
||||
var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes);
|
||||
nns = exportableSubflow.concat(nns);
|
||||
}
|
||||
@ -787,16 +862,29 @@ RED.nodes = (function() {
|
||||
if (node.type !== "subflow") {
|
||||
var convertedNode = RED.nodes.convertNode(node);
|
||||
for (var d in node._def.defaults) {
|
||||
if (node._def.defaults[d].type && node[d] in configNodes) {
|
||||
var confNode = configNodes[node[d]];
|
||||
var exportable = registry.getNodeType(node._def.defaults[d].type).exportable;
|
||||
if ((exportable == null || exportable)) {
|
||||
if (!(node[d] in exportedConfigNodes)) {
|
||||
exportedConfigNodes[node[d]] = true;
|
||||
set.push(confNode);
|
||||
if (node._def.defaults[d].type) {
|
||||
var nodeList = node[d];
|
||||
if (!Array.isArray(nodeList)) {
|
||||
nodeList = [nodeList];
|
||||
}
|
||||
nodeList = nodeList.filter(function(id) {
|
||||
if (id in configNodes) {
|
||||
var confNode = configNodes[id];
|
||||
if (confNode._def.exportable !== false) {
|
||||
if (!(id in exportedConfigNodes)) {
|
||||
exportedConfigNodes[id] = true;
|
||||
set.push(confNode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
if (nodeList.length === 0) {
|
||||
convertedNode[d] = Array.isArray(node[d])?[]:""
|
||||
} else {
|
||||
convertedNode[d] = "";
|
||||
convertedNode[d] = Array.isArray(node[d])?nodeList:nodeList[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1360,7 +1448,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (n.z && !workspaces[n.z]) {
|
||||
if (n.z && !workspaces[n.z] && !subflow_map[n.z]) {
|
||||
n.z = activeWorkspace;
|
||||
}
|
||||
}
|
||||
@ -1587,15 +1675,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: make this a part of the node definition so it doesn't have to
|
||||
// be hardcoded here
|
||||
var nodeTypeArrayReferences = {
|
||||
"catch":"scope",
|
||||
"status":"scope",
|
||||
"complete": "scope",
|
||||
"link in":"links",
|
||||
"link out":"links"
|
||||
}
|
||||
|
||||
// Remap all wires and config node references
|
||||
for (i=0;i<new_nodes.length;i++) {
|
||||
@ -1624,19 +1703,24 @@ RED.nodes = (function() {
|
||||
}
|
||||
for (var d3 in n._def.defaults) {
|
||||
if (n._def.defaults.hasOwnProperty(d3)) {
|
||||
if (n._def.defaults[d3].type && node_map[n[d3]]) {
|
||||
configNode = node_map[n[d3]];
|
||||
n[d3] = configNode.id;
|
||||
if (configNode.users.indexOf(n) === -1) {
|
||||
configNode.users.push(n);
|
||||
if (n._def.defaults[d3].type) {
|
||||
var nodeList = n[d3];
|
||||
if (!Array.isArray(nodeList)) {
|
||||
nodeList = [nodeList];
|
||||
}
|
||||
} else if (nodeTypeArrayReferences.hasOwnProperty(n.type) && nodeTypeArrayReferences[n.type] === d3 && n[d3] !== undefined && n[d3] !== null) {
|
||||
for (var j = 0;j<n[d3].length;j++) {
|
||||
if (node_map[n[d3][j]]) {
|
||||
n[d3][j] = node_map[n[d3][j]].id;
|
||||
nodeList = nodeList.map(function(id) {
|
||||
var node = node_map[id];
|
||||
if (node) {
|
||||
if (node._def.category === 'config') {
|
||||
if (node.users.indexOf(n) === -1) {
|
||||
node.users.push(n);
|
||||
}
|
||||
}
|
||||
return node.id;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
})
|
||||
n[d3] = Array.isArray(n[d3])?nodeList:nodeList[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1920,6 +2004,18 @@ RED.nodes = (function() {
|
||||
RED.events.emit("groups:remove",group);
|
||||
}
|
||||
|
||||
function getNodeHelp(type) {
|
||||
var helpContent = "";
|
||||
var helpElement = $("script[data-help-name='"+type+"']");
|
||||
if (helpElement) {
|
||||
helpContent = helpElement.html();
|
||||
var helpType = helpElement.attr("type");
|
||||
if (helpType === "text/markdown") {
|
||||
helpContent = RED.utils.renderMarkdown(helpContent);
|
||||
}
|
||||
}
|
||||
return helpContent;
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
@ -1999,6 +2095,7 @@ RED.nodes = (function() {
|
||||
|
||||
registerType: registry.registerNodeType,
|
||||
getType: registry.getNodeType,
|
||||
getNodeHelp: getNodeHelp,
|
||||
convertNode: convertNode,
|
||||
|
||||
add: addNode,
|
||||
|
46
packages/node_modules/@node-red/editor-client/src/js/plugins.js
vendored
Normal file
46
packages/node_modules/@node-red/editor-client/src/js/plugins.js
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
RED.plugins = (function() {
|
||||
var plugins = {};
|
||||
var pluginsByType = {};
|
||||
|
||||
function registerPlugin(id,definition) {
|
||||
plugins[id] = definition;
|
||||
if (definition.type) {
|
||||
pluginsByType[definition.type] = pluginsByType[definition.type] || [];
|
||||
pluginsByType[definition.type].push(definition);
|
||||
}
|
||||
if (RED._loadingModule) {
|
||||
definition.module = RED._loadingModule;
|
||||
definition["_"] = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var originalKey = args[0];
|
||||
if (!/:/.test(args[0])) {
|
||||
args[0] = definition.module+":"+args[0];
|
||||
}
|
||||
var result = RED._.apply(null,args);
|
||||
if (result === args[0]) {
|
||||
return originalKey;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
definition["_"] = RED["_"]
|
||||
}
|
||||
if (definition.onadd && typeof definition.onadd === 'function') {
|
||||
definition.onadd();
|
||||
}
|
||||
RED.events.emit("registry:plugin-added",id);
|
||||
}
|
||||
|
||||
function getPlugin(id) {
|
||||
return plugins[id]
|
||||
}
|
||||
|
||||
function getPluginsByType(type) {
|
||||
return pluginsByType[type] || [];
|
||||
}
|
||||
return {
|
||||
registerPlugin: registerPlugin,
|
||||
getPlugin: getPlugin,
|
||||
getPluginsByType: getPluginsByType
|
||||
}
|
||||
})();
|
@ -52,6 +52,5 @@
|
||||
Set.prototype = _Set.prototype;
|
||||
Set.prototype.constructor = Set;
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -15,19 +15,65 @@
|
||||
**/
|
||||
var RED = (function() {
|
||||
|
||||
function appendNodeConfig(nodeConfig,done) {
|
||||
|
||||
function loadPluginList() {
|
||||
loader.reportProgress(RED._("event.loadPlugins"), 10)
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: 'plugins',
|
||||
success: function(data) {
|
||||
loader.reportProgress(RED._("event.loadPlugins"), 13)
|
||||
RED.i18n.loadPluginCatalogs(function() {
|
||||
loadPlugins(function() {
|
||||
loadNodeList();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function loadPlugins(done) {
|
||||
loader.reportProgress(RED._("event.loadPlugins",{count:""}), 17)
|
||||
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
|
||||
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"text/html",
|
||||
"Accept-Language": lang
|
||||
},
|
||||
cache: false,
|
||||
url: 'plugins',
|
||||
success: function(data) {
|
||||
var configs = data.trim().split(/(?=<!-- --- \[red-plugin:\S+\] --- -->)/);
|
||||
var totalCount = configs.length;
|
||||
var stepConfig = function() {
|
||||
// loader.reportProgress(RED._("event.loadNodes",{count:(totalCount-configs.length)+"/"+totalCount}), 30 + ((totalCount-configs.length)/totalCount)*40 )
|
||||
if (configs.length === 0) {
|
||||
done();
|
||||
} else {
|
||||
var config = configs.shift();
|
||||
appendPluginConfig(config,stepConfig);
|
||||
}
|
||||
}
|
||||
stepConfig();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function appendConfig(config, moduleIdMatch, targetContainer, done) {
|
||||
done = done || function(){};
|
||||
var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim());
|
||||
var moduleId;
|
||||
if (m) {
|
||||
moduleId = m[1];
|
||||
if (moduleIdMatch) {
|
||||
moduleId = moduleIdMatch[1];
|
||||
RED._loadingModule = moduleId;
|
||||
} else {
|
||||
moduleId = "unknown";
|
||||
}
|
||||
try {
|
||||
var hasDeferred = false;
|
||||
|
||||
var nodeConfigEls = $("<div>"+nodeConfig+"</div>");
|
||||
var nodeConfigEls = $("<div>"+config+"</div>");
|
||||
var scripts = nodeConfigEls.find("script");
|
||||
var scriptCount = scripts.length;
|
||||
scripts.each(function(i,el) {
|
||||
@ -38,14 +84,15 @@ var RED = (function() {
|
||||
newScript.onload = function() {
|
||||
scriptCount--;
|
||||
if (scriptCount === 0) {
|
||||
$("#red-ui-editor-node-configs").append(nodeConfigEls);
|
||||
$(targetContainer).append(nodeConfigEls);
|
||||
delete RED._loadingModule;
|
||||
done()
|
||||
}
|
||||
}
|
||||
if ($(el).attr('type') === "module") {
|
||||
newScript.type = "module";
|
||||
}
|
||||
$("#red-ui-editor-node-configs").append(newScript);
|
||||
$(targetContainer).append(newScript);
|
||||
newScript.src = RED.settings.apiRootUrl+srcUrl;
|
||||
hasDeferred = true;
|
||||
} else {
|
||||
@ -61,7 +108,8 @@ var RED = (function() {
|
||||
}
|
||||
})
|
||||
if (!hasDeferred) {
|
||||
$("#red-ui-editor-node-configs").append(nodeConfigEls);
|
||||
$(targetContainer).append(nodeConfigEls);
|
||||
delete RED._loadingModule;
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
@ -70,9 +118,27 @@ var RED = (function() {
|
||||
timeout: 10000
|
||||
});
|
||||
console.log("["+moduleId+"] "+err.toString());
|
||||
delete RED._loadingModule;
|
||||
done();
|
||||
}
|
||||
}
|
||||
function appendPluginConfig(pluginConfig,done) {
|
||||
appendConfig(
|
||||
pluginConfig,
|
||||
/<!-- --- \[red-plugin:(\S+)\] --- -->/.exec(pluginConfig.trim()),
|
||||
"#red-ui-editor-plugin-configs",
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
function appendNodeConfig(nodeConfig,done) {
|
||||
appendConfig(
|
||||
nodeConfig,
|
||||
/<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim()),
|
||||
"#red-ui-editor-node-configs",
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
function loadNodeList() {
|
||||
loader.reportProgress(RED._("event.loadPalette"), 20)
|
||||
@ -186,6 +252,7 @@ var RED = (function() {
|
||||
RED.workspaces.show(currentHash.substring(6));
|
||||
}
|
||||
} catch(err) {
|
||||
console.warn(err);
|
||||
RED.notify(
|
||||
RED._("event.importError", {message: err.message}),
|
||||
{
|
||||
@ -269,7 +336,7 @@ var RED = (function() {
|
||||
}
|
||||
}
|
||||
]
|
||||
// } else if (RED.settings.theme('palette.editable') !== false) {
|
||||
// } else if (RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
} else {
|
||||
options.buttons = [
|
||||
{
|
||||
@ -509,7 +576,7 @@ var RED = (function() {
|
||||
]});
|
||||
|
||||
menuOptions.push(null);
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
|
||||
menuOptions.push(null);
|
||||
}
|
||||
@ -544,7 +611,7 @@ var RED = (function() {
|
||||
RED.palette.init();
|
||||
RED.eventLog.init();
|
||||
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
RED.palette.editor.init();
|
||||
} else {
|
||||
console.log("Palette editor disabled");
|
||||
@ -579,7 +646,7 @@ var RED = (function() {
|
||||
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
|
||||
loadNodeList();
|
||||
loadPluginList();
|
||||
}
|
||||
|
||||
|
||||
@ -595,6 +662,7 @@ var RED = (function() {
|
||||
'<div id="red-ui-sidebar"></div>'+
|
||||
'<div id="red-ui-sidebar-separator"></div>'+
|
||||
'</div>').appendTo(options.target);
|
||||
$('<div id="red-ui-editor-plugin-configs"></div>').appendTo(options.target);
|
||||
$('<div id="red-ui-editor-node-configs"></div>').appendTo(options.target);
|
||||
$('<div id="red-ui-full-shade" class="hide"></div>').appendTo(options.target);
|
||||
|
||||
@ -613,9 +681,12 @@ var RED = (function() {
|
||||
$('<span>').html(theme.header.title).appendTo(logo);
|
||||
}
|
||||
}
|
||||
if (theme.themes) {
|
||||
knownThemes = theme.themes;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var knownThemes = null;
|
||||
var initialised = false;
|
||||
|
||||
function init(options) {
|
||||
@ -635,7 +706,13 @@ var RED = (function() {
|
||||
buildEditor(options);
|
||||
|
||||
RED.i18n.init(options, function() {
|
||||
RED.settings.init(options, loadEditor);
|
||||
RED.settings.init(options, function() {
|
||||
if (knownThemes) {
|
||||
RED.settings.editorTheme = RED.settings.editorTheme || {};
|
||||
RED.settings.editorTheme.themes = knownThemes;
|
||||
}
|
||||
loadEditor();
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -57,12 +57,11 @@ RED.settings = (function () {
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
} else {
|
||||
var v;
|
||||
try {
|
||||
v = RED.utils.getMessageProperty(userSettings,key);
|
||||
if (v === undefined) {
|
||||
v = defaultIfUndefined;
|
||||
}
|
||||
} catch(err) {
|
||||
try { v = RED.utils.getMessageProperty(userSettings,key); } catch(err) {}
|
||||
if (v === undefined) {
|
||||
try { v = RED.utils.getMessageProperty(RED.settings,key); } catch(err) {}
|
||||
}
|
||||
if (v === undefined) {
|
||||
v = defaultIfUndefined;
|
||||
}
|
||||
return v;
|
||||
|
@ -30,6 +30,27 @@ RED.clipboard = (function() {
|
||||
|
||||
var pendingImportConfig;
|
||||
|
||||
|
||||
function downloadData(file, data) {
|
||||
if (window.navigator.msSaveBlob) {
|
||||
// IE11 workaround
|
||||
// IE does not support data uri scheme for downloading data
|
||||
var blob = new Blob([data], {
|
||||
type: "data:text/plain;charset=utf-8"
|
||||
});
|
||||
navigator.msSaveBlob(blob, file);
|
||||
}
|
||||
else {
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data));
|
||||
element.setAttribute('download', file);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
function setupDialogs() {
|
||||
dialog = $('<div id="red-ui-clipboard-dialog" class="hide"><form class="dialog-form form-horizontal"></form></div>')
|
||||
.appendTo("#red-ui-editor")
|
||||
@ -56,13 +77,8 @@ RED.clipboard = (function() {
|
||||
class: "primary",
|
||||
text: RED._("clipboard.download"),
|
||||
click: function() {
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent($("#red-ui-clipboard-dialog-export-text").val()));
|
||||
element.setAttribute('download', "flows.json");
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
var data = $("#red-ui-clipboard-dialog-export-text").val();
|
||||
downloadData("flows.json", data);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
@ -72,9 +88,7 @@ RED.clipboard = (function() {
|
||||
text: RED._("clipboard.export.copy"),
|
||||
click: function() {
|
||||
if (activeTab === "red-ui-clipboard-dialog-export-tab-clipboard") {
|
||||
$("#red-ui-clipboard-dialog-export-text").select();
|
||||
document.execCommand("copy");
|
||||
document.getSelection().removeAllRanges();
|
||||
copyText($("#red-ui-clipboard-dialog-export-text").val());
|
||||
RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"});
|
||||
$( this ).dialog( "close" );
|
||||
} else {
|
||||
@ -222,14 +236,22 @@ RED.clipboard = (function() {
|
||||
'</div>'+
|
||||
'<div id="red-ui-clipboard-dialog-export-tabs-content" class="red-ui-clipboard-dialog-tabs-content">'+
|
||||
'<div id="red-ui-clipboard-dialog-export-tab-clipboard" class="red-ui-clipboard-dialog-tab-clipboard">'+
|
||||
'<div class="form-row" style="height:calc(100% - 30px)">'+
|
||||
'<textarea readonly id="red-ui-clipboard-dialog-export-text"></textarea>'+
|
||||
'<div id="red-ui-clipboard-dialog-export-tab-clipboard-tab-bar">'+
|
||||
'<ul id="red-ui-clipboard-dialog-export-tab-clipboard-tabs"></ul>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" style="text-align: right;">'+
|
||||
'<span id="red-ui-clipboard-dialog-export-fmt-group" class="button-group">'+
|
||||
'<a id="red-ui-clipboard-dialog-export-fmt-mini" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
||||
'<a id="red-ui-clipboard-dialog-export-fmt-full" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
||||
'</span>'+
|
||||
'<div class="red-ui-clipboard-dialog-export-tab-clipboard-tab" id="red-ui-clipboard-dialog-export-tab-clipboard-preview">'+
|
||||
'<div id="red-ui-clipboard-dialog-export-tab-clipboard-preview-list"></div>'+
|
||||
'</div>'+
|
||||
'<div class="red-ui-clipboard-dialog-export-tab-clipboard-tab" id="red-ui-clipboard-dialog-export-tab-clipboard-json">'+
|
||||
'<div class="form-row" style="height:calc(100% - 40px)">'+
|
||||
'<textarea readonly id="red-ui-clipboard-dialog-export-text"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" style="text-align: right;">'+
|
||||
'<span id="red-ui-clipboard-dialog-export-fmt-group" class="button-group">'+
|
||||
'<a id="red-ui-clipboard-dialog-export-fmt-mini" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
||||
'<a id="red-ui-clipboard-dialog-export-fmt-full" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'<div id="red-ui-clipboard-dialog-export-tab-library" class="red-ui-clipboard-dialog-tab-library">'+
|
||||
@ -592,6 +614,30 @@ RED.clipboard = (function() {
|
||||
})
|
||||
loadFlowLibrary(libraryBrowser,"local",RED._("library.types.local"));
|
||||
|
||||
var clipboardTabs = RED.tabs.create({
|
||||
id: "red-ui-clipboard-dialog-export-tab-clipboard-tabs",
|
||||
onchange: function(tab) {
|
||||
$(".red-ui-clipboard-dialog-export-tab-clipboard-tab").hide();
|
||||
$("#" + tab.id).show();
|
||||
}
|
||||
});
|
||||
|
||||
clipboardTabs.addTab({
|
||||
id: "red-ui-clipboard-dialog-export-tab-clipboard-preview",
|
||||
label: RED._("clipboard.exportNodes")
|
||||
});
|
||||
|
||||
clipboardTabs.addTab({
|
||||
id: "red-ui-clipboard-dialog-export-tab-clipboard-json",
|
||||
label: RED._("editor.types.json")
|
||||
});
|
||||
|
||||
|
||||
var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({
|
||||
data: []
|
||||
})
|
||||
refreshExportPreview();
|
||||
|
||||
$("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select();
|
||||
|
||||
dialogContainer.i18n();
|
||||
@ -630,10 +676,10 @@ RED.clipboard = (function() {
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
var type = $(this).attr('id');
|
||||
var type = $(this).attr('id').substring("red-ui-clipboard-dialog-export-rng-".length);
|
||||
var flow = "";
|
||||
var nodes = null;
|
||||
if (type === 'red-ui-clipboard-dialog-export-rng-selected') {
|
||||
if (type === 'selected') {
|
||||
var selection = RED.workspaces.selection();
|
||||
if (selection.length > 0) {
|
||||
nodes = [];
|
||||
@ -647,14 +693,14 @@ RED.clipboard = (function() {
|
||||
}
|
||||
// Don't include the subflow meta-port nodes in the exported selection
|
||||
nodes = RED.nodes.createExportableNodeSet(nodes.filter(function(n) { return n.type !== 'subflow'}));
|
||||
} else if (type === 'red-ui-clipboard-dialog-export-rng-flow') {
|
||||
} else if (type === 'flow') {
|
||||
var activeWorkspace = RED.workspaces.active();
|
||||
nodes = RED.nodes.groups(activeWorkspace);
|
||||
nodes = nodes.concat(RED.nodes.filterNodes({z:activeWorkspace}));
|
||||
var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
|
||||
nodes.unshift(parentNode);
|
||||
nodes = RED.nodes.createExportableNodeSet(nodes);
|
||||
} else if (type === 'red-ui-clipboard-dialog-export-rng-full') {
|
||||
} else if (type === 'full') {
|
||||
nodes = RED.nodes.createCompleteNodeSet(false);
|
||||
}
|
||||
if (nodes !== null) {
|
||||
@ -670,8 +716,10 @@ RED.clipboard = (function() {
|
||||
$("#red-ui-clipboard-dialog-export").addClass('disabled');
|
||||
}
|
||||
$("#red-ui-clipboard-dialog-export-text").val(flow);
|
||||
setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50);
|
||||
$("#red-ui-clipboard-dialog-export-text").trigger("focus");
|
||||
setTimeout(function() {
|
||||
$("#red-ui-clipboard-dialog-export-text").scrollTop(0);
|
||||
refreshExportPreview(type);
|
||||
},50);
|
||||
})
|
||||
|
||||
$("#red-ui-clipboard-dialog-ok").hide();
|
||||
@ -717,6 +765,93 @@ RED.clipboard = (function() {
|
||||
|
||||
}
|
||||
|
||||
function refreshExportPreview(type) {
|
||||
|
||||
var flowData = $("#red-ui-clipboard-dialog-export-text").val() || "[]";
|
||||
var flow = JSON.parse(flowData);
|
||||
var flows = {};
|
||||
var subflows = {};
|
||||
var nodes = [];
|
||||
var nodesByZ = {};
|
||||
|
||||
var treeFlows = [];
|
||||
var treeSubflows = [];
|
||||
|
||||
flow.forEach(function(node) {
|
||||
if (node.type === "tab") {
|
||||
flows[node.id] = {
|
||||
element: getFlowLabel(node,false),
|
||||
deferBuild: type !== "flow",
|
||||
expanded: type === "flow",
|
||||
children: []
|
||||
};
|
||||
treeFlows.push(flows[node.id])
|
||||
} else if (node.type === "subflow") {
|
||||
subflows[node.id] = {
|
||||
element: getNodeLabel(node,false),
|
||||
deferBuild: true,
|
||||
children: []
|
||||
};
|
||||
treeSubflows.push(subflows[node.id])
|
||||
} else {
|
||||
nodes.push(node);
|
||||
}
|
||||
});
|
||||
|
||||
var globalNodes = [];
|
||||
var parentlessNodes = [];
|
||||
|
||||
nodes.forEach(function(node) {
|
||||
var treeNode = {
|
||||
element: getNodeLabel(node, false, false)
|
||||
};
|
||||
if (node.z) {
|
||||
if (!flows[node.z] && !subflows[node.z]) {
|
||||
parentlessNodes.push(treeNode)
|
||||
} else if (flows[node.z]) {
|
||||
flows[node.z].children.push(treeNode)
|
||||
} else if (subflows[node.z]) {
|
||||
subflows[node.z].children.push(treeNode)
|
||||
}
|
||||
} else {
|
||||
globalNodes.push(treeNode);
|
||||
}
|
||||
});
|
||||
var treeData = [];
|
||||
|
||||
if (parentlessNodes.length > 0) {
|
||||
treeData = treeData.concat(parentlessNodes);
|
||||
}
|
||||
if (type === "flow") {
|
||||
treeData = treeData.concat(treeFlows);
|
||||
} else if (treeFlows.length > 0) {
|
||||
treeData.push({
|
||||
label: RED._("menu.label.flows"),
|
||||
deferBuild: treeFlows.length > 20,
|
||||
expanded: treeFlows.length <= 20,
|
||||
children: treeFlows
|
||||
})
|
||||
}
|
||||
if (treeSubflows.length > 0) {
|
||||
treeData.push({
|
||||
label: RED._("menu.label.subflows"),
|
||||
deferBuild: treeSubflows.length > 10,
|
||||
expanded: treeSubflows.length <= 10,
|
||||
children: treeSubflows
|
||||
})
|
||||
}
|
||||
if (globalNodes.length > 0) {
|
||||
treeData.push({
|
||||
label: RED._("sidebar.info.globalConfig"),
|
||||
deferBuild: globalNodes.length > 10,
|
||||
expanded: globalNodes.length <= 10,
|
||||
children: globalNodes
|
||||
})
|
||||
}
|
||||
|
||||
$("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").treeList('data',treeData);
|
||||
}
|
||||
|
||||
function loadFlowLibrary(browser,library,label) {
|
||||
// if (includeExamples) {
|
||||
// listing.push({
|
||||
@ -756,6 +891,7 @@ RED.clipboard = (function() {
|
||||
}
|
||||
function copyText(value,element,msg) {
|
||||
var truncated = false;
|
||||
var currentFocus = document.activeElement;
|
||||
if (typeof value !== "string" ) {
|
||||
value = JSON.stringify(value, function(key,value) {
|
||||
if (value !== null && typeof value === 'object') {
|
||||
@ -787,7 +923,7 @@ RED.clipboard = (function() {
|
||||
if (truncated) {
|
||||
msg += "_truncated";
|
||||
}
|
||||
$("#red-ui-clipboard-hidden").val(value).select();
|
||||
$("#red-ui-clipboard-hidden").val(value).focus().select();
|
||||
var result = document.execCommand("copy");
|
||||
if (result && element) {
|
||||
var popover = RED.popover.create({
|
||||
@ -801,6 +937,10 @@ RED.clipboard = (function() {
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
$("#red-ui-clipboard-hidden").val("");
|
||||
if (currentFocus) {
|
||||
$(currentFocus).focus();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1103,7 +1243,7 @@ RED.clipboard = (function() {
|
||||
init: function() {
|
||||
setupDialogs();
|
||||
|
||||
$('<input type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
|
||||
$('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
|
||||
|
||||
RED.actions.add("core:show-export-dialog",showExportNodes);
|
||||
RED.actions.add("core:show-import-dialog",showImportNodes);
|
||||
|
@ -965,6 +965,18 @@
|
||||
},
|
||||
hide: function() {
|
||||
this.uiSelect.hide();
|
||||
},
|
||||
disable: function(val) {
|
||||
if(val === true) {
|
||||
this.uiSelect.attr("disabled", "disabled");
|
||||
} else if (val === false) {
|
||||
this.uiSelect.attr("disabled", null); //remove attr
|
||||
} else {
|
||||
this.uiSelect.attr("disabled", val); //user value
|
||||
}
|
||||
},
|
||||
disabled: function() {
|
||||
return this.uiSelect.attr("disabled");
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
@ -414,18 +414,20 @@ RED.editor = (function() {
|
||||
for (var cred in credDefinition) {
|
||||
if (credDefinition.hasOwnProperty(cred)) {
|
||||
var input = $("#" + prefix + '-' + cred);
|
||||
var value = input.val();
|
||||
if (credDefinition[cred].type == 'password') {
|
||||
node.credentials['has_' + cred] = (value !== "");
|
||||
if (value == '__PWRD__') {
|
||||
continue;
|
||||
}
|
||||
changed = true;
|
||||
if (input.length > 0) {
|
||||
var value = input.val();
|
||||
if (credDefinition[cred].type == 'password') {
|
||||
node.credentials['has_' + cred] = (value !== "");
|
||||
if (value == '__PWRD__') {
|
||||
continue;
|
||||
}
|
||||
changed = true;
|
||||
|
||||
}
|
||||
node.credentials[cred] = value;
|
||||
if (value != node.credentials._[cred]) {
|
||||
changed = true;
|
||||
}
|
||||
node.credentials[cred] = value;
|
||||
if (value != node.credentials._[cred]) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -442,16 +444,18 @@ RED.editor = (function() {
|
||||
for (var d in definition.defaults) {
|
||||
if (definition.defaults.hasOwnProperty(d)) {
|
||||
if (definition.defaults[d].type) {
|
||||
var configTypeDef = RED.nodes.getType(definition.defaults[d].type);
|
||||
if (configTypeDef) {
|
||||
if (configTypeDef.exclusive) {
|
||||
prepareConfigNodeButton(node,d,definition.defaults[d].type,prefix);
|
||||
if (!definition.defaults[d]._type.array) {
|
||||
var configTypeDef = RED.nodes.getType(definition.defaults[d].type);
|
||||
if (configTypeDef && configTypeDef.category === 'config') {
|
||||
if (configTypeDef.exclusive) {
|
||||
prepareConfigNodeButton(node,d,definition.defaults[d].type,prefix);
|
||||
} else {
|
||||
prepareConfigNodeSelect(node,d,definition.defaults[d].type,prefix);
|
||||
}
|
||||
} else {
|
||||
prepareConfigNodeSelect(node,d,definition.defaults[d].type,prefix);
|
||||
console.log("Unknown type:", definition.defaults[d].type);
|
||||
preparePropertyEditor(node,d,prefix,definition.defaults);
|
||||
}
|
||||
} else {
|
||||
console.log("Unknown type:", definition.defaults[d].type);
|
||||
preparePropertyEditor(node,d,prefix,definition.defaults);
|
||||
}
|
||||
} else {
|
||||
preparePropertyEditor(node,d,prefix,definition.defaults);
|
||||
@ -465,6 +469,7 @@ RED.editor = (function() {
|
||||
definition.oneditprepare.call(node);
|
||||
} catch(err) {
|
||||
console.log("oneditprepare",node.id,node.type,err.toString());
|
||||
console.log(err.stack);
|
||||
}
|
||||
}
|
||||
// Now invoke any change handlers added to the fields - passing true
|
||||
@ -491,11 +496,13 @@ RED.editor = (function() {
|
||||
populateCredentialsInputs(node, definition.credentials, node.credentials, prefix);
|
||||
completePrepare();
|
||||
} else {
|
||||
$.getJSON(getCredentialsURL(node.type, node.id), function (data) {
|
||||
node.credentials = data;
|
||||
node.credentials._ = $.extend(true,{},data);
|
||||
if (!/^subflow:/.test(definition.type)) {
|
||||
populateCredentialsInputs(node, definition.credentials, node.credentials, prefix);
|
||||
getNodeCredentials(node.type, node.id, function(data) {
|
||||
if (data) {
|
||||
node.credentials = data;
|
||||
node.credentials._ = $.extend(true,{},data);
|
||||
if (!/^subflow:/.test(definition.type)) {
|
||||
populateCredentialsInputs(node, definition.credentials, node.credentials, prefix);
|
||||
}
|
||||
}
|
||||
completePrepare();
|
||||
});
|
||||
@ -1083,8 +1090,11 @@ RED.editor = (function() {
|
||||
node.infoEditor = nodeInfoEditor;
|
||||
return nodeInfoEditor;
|
||||
}
|
||||
var buildingEditDialog = false;
|
||||
|
||||
function showEditDialog(node, defaultTab) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var editing_node = node;
|
||||
var isDefaultIcon;
|
||||
var defaultIcon;
|
||||
@ -1192,7 +1202,7 @@ RED.editor = (function() {
|
||||
changed = true;
|
||||
}
|
||||
} catch(err) {
|
||||
console.log("oneditsave",editing_node.id,editing_node.type,err.toString());
|
||||
console.warn("oneditsave",editing_node.id,editing_node.type,err.toString());
|
||||
}
|
||||
|
||||
for (d in editing_node._def.defaults) {
|
||||
@ -1609,6 +1619,7 @@ RED.editor = (function() {
|
||||
if (defaultTab) {
|
||||
editorTabs.activateTab(defaultTab);
|
||||
}
|
||||
buildingEditDialog = false;
|
||||
done();
|
||||
});
|
||||
},
|
||||
@ -1660,6 +1671,8 @@ RED.editor = (function() {
|
||||
* prefix - the input prefix of the parent property
|
||||
*/
|
||||
function showEditConfigNodeDialog(name,type,id,prefix) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var adding = (id == "_ADD_");
|
||||
var node_def = RED.nodes.getType(type);
|
||||
var editing_config_node = RED.nodes.node(id);
|
||||
@ -1823,6 +1836,7 @@ RED.editor = (function() {
|
||||
trayBody.i18n();
|
||||
trayFooter.i18n();
|
||||
finishedBuilding = true;
|
||||
buildingEditDialog = false;
|
||||
done();
|
||||
});
|
||||
},
|
||||
@ -1890,7 +1904,7 @@ RED.editor = (function() {
|
||||
try {
|
||||
configTypeDef.oneditsave.call(editing_config_node);
|
||||
} catch(err) {
|
||||
console.log("oneditsave",editing_config_node.id,editing_config_node.type,err.toString());
|
||||
console.warn("oneditsave",editing_config_node.id,editing_config_node.type,err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2146,6 +2160,8 @@ RED.editor = (function() {
|
||||
}
|
||||
|
||||
function showEditSubflowDialog(subflow) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var editing_node = subflow;
|
||||
editStack.push(subflow);
|
||||
RED.view.state(RED.state.EDITING);
|
||||
@ -2250,6 +2266,14 @@ RED.editor = (function() {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
var newMeta = RED.subflow.exportSubflowModuleProperties(editing_node);
|
||||
|
||||
if (!isSameObj(editing_node.meta,newMeta)) {
|
||||
changes.meta = editing_node.meta;
|
||||
editing_node.meta = newMeta;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
var wasChanged = editing_node.changed;
|
||||
editing_node.changed = true;
|
||||
@ -2356,6 +2380,16 @@ RED.editor = (function() {
|
||||
};
|
||||
editorTabs.addTab(nodePropertiesTab);
|
||||
|
||||
var moduleTab = {
|
||||
id: "editor-tab-module",
|
||||
label: RED._("editor-tab.module"),
|
||||
name: RED._("editor-tab.module"),
|
||||
content: $('<div>', {class:"red-ui-tray-content"}).appendTo(editorContent).hide(),
|
||||
iconClass: "fa fa-cube",
|
||||
};
|
||||
editorTabs.addTab(moduleTab);
|
||||
RED.subflow.buildModuleForm(moduleTab.content, editing_node);
|
||||
|
||||
var descriptionTab = {
|
||||
id: "editor-tab-description",
|
||||
label: RED._("editor-tab.description"),
|
||||
@ -2384,15 +2418,17 @@ RED.editor = (function() {
|
||||
|
||||
buildEditForm(nodePropertiesTab.content,"dialog-form","subflow-template", undefined, editing_node);
|
||||
trayBody.i18n();
|
||||
|
||||
$.getJSON(getCredentialsURL("subflow", subflow.id), function (data) {
|
||||
subflow.credentials = data;
|
||||
subflow.credentials._ = $.extend(true,{},data);
|
||||
|
||||
getNodeCredentials("subflow", subflow.id, function(data) {
|
||||
if (data) {
|
||||
subflow.credentials = data;
|
||||
subflow.credentials._ = $.extend(true,{},data);
|
||||
}
|
||||
$("#subflow-input-name").val(subflow.name);
|
||||
RED.text.bidi.prepareInput($("#subflow-input-name"));
|
||||
|
||||
finishedBuilding = true;
|
||||
buildingEditDialog = false;
|
||||
|
||||
done();
|
||||
});
|
||||
},
|
||||
@ -2413,7 +2449,39 @@ RED.editor = (function() {
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
function getNodeCredentials(type, id, done) {
|
||||
var timeoutNotification;
|
||||
var intialTimeout = setTimeout(function() {
|
||||
timeoutNotification = RED.notify($('<p data-i18n="[prepend]editor.loadCredentials"> <img src="red/images/spin.svg"/></p>').i18n(),{fixed: true})
|
||||
},800);
|
||||
|
||||
$.ajax({
|
||||
url: getCredentialsURL(type,id),
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (timeoutNotification) {
|
||||
timeoutNotification.close();
|
||||
timeoutNotification = null;
|
||||
}
|
||||
clearTimeout(intialTimeout);
|
||||
done(data);
|
||||
},
|
||||
error: function(jqXHR,status,error) {
|
||||
if (timeoutNotification) {
|
||||
timeoutNotification.close();
|
||||
timeoutNotification = null;
|
||||
}
|
||||
clearTimeout(intialTimeout);
|
||||
RED.notify(RED._("editor.errors.credentialLoadFailed"),"error")
|
||||
done(null);
|
||||
},
|
||||
timeout: 30000,
|
||||
});
|
||||
}
|
||||
|
||||
function showEditGroupDialog(group) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
var editing_node = group;
|
||||
editStack.push(group);
|
||||
RED.view.state(RED.state.EDITING);
|
||||
@ -2457,7 +2525,7 @@ RED.editor = (function() {
|
||||
changed = true;
|
||||
}
|
||||
} catch(err) {
|
||||
console.log("oneditsave",editing_node.id,editing_node.type,err.toString());
|
||||
console.warn("oneditsave",editing_node.id,editing_node.type,err.toString());
|
||||
}
|
||||
|
||||
for (d in editing_node._def.defaults) {
|
||||
@ -2637,6 +2705,7 @@ RED.editor = (function() {
|
||||
prepareEditDialog(group,group._def,"node-input", function() {
|
||||
trayBody.i18n();
|
||||
finishedBuilding = true;
|
||||
buildingEditDialog = false;
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
@ -329,21 +329,26 @@ RED.palette.editor = (function() {
|
||||
catalogueLoadStatus.push(err||v);
|
||||
if (!err) {
|
||||
if (v.modules) {
|
||||
v.modules.forEach(function(m) {
|
||||
loadedIndex[m.id] = m;
|
||||
m.index = [m.id];
|
||||
if (m.keywords) {
|
||||
m.index = m.index.concat(m.keywords);
|
||||
var a = false;
|
||||
v.modules = v.modules.filter(function(m) {
|
||||
if (checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
|
||||
loadedIndex[m.id] = m;
|
||||
m.index = [m.id];
|
||||
if (m.keywords) {
|
||||
m.index = m.index.concat(m.keywords);
|
||||
}
|
||||
if (m.types) {
|
||||
m.index = m.index.concat(m.types);
|
||||
}
|
||||
if (m.updated_at) {
|
||||
m.timestamp = new Date(m.updated_at).getTime();
|
||||
} else {
|
||||
m.timestamp = 0;
|
||||
}
|
||||
m.index = m.index.join(",").toLowerCase();
|
||||
return true;
|
||||
}
|
||||
if (m.types) {
|
||||
m.index = m.index.concat(m.types);
|
||||
}
|
||||
if (m.updated_at) {
|
||||
m.timestamp = new Date(m.updated_at).getTime();
|
||||
} else {
|
||||
m.timestamp = 0;
|
||||
}
|
||||
m.index = m.index.join(",").toLowerCase();
|
||||
return false;
|
||||
})
|
||||
loadedList = loadedList.concat(v.modules);
|
||||
}
|
||||
@ -437,11 +442,84 @@ RED.palette.editor = (function() {
|
||||
return -1 * (A.info.timestamp-B.info.timestamp);
|
||||
}
|
||||
|
||||
var installAllowList = ['*'];
|
||||
var installDenyList = [];
|
||||
|
||||
function parseModuleList(list) {
|
||||
list = list || ["*"];
|
||||
return list.map(function(rule) {
|
||||
var m = /^(.+?)(?:@(.*))?$/.exec(rule);
|
||||
var wildcardPos = m[1].indexOf("*");
|
||||
wildcardPos = wildcardPos===-1?Infinity:wildcardPos;
|
||||
|
||||
return {
|
||||
module: new RegExp("^"+m[1].replace(/\*/g,".*")+"$"),
|
||||
version: m[2],
|
||||
wildcardPos: wildcardPos
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function checkAgainstList(module,version,list) {
|
||||
for (var i=0;i<list.length;i++) {
|
||||
var rule = list[i];
|
||||
if (rule.module.test(module)) {
|
||||
// Without a full semver library in the editor,
|
||||
// we skip the version check.
|
||||
// Not ideal - but will get caught in the runtime
|
||||
// if the user tries to install.
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkModuleAllowed(module,version,allowList,denyList) {
|
||||
if (!allowList && !denyList) {
|
||||
// Default to allow
|
||||
return true;
|
||||
}
|
||||
if (allowList.length === 0 && denyList.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var allowedRule = checkAgainstList(module,version,allowList);
|
||||
var deniedRule = checkAgainstList(module,version,denyList);
|
||||
// console.log("A",allowedRule)
|
||||
// console.log("D",deniedRule)
|
||||
|
||||
if (allowedRule && !deniedRule) {
|
||||
return true;
|
||||
}
|
||||
if (!allowedRule && deniedRule) {
|
||||
return false;
|
||||
}
|
||||
if (!allowedRule && !deniedRule) {
|
||||
return true;
|
||||
}
|
||||
if (allowedRule.wildcardPos !== deniedRule.wildcardPos) {
|
||||
return allowedRule.wildcardPos > deniedRule.wildcardPos
|
||||
} else {
|
||||
// First wildcard in same position.
|
||||
// Go with the longer matching rule. This isn't going to be 100%
|
||||
// right, but we are deep into edge cases at this point.
|
||||
return allowedRule.module.toString().length > deniedRule.module.toString().length
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
return;
|
||||
}
|
||||
var settingsAllowList = RED.settings.get("externalModules.palette.allowList")
|
||||
var settingsDenyList = RED.settings.get("externalModules.palette.denyList")
|
||||
if (settingsAllowList || settingsDenyList) {
|
||||
installAllowList = settingsAllowList;
|
||||
installDenyList = settingsDenyList
|
||||
}
|
||||
installAllowList = parseModuleList(installAllowList);
|
||||
installDenyList = parseModuleList(installDenyList);
|
||||
|
||||
createSettingsPane();
|
||||
|
||||
RED.userSettings.add({
|
||||
@ -880,7 +958,7 @@ RED.palette.editor = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
if (RED.settings.theme('palette.upload') !== false) {
|
||||
if (RED.settings.get('externalModules.palette.allowUpload', true) !== false) {
|
||||
var uploadSpan = $('<span class="button-group">').prependTo(toolBar);
|
||||
var uploadButton = $('<button type="button" class="red-ui-sidebar-header-button red-ui-palette-editor-upload-button"><label><i class="fa fa-upload"></i><form id="red-ui-palette-editor-upload-form" enctype="multipart/form-data"><input name="tarball" type="file" accept=".tgz"></label></button>').appendTo(uploadSpan);
|
||||
|
||||
@ -962,7 +1040,7 @@ RED.palette.editor = (function() {
|
||||
}
|
||||
|
||||
function update(entry,version,url,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
@ -1021,7 +1099,7 @@ RED.palette.editor = (function() {
|
||||
})
|
||||
}
|
||||
function remove(entry,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
@ -1078,7 +1156,7 @@ RED.palette.editor = (function() {
|
||||
})
|
||||
}
|
||||
function install(entry,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
|
@ -97,13 +97,18 @@ RED.palette = (function() {
|
||||
label = RED.utils.sanitize(label);
|
||||
|
||||
|
||||
var words = label.split(/[ -]/);
|
||||
var words = label.split(/([ -]|\\n )/);
|
||||
|
||||
var displayLines = [];
|
||||
|
||||
var currentLine = "";
|
||||
for (var i=0;i<words.length;i++) {
|
||||
var word = words[i];
|
||||
if (word === "\\n ") {
|
||||
displayLines.push(currentLine);
|
||||
currentLine = "";
|
||||
continue;
|
||||
}
|
||||
var sep = (i == 0) ? "" : " ";
|
||||
var newWidth = RED.view.calculateTextWidth(currentLine+sep+word, "red-ui-palette-label");
|
||||
if (newWidth < nodeWidth) {
|
||||
@ -147,7 +152,7 @@ RED.palette = (function() {
|
||||
var popOverContent;
|
||||
try {
|
||||
var l = "<p><b>"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"</b></p>";
|
||||
popOverContent = $('<div></div>').append($(l+(info?info:$("script[data-help-name='"+type+"']").html()||"<p>"+RED._("palette.noInfo")+"</p>").trim())
|
||||
popOverContent = $('<div></div>').append($(l+(info?info:RED.nodes.getNodeHelp(type)||"<p>"+RED._("palette.noInfo")+"</p>").trim())
|
||||
.filter(function(n) {
|
||||
return (this.nodeType == 1 && this.nodeName == "P") || (this.nodeType == 3 && this.textContent.trim().length > 0)
|
||||
}).slice(0,2));
|
||||
@ -165,7 +170,16 @@ RED.palette = (function() {
|
||||
metaData = typeInfo.set.module+" : ";
|
||||
}
|
||||
metaData += type;
|
||||
$('<button type="button" onclick="RED.sidebar.help.show(\''+type+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
|
||||
|
||||
if (/^subflow:/.test(type)) {
|
||||
$('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
|
||||
}
|
||||
|
||||
var safeType = type.replace(/'/g,"\\'");
|
||||
|
||||
$('<button type="button" onclick="RED.search.show(\'type:'+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent)
|
||||
$('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
|
||||
|
||||
$('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);
|
||||
}
|
||||
} catch(err) {
|
||||
@ -264,27 +278,6 @@ RED.palette = (function() {
|
||||
|
||||
d.data('popover',popover);
|
||||
|
||||
// $(d).popover({
|
||||
// title:d.type,
|
||||
// placement:"right",
|
||||
// trigger: "hover",
|
||||
// delay: { show: 750, hide: 50 },
|
||||
// html: true,
|
||||
// container:'body'
|
||||
// });
|
||||
// d.on("click", function() {
|
||||
// RED.view.focus();
|
||||
// var helpText;
|
||||
// if (nt.indexOf("subflow:") === 0) {
|
||||
// helpText = RED.utils.renderMarkdown(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
// } else {
|
||||
// helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
// }
|
||||
// // Don't look too closely. RED.sidebar.info.set will set the 'Description'
|
||||
// // section of the sidebar. Pass in the title of the Help section so it looks
|
||||
// // right.
|
||||
// RED.sidebar.type.show(helpText,RED._("sidebar.info.nodeHelp"));
|
||||
// });
|
||||
var chart = $("#red-ui-workspace-chart");
|
||||
var chartSVG = $("#red-ui-workspace-chart>svg").get(0);
|
||||
var activeSpliceLink;
|
||||
@ -417,7 +410,8 @@ RED.palette = (function() {
|
||||
RED.workspaces.show(nt.substring(8));
|
||||
e.preventDefault();
|
||||
});
|
||||
nodeInfo = RED.utils.renderMarkdown(def.info||"");
|
||||
var subflow = RED.nodes.subflow(nt.substring(8));
|
||||
nodeInfo = RED.utils.renderMarkdown(subflow.info||"");
|
||||
}
|
||||
setLabel(nt,d,label,nodeInfo);
|
||||
|
||||
|
@ -465,7 +465,7 @@ RED.projects.settings = (function() {
|
||||
metaRow = $('<div class="red-ui-palette-module-meta"></div>').appendTo(headerRow);
|
||||
var buttons = $('<div class="red-ui-palette-module-button-group"></div>').appendTo(metaRow);
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
if (!entry.installed && RED.settings.theme('palette.editable') !== false) {
|
||||
if (!entry.installed && RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
$('<a href="#" class="red-ui-button red-ui-button-small">' + RED._("sidebar.project.projectSettings.install") + '</a>').appendTo(buttons)
|
||||
.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
|
@ -43,9 +43,11 @@ RED.projects.userSettings = (function() {
|
||||
|
||||
function createWorkflowSection(pane) {
|
||||
|
||||
var defaultWorkflowMode = RED.settings.theme("projects.workflow.mode","manual");
|
||||
|
||||
var currentGitSettings = RED.settings.get('git') || {};
|
||||
currentGitSettings.workflow = currentGitSettings.workflow || {};
|
||||
currentGitSettings.workflow.mode = currentGitSettings.workflow.mode || "manual";
|
||||
currentGitSettings.workflow.mode = currentGitSettings.workflow.mode || defaultWorkflowMode;
|
||||
|
||||
var title = $('<h3></h3>').text(RED._("editor:sidebar.project.userSettings.workflow")).appendTo(pane);
|
||||
|
||||
|
@ -294,7 +294,10 @@ RED.sidebar.versionControl = (function() {
|
||||
// TODO: this is a full refresh of the files - should be able to
|
||||
// just do an incremental refresh
|
||||
|
||||
var workflowMode = ((RED.settings.get('git') || {}).workflow || {}).mode || "manual";
|
||||
// Get the default workflow mode from theme settings
|
||||
var defaultWorkflowMode = RED.settings.theme("projects.workflow.mode","manual");
|
||||
// Check for the user-defined choice of mode
|
||||
var workflowMode = ((RED.settings.get('git') || {}).workflow || {}).mode || defaultWorkflowMode;
|
||||
if (workflowMode === 'auto') {
|
||||
refresh(true);
|
||||
} else {
|
||||
|
@ -47,6 +47,37 @@ RED.subflow = (function() {
|
||||
'</div>'+
|
||||
'</script>';
|
||||
|
||||
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-type" data-i18n="[append]editor:subflow.type"> </label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-type">'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-license" data-i18n="[append]editor:subflow.license"></label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
|
||||
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
|
||||
'</div>'+
|
||||
'</form>';
|
||||
|
||||
function findAvailableSubflowIOPosition(subflow,isInput) {
|
||||
var pos = {x:50,y:30};
|
||||
if (!isInput) {
|
||||
@ -433,12 +464,43 @@ RED.subflow = (function() {
|
||||
|
||||
$("#red-ui-subflow-delete").on("click", function(event) {
|
||||
event.preventDefault();
|
||||
var startDirty = RED.nodes.dirty();
|
||||
var historyEvent = removeSubflow(RED.workspaces.active());
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = startDirty;
|
||||
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
||||
if (subflow.instances.length > 0) {
|
||||
var msg = $('<div>')
|
||||
$('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
|
||||
$('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg);
|
||||
var confirmDeleteNotification = RED.notify(msg, {
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._('common.label.cancel'),
|
||||
click: function() {
|
||||
confirmDeleteNotification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._('workspace.confirmDelete'),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
confirmDeleteNotification.close();
|
||||
completeDelete();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
RED.history.push(historyEvent);
|
||||
return;
|
||||
} else {
|
||||
completeDelete();
|
||||
}
|
||||
function completeDelete() {
|
||||
var startDirty = RED.nodes.dirty();
|
||||
var historyEvent = removeSubflow(RED.workspaces.active());
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = startDirty;
|
||||
RED.history.push(historyEvent);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@ -993,6 +1055,7 @@ RED.subflow = (function() {
|
||||
icon: "",
|
||||
type: "cred"
|
||||
}
|
||||
opt.ui.type = "cred";
|
||||
} else {
|
||||
opt.ui = opt.ui || {
|
||||
icon: "",
|
||||
@ -1488,6 +1551,7 @@ RED.subflow = (function() {
|
||||
var locale = RED.i18n.lang();
|
||||
var labelText = lookupLabel(labels, labels["en-US"]||tenv.name, locale);
|
||||
var label = $('<label>').appendTo(row);
|
||||
$('<span> </span>').appendTo(row);
|
||||
var labelContainer = $('<span></span>').appendTo(label);
|
||||
if (ui.icon) {
|
||||
var newPath = RED.utils.separateIconPath(ui.icon);
|
||||
@ -1723,22 +1787,54 @@ RED.subflow = (function() {
|
||||
parentEnv[env.name] = item;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (node.env) {
|
||||
for (var i = 0; i < node.env.length; i++) {
|
||||
var env = node.env[i];
|
||||
if (parentEnv.hasOwnProperty(env.name)) {
|
||||
parentEnv[env.name].type = env.type;
|
||||
parentEnv[env.name].value = env.value;
|
||||
} else {
|
||||
// envList.push({
|
||||
// name: env.name,
|
||||
// type: env.type,
|
||||
// value: env.value,
|
||||
// });
|
||||
if (node.env) {
|
||||
for (var i = 0; i < node.env.length; i++) {
|
||||
var env = node.env[i];
|
||||
if (parentEnv.hasOwnProperty(env.name)) {
|
||||
parentEnv[env.name].type = env.type;
|
||||
parentEnv[env.name].value = env.value;
|
||||
} else {
|
||||
// envList.push({
|
||||
// name: env.name,
|
||||
// type: env.type,
|
||||
// value: env.value,
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (node._def.subflowModule) {
|
||||
var keys = Object.keys(node._def.defaults);
|
||||
keys.forEach(function(name) {
|
||||
if (name !== 'name') {
|
||||
var prop = node._def.defaults[name];
|
||||
var nodeProp = node[name];
|
||||
var nodePropType;
|
||||
var nodePropValue = nodeProp;
|
||||
if (prop.ui && prop.ui.type === "cred") {
|
||||
nodePropType = "cred";
|
||||
} else {
|
||||
switch(typeof nodeProp) {
|
||||
case "string": nodePropType = "str"; break;
|
||||
case "number": nodePropType = "num"; break;
|
||||
case "boolean": nodePropType = "bool"; nodePropValue = nodeProp?"true":"false"; break;
|
||||
default:
|
||||
nodePropType = nodeProp.type;
|
||||
nodePropValue = nodeProp.value;
|
||||
}
|
||||
}
|
||||
var item = {
|
||||
name: name,
|
||||
type: nodePropType,
|
||||
value: nodePropValue,
|
||||
parent: {
|
||||
type: prop.type,
|
||||
value: prop.value
|
||||
},
|
||||
ui: $.extend(true,{},prop.ui)
|
||||
}
|
||||
envList.push(item);
|
||||
}
|
||||
})
|
||||
}
|
||||
return envList;
|
||||
}
|
||||
@ -1859,6 +1955,126 @@ RED.subflow = (function() {
|
||||
buildPropertiesList(list, node);
|
||||
}
|
||||
|
||||
function setupInputValidation(input,validator) {
|
||||
var errorTip;
|
||||
var validateTimeout;
|
||||
|
||||
var validateFunction = function() {
|
||||
if (validateTimeout) {
|
||||
return;
|
||||
}
|
||||
validateTimeout = setTimeout(function() {
|
||||
var error = validator(input.val());
|
||||
// if (!error && errorTip) {
|
||||
// errorTip.close();
|
||||
// errorTip = null;
|
||||
// } else if (error && !errorTip) {
|
||||
// errorTip = RED.popover.create({
|
||||
// tooltip: true,
|
||||
// target:input,
|
||||
// size: "small",
|
||||
// direction: "bottom",
|
||||
// content: error,
|
||||
// }).open();
|
||||
// }
|
||||
input.toggleClass("input-error",!!error);
|
||||
validateTimeout = null;
|
||||
})
|
||||
}
|
||||
input.on("change keyup paste", validateFunction);
|
||||
}
|
||||
|
||||
function buildModuleForm(container, node) {
|
||||
$(_subflowModulePaneTemplate).appendTo(container);
|
||||
var moduleProps = node.meta || {};
|
||||
[
|
||||
'module',
|
||||
'type',
|
||||
'version',
|
||||
'author',
|
||||
'desc',
|
||||
'keywords',
|
||||
'license'
|
||||
].forEach(function(property) {
|
||||
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
|
||||
})
|
||||
$("#subflow-input-module-type").attr("placeholder",node.id);
|
||||
|
||||
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
|
||||
newValue = newValue.trim();
|
||||
var isValid = newValue.length < 215;
|
||||
isValid = isValid && !/^[._]/.test(newValue);
|
||||
isValid = isValid && !/[A-Z]/.test(newValue);
|
||||
if (newValue !== encodeURIComponent(newValue)) {
|
||||
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
|
||||
if (m) {
|
||||
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
|
||||
} else {
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
return isValid?"":"Invalid module name"
|
||||
})
|
||||
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
|
||||
newValue = newValue.trim();
|
||||
var isValid = newValue === "" ||
|
||||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
|
||||
return isValid?"":"Invalid version number"
|
||||
})
|
||||
|
||||
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
|
||||
var typedLicenses = {
|
||||
types: licenses.map(function(l) {
|
||||
return {
|
||||
value: l,
|
||||
label: l === "none" ? RED._("editor:subflow.licenseNone") : l,
|
||||
hasValue: false
|
||||
};
|
||||
})
|
||||
}
|
||||
typedLicenses.types.push({
|
||||
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
|
||||
})
|
||||
if (!moduleProps.license) {
|
||||
typedLicenses.default = "none";
|
||||
} else if (licenses.indexOf(moduleProps.license) > -1) {
|
||||
typedLicenses.default = moduleProps.license;
|
||||
} else {
|
||||
typedLicenses.default = "_custom_";
|
||||
}
|
||||
$("#subflow-input-module-license").typedInput(typedLicenses)
|
||||
}
|
||||
|
||||
function exportSubflowModuleProperties(node) {
|
||||
var value;
|
||||
var moduleProps = {};
|
||||
[
|
||||
'module',
|
||||
'type',
|
||||
'version',
|
||||
'author',
|
||||
'desc',
|
||||
'keywords'
|
||||
].forEach(function(property) {
|
||||
value = $("#subflow-input-module-"+property).val().trim();
|
||||
if (value) {
|
||||
moduleProps[property] = value;
|
||||
}
|
||||
})
|
||||
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
|
||||
|
||||
if (selectedLicenseType === '_custom_') {
|
||||
value = $("#subflow-input-module-license").val();
|
||||
if (value) {
|
||||
moduleProps.license = value;
|
||||
}
|
||||
} else if (selectedLicenseType !== "none") {
|
||||
moduleProps.license = selectedLicenseType;
|
||||
}
|
||||
return moduleProps;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: init,
|
||||
createSubflow: createSubflow,
|
||||
@ -1872,9 +2088,11 @@ RED.subflow = (function() {
|
||||
|
||||
buildEditForm: buildEditForm,
|
||||
buildPropertiesForm: buildPropertiesForm,
|
||||
buildModuleForm: buildModuleForm,
|
||||
|
||||
exportSubflowTemplateEnv: exportEnvList,
|
||||
exportSubflowInstanceEnv: exportSubflowInstanceEnv
|
||||
exportSubflowInstanceEnv: exportSubflowInstanceEnv,
|
||||
exportSubflowModuleProperties: exportSubflowModuleProperties
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -247,7 +247,7 @@ RED.sidebar.help = (function() {
|
||||
helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'));
|
||||
title = subflowNode.name || nodeType;
|
||||
} else {
|
||||
helpText = $("script[data-help-name='"+nodeType+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
helpText = RED.nodes.getNodeHelp(nodeType)||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
title = nodeType;
|
||||
}
|
||||
setInfoText(title, helpText, helpSection);
|
||||
|
@ -119,34 +119,17 @@ RED.sidebar.info.outliner = (function() {
|
||||
return div;
|
||||
}
|
||||
|
||||
function getSubflowLabel(n) {
|
||||
|
||||
var div = $('<div>',{class:"red-ui-info-outline-item"});
|
||||
RED.utils.createNodeIcon(n).appendTo(div);
|
||||
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
||||
var labelText = getNodeLabelText(n);
|
||||
var label = $('<div>',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).appendTo(contentDiv);
|
||||
if (labelText) {
|
||||
label.text(labelText)
|
||||
} else {
|
||||
label.html(" ")
|
||||
}
|
||||
|
||||
addControls(n, div);
|
||||
|
||||
return div;
|
||||
|
||||
|
||||
// var div = $('<div>',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"});
|
||||
// var contentDiv = $('<div>',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div);
|
||||
// contentDiv.text(n.name || n.id);
|
||||
// addControls(n, div);
|
||||
// return div;
|
||||
}
|
||||
|
||||
function addControls(n,div) {
|
||||
var controls = $('<div>',{class:"red-ui-info-outline-item-controls red-ui-info-outline-item-hover-controls"}).appendTo(div);
|
||||
|
||||
if (n.type === "subflow") {
|
||||
var subflowInstanceBadge = $('<button type="button" class="red-ui-info-outline-item-control-users red-ui-button red-ui-button-small"><i class="fa fa-toggle-right"></i></button>').text(n.instances.length).appendTo(controls).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
RED.search.show("type:subflow:"+n.id);
|
||||
})
|
||||
// RED.popover.tooltip(userCountBadge,function() { return RED._('editor.nodesUse',{count:n.users.length})});
|
||||
}
|
||||
if (n._def.category === "config" && n.type !== "group") {
|
||||
var userCountBadge = $('<button type="button" class="red-ui-info-outline-item-control-users red-ui-button red-ui-button-small"><i class="fa fa-toggle-right"></i></button>').text(n.users.length).appendTo(controls).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
@ -169,7 +152,7 @@ RED.sidebar.info.outliner = (function() {
|
||||
// evt.stopPropagation();
|
||||
// RED.view.reveal(n.id);
|
||||
// })
|
||||
if (n.type !== 'group' && n.type !== 'subflow') {
|
||||
if (n.type !== 'subflow') {
|
||||
var toggleButton = $('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
@ -179,6 +162,46 @@ RED.sidebar.info.outliner = (function() {
|
||||
} else {
|
||||
RED.workspaces.disable(n.id)
|
||||
}
|
||||
} else if (n.type === 'group') {
|
||||
var groupNodes = RED.group.getNodes(n,true);
|
||||
var groupHistoryEvent = {
|
||||
t:'multi',
|
||||
events:[],
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
var targetState;
|
||||
groupNodes.forEach(function(n) {
|
||||
if (n.type !== 'group') {
|
||||
if (targetState === undefined) {
|
||||
targetState = !n.d;
|
||||
}
|
||||
var state = !!n.d;
|
||||
if (state !== targetState) {
|
||||
var historyEvent = {
|
||||
t: "edit",
|
||||
node: n,
|
||||
changed: n.changed,
|
||||
changes: {
|
||||
d: n.d
|
||||
}
|
||||
}
|
||||
if (n.d) {
|
||||
delete n.d;
|
||||
} else {
|
||||
n.d = true;
|
||||
}
|
||||
n.dirty = true;
|
||||
n.changed = true;
|
||||
RED.events.emit("nodes:change",n);
|
||||
groupHistoryEvent.events.push(historyEvent);
|
||||
}
|
||||
}
|
||||
if (groupHistoryEvent.events.length > 0) {
|
||||
RED.history.push(groupHistoryEvent);
|
||||
RED.nodes.dirty(true)
|
||||
RED.view.redraw();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// TODO: this ought to be a utility function in RED.nodes
|
||||
var historyEvent = {
|
||||
@ -198,11 +221,15 @@ RED.sidebar.info.outliner = (function() {
|
||||
n.dirty = true;
|
||||
n.changed = true;
|
||||
RED.events.emit("nodes:change",n);
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true)
|
||||
RED.view.redraw();
|
||||
}
|
||||
});
|
||||
RED.popover.tooltip(toggleButton,function() {
|
||||
if (n.type === "group") {
|
||||
return RED._("common.label.enable")+" / "+RED._("common.label.disable")
|
||||
}
|
||||
return RED._("common.label."+(((n.type==='tab' && n.disabled) || (n.type!=='tab' && n.d))?"enable":"disable"));
|
||||
});
|
||||
} else {
|
||||
@ -486,6 +513,13 @@ RED.sidebar.info.outliner = (function() {
|
||||
existingObject.treeList.remove();
|
||||
delete objects[n.id]
|
||||
|
||||
if (/^subflow:/.test(n.type)) {
|
||||
var sfType = n.type.substring(8);
|
||||
if (objects[sfType]) {
|
||||
objects[sfType].element.find(".red-ui-info-outline-item-control-users").text(RED.nodes.subflow(sfType).instances.length);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a group being removed, it may have an empty item
|
||||
if (empties[n.id]) {
|
||||
delete empties[n.id];
|
||||
@ -587,6 +621,12 @@ RED.sidebar.info.outliner = (function() {
|
||||
configNodeTypes[parent].types[n.type].treeList.addChild(objects[n.id]);
|
||||
}
|
||||
objects[n.id].element.toggleClass("red-ui-info-outline-item-disabled", !!n.d)
|
||||
if (/^subflow:/.test(n.type)) {
|
||||
var sfType = n.type.substring(8);
|
||||
if (objects[sfType]) {
|
||||
objects[sfType].element.find(".red-ui-info-outline-item-control-users").text(RED.nodes.subflow(sfType).instances.length);
|
||||
}
|
||||
}
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
|
@ -338,7 +338,7 @@ RED.sidebar.info = (function() {
|
||||
count++;
|
||||
propRow = $('<tr class="red-ui-help-info-property-row'+(expandedSections.property?"":" hide")+'"><td></td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[0]).text(n);
|
||||
if (defaults[n].type) {
|
||||
if (defaults[n].type && !defaults[n]._type.array) {
|
||||
var configNode = RED.nodes.node(val);
|
||||
if (!configNode) {
|
||||
RED.utils.createObjectElement(undefined).appendTo(propRow.children()[1]);
|
||||
@ -382,21 +382,14 @@ RED.sidebar.info = (function() {
|
||||
var category = subflowNode.category||"subflows";
|
||||
$(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category}))
|
||||
$('<tr class="node-info-subflow-row"><td>'+RED._("sidebar.info.instances")+"</td><td>"+subflowUserCount+'</td></tr>').appendTo(tableBody);
|
||||
if (subflowNode.meta) {
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.module")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).text(subflowNode.meta.module||"")
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.version")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).text(subflowNode.meta.version||"")
|
||||
}
|
||||
}
|
||||
|
||||
// var helpText = "";
|
||||
// if (node.type === "tab" || node.type === "subflow") {
|
||||
// } else {
|
||||
// if (subflowNode && node.type !== "subflow") {
|
||||
// // Selected a subflow instance node.
|
||||
// // - The subflow template info goes into help
|
||||
// helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'));
|
||||
// } else {
|
||||
// helpText = $("script[data-help-name='"+node.type+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
// }
|
||||
// setInfoText(helpText, helpSection.content);
|
||||
// }
|
||||
|
||||
var infoText = "";
|
||||
|
||||
if (node._def && node._def.info) {
|
||||
@ -409,23 +402,6 @@ RED.sidebar.info = (function() {
|
||||
}
|
||||
var infoSectionContainer = $("<div>").css("padding","0 6px 6px").appendTo(propertiesPanelContent)
|
||||
|
||||
// var editInfo = $('<button class="red-ui-button red-ui-button-small" style="float: right"><i class="fa fa-file-text-o"></button>').appendTo(infoSectionContainer).on("click", function(evt) {
|
||||
// //.text(RED._("sidebar.info.editDescription"))
|
||||
// evt.preventDefault();
|
||||
// evt.stopPropagation();
|
||||
// if (node.type === 'tab') {
|
||||
//
|
||||
// } else if (node.type === 'subflow') {
|
||||
//
|
||||
// } else if (node.type === 'group') {
|
||||
//
|
||||
// } else if (node._def.category !== 'config') {
|
||||
// RED.editor.edit(node,"editor-tab-description");
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
// })
|
||||
|
||||
setInfoText(infoText, infoSectionContainer);
|
||||
|
||||
$(".red-ui-sidebar-info-stack").scrollTop(0);
|
||||
|
@ -115,7 +115,13 @@ RED.userSettings = (function() {
|
||||
options: [
|
||||
{setting:"editor-language",local: true, label:"menu.label.view.language",options:function(done){ done([{val:'',text:RED._('menu.label.view.browserDefault')}].concat(RED.settings.theme("languages").map(localeToName).sort(compText))) }},
|
||||
]
|
||||
},{
|
||||
},
|
||||
// {
|
||||
// options: [
|
||||
// {setting:"theme", label:"Theme",options:function(done){ done([{val:'',text:'default'}].concat(RED.settings.theme("themes"))) }},
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
title: "menu.label.view.grid",
|
||||
options: [
|
||||
{setting:"view-show-grid",oldSetting:"menu-menu-item-view-show-grid",label:"menu.label.view.showGrid", default: true, toggle:true,onchange:"core:toggle-show-grid"},
|
||||
|
@ -615,18 +615,25 @@ RED.utils = (function() {
|
||||
return element;
|
||||
}
|
||||
|
||||
function normalisePropertyExpression(str) {
|
||||
function createError(code, message) {
|
||||
var e = new Error(message);
|
||||
e.code = code;
|
||||
return e;
|
||||
}
|
||||
|
||||
function normalisePropertyExpression(str,msg) {
|
||||
// This must be kept in sync with validatePropertyExpression
|
||||
// in editor/js/ui/utils.js
|
||||
|
||||
var length = str.length;
|
||||
if (length === 0) {
|
||||
throw new Error("Invalid property expression: zero-length");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: zero-length");
|
||||
}
|
||||
var parts = [];
|
||||
var start = 0;
|
||||
var inString = false;
|
||||
var inBox = false;
|
||||
var boxExpression = false;
|
||||
var quoteChar;
|
||||
var v;
|
||||
for (var i=0;i<length;i++) {
|
||||
@ -634,14 +641,14 @@ RED.utils = (function() {
|
||||
if (!inString) {
|
||||
if (c === "'" || c === '"') {
|
||||
if (i != start) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
inString = true;
|
||||
quoteChar = c;
|
||||
start = i+1;
|
||||
} else if (c === '.') {
|
||||
if (i===0) {
|
||||
throw new Error("Invalid property expression: unexpected . at position 0");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected . at position 0");
|
||||
}
|
||||
if (start != i) {
|
||||
v = str.substring(start,i);
|
||||
@ -652,57 +659,99 @@ RED.utils = (function() {
|
||||
}
|
||||
}
|
||||
if (i===length-1) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unterminated expression");
|
||||
}
|
||||
// Next char is first char of an identifier: a-z 0-9 $ _
|
||||
if (!/[a-z0-9\$\_]/i.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
} else if (c === '[') {
|
||||
if (i === 0) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
if (start != i) {
|
||||
parts.push(str.substring(start,i));
|
||||
}
|
||||
if (i===length-1) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unterminated expression");
|
||||
}
|
||||
// Next char is either a quote or a number
|
||||
if (!/["'\d]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
// Start of a new expression. If it starts with msg it is a nested expression
|
||||
// Need to scan ahead to find the closing bracket
|
||||
if (/^msg[.\[]/.test(str.substring(i+1))) {
|
||||
var depth = 1;
|
||||
var inLocalString = false;
|
||||
var localStringQuote;
|
||||
for (var j=i+1;j<length;j++) {
|
||||
if (/["']/.test(str[j])) {
|
||||
if (inLocalString) {
|
||||
if (str[j] === localStringQuote) {
|
||||
inLocalString = false
|
||||
}
|
||||
} else {
|
||||
inLocalString = true;
|
||||
localStringQuote = str[j]
|
||||
}
|
||||
}
|
||||
if (str[j] === '[') {
|
||||
depth++;
|
||||
} else if (str[j] === ']') {
|
||||
depth--;
|
||||
}
|
||||
if (depth === 0) {
|
||||
try {
|
||||
if (msg) {
|
||||
parts.push(getMessageProperty(msg, str.substring(i+1,j)))
|
||||
} else {
|
||||
parts.push(normalisePropertyExpression(str.substring(i+1,j), msg));
|
||||
}
|
||||
inBox = false;
|
||||
i = j;
|
||||
start = j+1;
|
||||
break;
|
||||
} catch(err) {
|
||||
throw createError("INVALID_EXPR","Invalid expression started at position "+(i+1))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (depth > 0) {
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unmatched '[' at position "+i);
|
||||
}
|
||||
continue;
|
||||
} else if (!/["'\d]/.test(str[i+1])) {
|
||||
// Next char is either a quote or a number
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
inBox = true;
|
||||
} else if (c === ']') {
|
||||
if (!inBox) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
if (start != i) {
|
||||
v = str.substring(start,i);
|
||||
if (/^\d+$/.test(v)) {
|
||||
parts.push(parseInt(v));
|
||||
} else {
|
||||
throw new Error("Invalid property expression: unexpected array expression at position "+start);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected array expression at position "+start);
|
||||
}
|
||||
}
|
||||
start = i+1;
|
||||
inBox = false;
|
||||
} else if (c === ' ') {
|
||||
throw new Error("Invalid property expression: unexpected ' ' at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected ' ' at position "+i);
|
||||
}
|
||||
} else {
|
||||
if (c === quoteChar) {
|
||||
if (i-start === 0) {
|
||||
throw new Error("Invalid property expression: zero-length string at position "+start);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: zero-length string at position "+start);
|
||||
}
|
||||
parts.push(str.substring(start,i));
|
||||
// If inBox, next char must be a ]. Otherwise it may be [ or .
|
||||
if (inBox && !/\]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected array expression at position "+start);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected array expression at position "+start);
|
||||
} else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
inString = false;
|
||||
@ -711,7 +760,7 @@ RED.utils = (function() {
|
||||
|
||||
}
|
||||
if (inBox || inString) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
throw new createError("INVALID_EXPR","Invalid property expression: unterminated expression");
|
||||
}
|
||||
if (start < length) {
|
||||
parts.push(str.substring(start));
|
||||
|
@ -2276,7 +2276,7 @@ RED.view = (function() {
|
||||
}
|
||||
|
||||
function calculateTextWidth(str, className) {
|
||||
var result=convertLineBreakCharacter(str);
|
||||
var result = convertLineBreakCharacter(str);
|
||||
var width = 0;
|
||||
for (var i=0;i<result.length;i++) {
|
||||
var calculateTextW=calculateTextDimensions(result[i],className)[0];
|
||||
|
@ -219,7 +219,7 @@ RED.user = (function() {
|
||||
|
||||
function init() {
|
||||
if (RED.settings.user) {
|
||||
if (!RED.settings.editorTheme || !RED.settings.editorTheme.hasOwnProperty("userMenu")) {
|
||||
if (!RED.settings.editorTheme || !RED.settings.editorTheme.hasOwnProperty("userMenu") || RED.settings.editorTheme.userMenu) {
|
||||
|
||||
var userMenu = $('<li><a id="red-ui-header-button-user" class="button hide" href="#"></a></li>')
|
||||
.prependTo(".red-ui-header-toolbar");
|
||||
|
@ -15,6 +15,9 @@
|
||||
**/
|
||||
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.red-ui-editor {
|
||||
font-size: $primary-font-size;
|
||||
|
@ -765,6 +765,10 @@ button.red-ui-toggleButton.toggle {
|
||||
width: calc(100% - 10px);
|
||||
padding-left: 3px;
|
||||
}
|
||||
select {
|
||||
padding: 0 3px;
|
||||
font-size: 11px;
|
||||
}
|
||||
.placeholder-input {
|
||||
span:first-child {
|
||||
display:inline-block;
|
||||
|
@ -139,6 +139,9 @@
|
||||
stroke-width: 2;
|
||||
}
|
||||
.red-ui-flow-node-icon-group {
|
||||
text {
|
||||
@include disable-selection;
|
||||
}
|
||||
.fa-lg {
|
||||
@include disable-selection;
|
||||
stroke: none;
|
||||
|
@ -29,8 +29,30 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.red-ui-clipboard-dialog-tab-clipboard {
|
||||
|
||||
#red-ui-clipboard-dialog-export-tab-clipboard-preview {
|
||||
.red-ui-treeList-container,.red-ui-editableList-border {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
#red-ui-clipboard-dialog-export-tab-clipboard-json {
|
||||
padding: 10px 10px 0;
|
||||
}
|
||||
#red-ui-clipboard-dialog-import-tab-clipboard {
|
||||
padding: 10px;
|
||||
}
|
||||
.red-ui-clipboard-dialog-export-tab-clipboard-tab {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.red-ui-clipboard-dialog-tab-clipboard {
|
||||
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
|
@ -131,10 +131,10 @@
|
||||
width: 120px;
|
||||
background-size: contain;
|
||||
position: relative;
|
||||
&:not(.red-ui-palette-node-config):first-child {
|
||||
&:not(.red-ui-palette-node-config):not(.red-ui-palette-node-small):first-child {
|
||||
margin-top: 15px;
|
||||
}
|
||||
&:not(.red-ui-palette-node-config):last-child {
|
||||
&:not(.red-ui-palette-node-config):not(.red-ui-palette-node-small):first-child {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ div.red-ui-info-table {
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
}
|
||||
}
|
||||
.red-ui-info-outline,.red-ui-sidebar-help-toc, #red-ui-clipboard-dialog-import-conflicts-list {
|
||||
.red-ui-info-outline,.red-ui-sidebar-help-toc, #red-ui-clipboard-dialog-import-conflicts-list, #red-ui-clipboard-dialog-export-tab-clipboard-preview {
|
||||
.red-ui-info-outline-item {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
|
@ -26,6 +26,14 @@
|
||||
box-sizing: border-box;
|
||||
overflow:visible;
|
||||
position: relative;
|
||||
&[disabled] {
|
||||
input, button {
|
||||
background: $secondary-background-inactive;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.red-ui-typedInput-input-wrap {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
color:"#c0edc0",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
scope: {value:[]},
|
||||
scope: {value:[], type:"*[]"},
|
||||
uncaught: {value:false}
|
||||
},
|
||||
inputs:0,
|
||||
|
@ -30,7 +30,7 @@
|
||||
color:"#e49191",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
scope: {value:null},
|
||||
scope: {value:null, type:"*[]"},
|
||||
uncaught: {value:false}
|
||||
},
|
||||
inputs:0,
|
||||
|
@ -26,7 +26,7 @@
|
||||
color:"#94c1d0",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
scope: {value:null}
|
||||
scope: {value:null, type:"*[]"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
|
@ -187,7 +187,7 @@
|
||||
color:"#ddd",//"#87D8CF",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
links: { value: [] }
|
||||
links: { value: [], type:"link out[]" }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
@ -216,7 +216,7 @@
|
||||
color:"#ddd",//"#87D8CF",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
links: { value: []}
|
||||
links: { value: [], type:"link in[]"}
|
||||
},
|
||||
align:"right",
|
||||
inputs:1,
|
||||
|
@ -168,6 +168,10 @@ module.exports = function(RED) {
|
||||
return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done);
|
||||
} else if (rule.fromt === 'flow' || rule.fromt === 'global') {
|
||||
var contextKey = RED.util.parseContextStore(rule.from);
|
||||
if (/\[msg\./.test(context.key)) {
|
||||
// The key has a nest msg. reference to evaluate first
|
||||
context.key = RED.util.normalisePropertyExpression(contextKey.key,msg,true);
|
||||
}
|
||||
node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => {
|
||||
if (err) {
|
||||
done(err)
|
||||
@ -243,6 +247,10 @@ module.exports = function(RED) {
|
||||
return done(undefined,msg);
|
||||
} else if (rule.pt === 'flow' || rule.pt === 'global') {
|
||||
var contextKey = RED.util.parseContextStore(property);
|
||||
if (/\[msg/.test(contextKey.key)) {
|
||||
// The key has a nest msg. reference to evaluate first
|
||||
contextKey.key = RED.util.normalisePropertyExpression(contextKey.key, msg, true)
|
||||
}
|
||||
var target = node.context()[rule.pt];
|
||||
var callback = err => {
|
||||
if (err) {
|
||||
|
@ -80,10 +80,10 @@ module.exports = function(RED) {
|
||||
this.drop = n.drop;
|
||||
var node = this;
|
||||
|
||||
function ourTimeout(handler, delay) {
|
||||
function ourTimeout(handler, delay, clearHandler) {
|
||||
var toutID = setTimeout(handler, delay);
|
||||
return {
|
||||
clear: function() { clearTimeout(toutID); },
|
||||
clear: function() { clearTimeout(toutID); clearHandler(); },
|
||||
trigger: function() { clearTimeout(toutID); return handler(); }
|
||||
};
|
||||
}
|
||||
@ -113,14 +113,15 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
if (node.pauseType === "delay") {
|
||||
node.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); }
|
||||
node.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); done(); }
|
||||
else {
|
||||
var id = ourTimeout(function() {
|
||||
node.idList.splice(node.idList.indexOf(id),1);
|
||||
if (node.idList.length === 0) { node.status({}); }
|
||||
node.send(msg);
|
||||
}, node.timeout);
|
||||
send(msg);
|
||||
done();
|
||||
}, node.timeout, () => done());
|
||||
node.idList.push(id);
|
||||
if ((node.timeout > 1000) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:" "});
|
||||
@ -131,7 +132,7 @@ module.exports = function(RED) {
|
||||
node.on("close", function() { clearDelayList(); });
|
||||
}
|
||||
else if (node.pauseType === "delayv") {
|
||||
node.on("input", function(msg) {
|
||||
node.on("input", function(msg, send, done) {
|
||||
var delayvar = Number(node.timeout);
|
||||
if (msg.hasOwnProperty("delay") && !isNaN(parseFloat(msg.delay))) {
|
||||
delayvar = parseFloat(msg.delay);
|
||||
@ -140,8 +141,9 @@ module.exports = function(RED) {
|
||||
var id = ourTimeout(function() {
|
||||
node.idList.splice(node.idList.indexOf(id),1);
|
||||
if (node.idList.length === 0) { node.status({}); }
|
||||
node.send(msg);
|
||||
}, delayvar);
|
||||
send(msg);
|
||||
done();
|
||||
}, delayvar, () => done());
|
||||
node.idList.push(id);
|
||||
if ((delayvar >= 0) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:delayvar/1000+"s"});
|
||||
@ -152,7 +154,7 @@ module.exports = function(RED) {
|
||||
node.on("close", function() { clearDelayList(); });
|
||||
}
|
||||
else if (node.pauseType === "rate") {
|
||||
node.on("input", function(msg) {
|
||||
node.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (node.intervalID !== -1 ) {
|
||||
clearInterval(node.intervalID);
|
||||
@ -161,17 +163,18 @@ module.exports = function(RED) {
|
||||
delete node.lastSent;
|
||||
node.buffer = [];
|
||||
node.status({text:"reset"});
|
||||
done();
|
||||
return;
|
||||
}
|
||||
if (!node.drop) {
|
||||
var m = RED.util.cloneMessage(msg);
|
||||
delete m.flush;
|
||||
if (node.intervalID !== -1) {
|
||||
node.buffer.push(m);
|
||||
node.buffer.push({msg: m, send: send, done: done});
|
||||
node.reportDepth();
|
||||
}
|
||||
else {
|
||||
node.send(m);
|
||||
send(m);
|
||||
node.reportDepth();
|
||||
node.intervalID = setInterval(function() {
|
||||
if (node.buffer.length === 0) {
|
||||
@ -179,16 +182,22 @@ module.exports = function(RED) {
|
||||
node.intervalID = -1;
|
||||
}
|
||||
if (node.buffer.length > 0) {
|
||||
node.send(node.buffer.shift());
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
node.reportDepth();
|
||||
}, node.rate);
|
||||
done();
|
||||
}
|
||||
if (msg.hasOwnProperty("flush")) {
|
||||
while (node.buffer.length > 0) {
|
||||
node.send(node.buffer.shift());
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
node.status({});
|
||||
done();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -198,17 +207,19 @@ module.exports = function(RED) {
|
||||
}
|
||||
if (!node.lastSent) { // ensuring that we always send the first message
|
||||
node.lastSent = process.hrtime();
|
||||
node.send(msg);
|
||||
send(msg);
|
||||
}
|
||||
else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
|
||||
node.lastSent = process.hrtime();
|
||||
node.send(msg);
|
||||
send(msg);
|
||||
}
|
||||
done();
|
||||
}
|
||||
});
|
||||
node.on("close", function() {
|
||||
clearInterval(node.intervalID);
|
||||
clearTimeout(node.busy);
|
||||
node.buffer.forEach((msgInfo) => msgInfo.done());
|
||||
node.buffer = [];
|
||||
node.status({});
|
||||
});
|
||||
@ -217,57 +228,75 @@ module.exports = function(RED) {
|
||||
node.intervalID = setInterval(function() {
|
||||
if (node.pauseType === "queue") {
|
||||
if (node.buffer.length > 0) {
|
||||
node.send(node.buffer.shift()); // send the first on the queue
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg); // send the first on the queue
|
||||
msgInfo.done();
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (node.buffer.length > 0) { // send the whole queue
|
||||
node.send(node.buffer.shift());
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
}
|
||||
node.reportDepth();
|
||||
},node.rate);
|
||||
|
||||
var hit;
|
||||
node.on("input", function(msg) {
|
||||
node.on("input", function(msg, send, done) {
|
||||
if (!msg.hasOwnProperty("topic")) { msg.topic = "_none_"; }
|
||||
hit = false;
|
||||
for (var b in node.buffer) { // check if already in queue
|
||||
if (msg.topic === node.buffer[b].topic) {
|
||||
node.buffer[b] = msg; // if so - replace existing entry
|
||||
if (msg.topic === node.buffer[b].msg.topic) {
|
||||
node.buffer[b].done();
|
||||
node.buffer[b] = {msg, send, done}; // if so - replace existing entry
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hit) {
|
||||
node.buffer.push(msg); // if not add to end of queue
|
||||
node.buffer.push({msg, send, done}); // if not add to end of queue
|
||||
node.reportDepth();
|
||||
}
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
while (node.buffer.length > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.done();
|
||||
}
|
||||
node.buffer = [];
|
||||
node.status({text:"reset"});
|
||||
done();
|
||||
}
|
||||
if (msg.hasOwnProperty("flush")) {
|
||||
while (node.buffer.length > 0) {
|
||||
node.send(node.buffer.shift());
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
node.status({});
|
||||
done();
|
||||
}
|
||||
});
|
||||
node.on("close", function() {
|
||||
clearInterval(node.intervalID);
|
||||
while (node.buffer.length > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
msgInfo.done();
|
||||
}
|
||||
node.buffer = [];
|
||||
node.status({});
|
||||
});
|
||||
}
|
||||
else if (node.pauseType === "random") {
|
||||
node.on("input", function(msg) {
|
||||
node.on("input", function(msg, send, done) {
|
||||
var wait = node.randomFirst + (node.diff * Math.random());
|
||||
var id = ourTimeout(function() {
|
||||
node.idList.splice(node.idList.indexOf(id),1);
|
||||
node.send(msg);
|
||||
send(msg);
|
||||
node.status({});
|
||||
}, wait);
|
||||
done();
|
||||
}, wait, () => done());
|
||||
node.idList.push(id);
|
||||
if ((node.timeout >= 1000) && (node.idList.length !== 0)) {
|
||||
node.status({fill:"blue",shape:"dot",text:parseInt(wait/10)/100+"s"});
|
||||
|
@ -82,10 +82,10 @@ module.exports = function(RED) {
|
||||
var npay = {};
|
||||
var pendingMessages = [];
|
||||
var activeMessagePromise = null;
|
||||
var processMessageQueue = function(msg) {
|
||||
if (msg) {
|
||||
var processMessageQueue = function(msgInfo) {
|
||||
if (msgInfo) {
|
||||
// A new message has arrived - add it to the message queue
|
||||
pendingMessages.push(msg);
|
||||
pendingMessages.push(msgInfo);
|
||||
if (activeMessagePromise !== null) {
|
||||
// The node is currently processing a message, so do nothing
|
||||
// more with this message
|
||||
@ -101,17 +101,17 @@ module.exports = function(RED) {
|
||||
|
||||
// There are more messages to process. Get the next message and
|
||||
// start processing it. Recurse back in to check for any more
|
||||
var nextMsg = pendingMessages.shift();
|
||||
activeMessagePromise = processMessage(nextMsg)
|
||||
var nextMsgInfo = pendingMessages.shift();
|
||||
activeMessagePromise = processMessage(nextMsgInfo)
|
||||
.then(processMessageQueue)
|
||||
.catch((err) => {
|
||||
node.error(err,nextMsg);
|
||||
nextMsgInfo.done(err);
|
||||
return processMessageQueue();
|
||||
});
|
||||
}
|
||||
|
||||
this.on('input', function(msg) {
|
||||
processMessageQueue(msg);
|
||||
this.on('input', function(msg, send, done) {
|
||||
processMessageQueue({msg, send, done});
|
||||
});
|
||||
|
||||
var stat = function() {
|
||||
@ -121,7 +121,8 @@ module.exports = function(RED) {
|
||||
else return {fill:"blue",shape:"dot",text:l};
|
||||
}
|
||||
|
||||
var processMessage = function(msg) {
|
||||
var processMessage = function(msgInfo) {
|
||||
let msg = msgInfo.msg;
|
||||
var topic = RED.util.getMessageProperty(msg,node.topic) || "_none";
|
||||
var promise;
|
||||
var delayDuration = node.duration;
|
||||
@ -179,7 +180,10 @@ module.exports = function(RED) {
|
||||
/* istanbul ignore else */
|
||||
if (node.op1type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
node.topics[topic].tout = setInterval(function() { node.send(RED.util.cloneMessage(msg2)); }, delayDuration);
|
||||
node.topics[topic].tout = setInterval(function() {
|
||||
if (node.op1type === "date") { msg2.payload = Date.now(); }
|
||||
msgInfo.send(RED.util.cloneMessage(msg2));
|
||||
}, delayDuration);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -203,14 +207,15 @@ module.exports = function(RED) {
|
||||
}
|
||||
promise.then(() => {
|
||||
if (node.op2type === "payl") {
|
||||
if (node.second === true) { node.send([null,npay[topic]]); }
|
||||
else { node.send(npay[topic]); }
|
||||
if (node.second === true) { msgInfo.send([null,npay[topic]]); }
|
||||
else { msgInfo.send(npay[topic]); }
|
||||
delete npay[topic];
|
||||
}
|
||||
else {
|
||||
msg2.payload = node.topics[topic].m2;
|
||||
if (node.second === true) { node.send([null,msg2]); }
|
||||
else { node.send(msg2); }
|
||||
if (node.op2type === "date") { msg2.payload = Date.now(); }
|
||||
if (node.second === true) { msgInfo.send([null,msg2]); }
|
||||
else { msgInfo.send(msg2); }
|
||||
}
|
||||
delete node.topics[topic];
|
||||
node.status(stat());
|
||||
@ -225,8 +230,9 @@ module.exports = function(RED) {
|
||||
}, delayDuration);
|
||||
}
|
||||
}
|
||||
msgInfo.done();
|
||||
node.status(stat());
|
||||
if (node.op1type !== "nul") { node.send(RED.util.cloneMessage(msg)); }
|
||||
if (node.op1type !== "nul") { msgInfo.send(RED.util.cloneMessage(msg)); }
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -262,8 +268,8 @@ module.exports = function(RED) {
|
||||
}
|
||||
delete node.topics[topic];
|
||||
node.status(stat());
|
||||
if (node.second === true) { node.send([null,msg2]); }
|
||||
else { node.send(msg2); }
|
||||
if (node.second === true) { msgInfo.send([null,msg2]); }
|
||||
else { msgInfo.send(msg2); }
|
||||
}).catch(err => {
|
||||
node.error(err);
|
||||
});
|
||||
@ -273,6 +279,7 @@ module.exports = function(RED) {
|
||||
// if (node.op2type === "payl") {node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
|
||||
// }
|
||||
}
|
||||
msgInfo.done();
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.on("close", function() {
|
||||
|
@ -52,7 +52,7 @@
|
||||
color:"darksalmon",
|
||||
defaults: {
|
||||
command: {value:""},
|
||||
addpay: {value:true},
|
||||
addpay: {value:false},
|
||||
append: {value:""},
|
||||
useSpawn: {value:"false"},
|
||||
timer: {value:""},
|
||||
|
@ -31,12 +31,12 @@ module.exports = function(RED) {
|
||||
this.timer = Number(n.timer || 0)*1000;
|
||||
this.activeProcesses = {};
|
||||
this.oldrc = (n.oldrc || false).toString();
|
||||
this.execOpt = {encoding:'binary', maxBuffer:10000000};
|
||||
this.execOpt = {encoding:'binary', maxBuffer:RED.settings.execMaxBufferSize||10000000};
|
||||
var node = this;
|
||||
|
||||
if (process.platform === 'linux' && fs.existsSync('/bin/bash')) { node.execOpt.shell = '/bin/bash'; }
|
||||
if (process.platform === 'linux' && fs.existsSync('/bin/bash')) { node.execOpt.shell = '/bin/bash'; }
|
||||
|
||||
var cleanup = function(p) {
|
||||
var cleanup = function(p) {
|
||||
node.activeProcesses[p].kill();
|
||||
//node.status({fill:"red",shape:"dot",text:"timeout"});
|
||||
//node.error("Exec node timeout");
|
||||
|
@ -210,7 +210,7 @@ module.exports = function(RED) {
|
||||
var httpMiddleware = function(req,res,next) { next(); }
|
||||
|
||||
if (RED.settings.httpNodeMiddleware) {
|
||||
if (typeof RED.settings.httpNodeMiddleware === "function") {
|
||||
if (typeof RED.settings.httpNodeMiddleware === "function" || Array.isArray(RED.settings.httpNodeMiddleware)) {
|
||||
httpMiddleware = RED.settings.httpNodeMiddleware;
|
||||
}
|
||||
}
|
||||
|
@ -235,6 +235,7 @@
|
||||
oneditprepare: function() {
|
||||
var previous = null;
|
||||
$("#node-input-out").on('focus', function () { previous = this.value; }).on("change", function() {
|
||||
$("#node-input-splitc").show();
|
||||
if (previous === null) { previous = $("#node-input-out").val(); }
|
||||
if ($("#node-input-out").val() == "char") {
|
||||
if (previous != "char") { $("#node-input-splitc").val("\\n"); }
|
||||
@ -247,6 +248,7 @@
|
||||
else if ($("#node-input-out").val() == "immed") {
|
||||
if (previous != "immed") { $("#node-input-splitc").val(" "); }
|
||||
$("#node-units").text("");
|
||||
$("#node-input-splitc").hide();
|
||||
}
|
||||
else if ($("#node-input-out").val() == "count") {
|
||||
if (previous != "count") { $("#node-input-splitc").val("12"); }
|
||||
@ -255,6 +257,7 @@
|
||||
else {
|
||||
if (previous != "sit") { $("#node-input-splitc").val(" "); }
|
||||
$("#node-units").text("");
|
||||
$("#node-input-splitc").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ module.exports = function(RED) {
|
||||
"use strict";
|
||||
function CSVNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.template = (n.temp || "").split(",");
|
||||
this.template = (n.temp || "");
|
||||
this.sep = (n.sep || ',').replace("\\t","\t").replace("\\n","\n").replace("\\r","\r");
|
||||
this.quo = '"';
|
||||
this.ret = (n.ret || "\n").replace("\\n","\n").replace("\\r","\r");
|
||||
@ -38,16 +38,12 @@ module.exports = function(RED) {
|
||||
if (this.hdrout === true) { this.hdrout = "all"; }
|
||||
var tmpwarn = true;
|
||||
var node = this;
|
||||
var re = new RegExp(',(?=(?:(?:[^"]*"){2})*[^"]*$)','g');
|
||||
|
||||
// pass in an array of column names to be trimed, de-quoted and retrimed
|
||||
var clean = function(col) {
|
||||
for (var t = 0; t < col.length; t++) {
|
||||
col[t] = col[t].trim(); // remove leading and trailing whitespace
|
||||
if (col[t].charAt(0) === '"' && col[t].charAt(col[t].length -1) === '"') {
|
||||
// remove leading and trailing quotes (if they exist) - and remove whitepace again.
|
||||
col[t] = col[t].substr(1,col[t].length -2).trim();
|
||||
}
|
||||
}
|
||||
col = col.trim().split(re) || [""];
|
||||
col = col.map(x => x.replace(/"/g,'').trim());
|
||||
if ((col.length === 1) && (col[0] === "")) { node.goodtmpl = false; }
|
||||
else { node.goodtmpl = true; }
|
||||
return col;
|
||||
@ -55,7 +51,7 @@ module.exports = function(RED) {
|
||||
node.template = clean(node.template);
|
||||
node.hdrSent = false;
|
||||
|
||||
this.on("input", function(msg) {
|
||||
this.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
node.hdrSent = false;
|
||||
}
|
||||
@ -67,13 +63,14 @@ module.exports = function(RED) {
|
||||
if (node.hdrout !== "none" && node.hdrSent === false) {
|
||||
if ((node.template.length === 1) && (node.template[0] === '')) {
|
||||
if (msg.hasOwnProperty("columns")) {
|
||||
node.template = clean((msg.columns || "").split(","));
|
||||
node.template = clean(msg.columns || "");
|
||||
}
|
||||
else {
|
||||
node.template = Object.keys(msg.payload[0]);
|
||||
}
|
||||
}
|
||||
ou += node.template.join(node.sep) + node.ret;
|
||||
// ou += node.template.join(node.sep) + node.ret;
|
||||
ou += node.template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep) + node.ret;
|
||||
if (node.hdrout === "once") { node.hdrSent = true; }
|
||||
}
|
||||
for (var s = 0; s < msg.payload.length; s++) {
|
||||
@ -93,7 +90,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
else {
|
||||
if ((node.template.length === 1) && (node.template[0] === '') && (msg.hasOwnProperty("columns"))) {
|
||||
node.template = clean((msg.columns || "").split(","));
|
||||
node.template = clean(msg.columns || "")//.split(","));
|
||||
}
|
||||
if ((node.template.length === 1) && (node.template[0] === '')) {
|
||||
/* istanbul ignore else */
|
||||
@ -144,10 +141,11 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
msg.payload = ou;
|
||||
msg.columns = node.template.join(',');
|
||||
if (msg.payload !== '') { node.send(msg); }
|
||||
msg.columns = node.template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
|
||||
if (msg.payload !== '') { send(msg); }
|
||||
done();
|
||||
}
|
||||
catch(e) { node.error(e,msg); }
|
||||
catch(e) { done(e); }
|
||||
}
|
||||
else if (typeof msg.payload == "string") { // convert CSV string to object
|
||||
try {
|
||||
@ -178,7 +176,7 @@ module.exports = function(RED) {
|
||||
if ((node.hdrin === true) && first) { // if the template is in the first line
|
||||
if ((line[i] === "\n")||(line[i] === "\r")||(line.length - i === 1)) { // look for first line break
|
||||
if (line.length - i === 1) { tmp += line[i]; }
|
||||
node.template = clean(tmp.split(node.sep));
|
||||
node.template = clean(tmp);
|
||||
first = false;
|
||||
}
|
||||
else { tmp += line[i]; }
|
||||
@ -254,22 +252,22 @@ module.exports = function(RED) {
|
||||
}
|
||||
if (msg.parts.index + 1 === msg.parts.count) {
|
||||
msg.payload = node.store;
|
||||
msg.columns = node.template.filter(val => val).join(',');
|
||||
msg.columns = node.template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
|
||||
delete msg.parts;
|
||||
node.send(msg);
|
||||
send(msg);
|
||||
node.store = [];
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg.columns = node.template.filter(val => val).join(',');
|
||||
node.send(msg); // finally send the array
|
||||
msg.columns = node.template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
|
||||
send(msg); // finally send the array
|
||||
}
|
||||
}
|
||||
else {
|
||||
var len = a.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var newMessage = RED.util.cloneMessage(msg);
|
||||
newMessage.columns = node.template.filter(val => val).join(',');
|
||||
newMessage.columns = node.template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
|
||||
newMessage.payload = a[i];
|
||||
if (!has_parts) {
|
||||
newMessage.parts = {
|
||||
@ -286,19 +284,21 @@ module.exports = function(RED) {
|
||||
newMessage.parts.count -= 1;
|
||||
}
|
||||
}
|
||||
node.send(newMessage);
|
||||
send(newMessage);
|
||||
}
|
||||
}
|
||||
node.linecount = 0;
|
||||
done();
|
||||
}
|
||||
catch(e) { node.error(e,msg); }
|
||||
catch(e) { done(e); }
|
||||
}
|
||||
else { node.warn(RED._("csv.errors.csv_js")); }
|
||||
else { node.warn(RED._("csv.errors.csv_js")); done(); }
|
||||
}
|
||||
else {
|
||||
if (!msg.hasOwnProperty("reset")) {
|
||||
node.send(msg); // If no payload and not reset - just pass it on.
|
||||
send(msg); // If no payload and not reset - just pass it on.
|
||||
}
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -17,18 +17,18 @@
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
|
||||
function sendArray(node,msg,array) {
|
||||
function sendArray(node,msg,array,send) {
|
||||
for (var i = 0; i < array.length-1; i++) {
|
||||
msg.payload = array[i];
|
||||
msg.parts.index = node.c++;
|
||||
if (node.stream !== true) { msg.parts.count = array.length; }
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
}
|
||||
if (node.stream !== true) {
|
||||
msg.payload = array[i];
|
||||
msg.parts.index = node.c++;
|
||||
msg.parts.count = array.length;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
node.c = 0;
|
||||
}
|
||||
else { node.remainder = array[i]; }
|
||||
@ -67,7 +67,8 @@ module.exports = function(RED) {
|
||||
}
|
||||
node.c = 0;
|
||||
node.buffer = Buffer.from([]);
|
||||
this.on("input", function(msg) {
|
||||
node.pendingDones = [];
|
||||
this.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("payload")) {
|
||||
if (msg.hasOwnProperty("parts")) { msg.parts = { parts:msg.parts }; } // push existing parts to a stack
|
||||
else { msg.parts = {}; }
|
||||
@ -93,14 +94,23 @@ module.exports = function(RED) {
|
||||
msg.payload = data.substring(pos,pos+node.splt);
|
||||
msg.parts.index = node.c++;
|
||||
pos += node.splt;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
}
|
||||
if (count > 1) {
|
||||
node.pendingDones.forEach(d => d());
|
||||
node.pendingDones = [];
|
||||
}
|
||||
node.remainder = data.substring(pos);
|
||||
if ((node.stream !== true) || (node.remainder.length === node.splt)) {
|
||||
msg.payload = node.remainder;
|
||||
msg.parts.index = node.c++;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
node.pendingDones.forEach(d => d());
|
||||
node.pendingDones = [];
|
||||
done();
|
||||
node.remainder = "";
|
||||
} else {
|
||||
node.pendingDones.push(done);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -115,7 +125,8 @@ module.exports = function(RED) {
|
||||
a = msg.payload.split(node.splt);
|
||||
msg.parts.ch = node.splt; // pass the split char to other end for rejoin
|
||||
}
|
||||
sendArray(node,msg,a);
|
||||
sendArray(node,msg,a,send);
|
||||
done();
|
||||
}
|
||||
}
|
||||
else if (Array.isArray(msg.payload)) { // then split array into messages
|
||||
@ -135,8 +146,9 @@ module.exports = function(RED) {
|
||||
}
|
||||
msg.parts.index = i;
|
||||
pos += node.arraySplt;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
}
|
||||
done();
|
||||
}
|
||||
else if ((typeof msg.payload === "object") && !Buffer.isBuffer(msg.payload)) {
|
||||
var j = 0;
|
||||
@ -152,10 +164,11 @@ module.exports = function(RED) {
|
||||
msg.parts.key = p;
|
||||
msg.parts.index = j;
|
||||
msg.parts.count = l;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
else if (Buffer.isBuffer(msg.payload)) {
|
||||
var len = node.buffer.length + msg.payload.length;
|
||||
@ -176,14 +189,23 @@ module.exports = function(RED) {
|
||||
msg.payload = buff.slice(pos,pos+node.splt);
|
||||
msg.parts.index = node.c++;
|
||||
pos += node.splt;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
}
|
||||
if (count > 1) {
|
||||
node.pendingDones.forEach(d => d());
|
||||
node.pendingDones = [];
|
||||
}
|
||||
node.buffer = buff.slice(pos);
|
||||
if ((node.stream !== true) || (node.buffer.length === node.splt)) {
|
||||
msg.payload = node.buffer;
|
||||
msg.parts.index = node.c++;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
node.pendingDones.forEach(d => d());
|
||||
node.pendingDones = [];
|
||||
done();
|
||||
node.buffer = Buffer.from([]);
|
||||
} else {
|
||||
node.pendingDones.push(done);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -210,23 +232,34 @@ module.exports = function(RED) {
|
||||
while (pos > -1) {
|
||||
msg.payload = buff.slice(p,pos);
|
||||
msg.parts.index = node.c++;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
i++;
|
||||
p = pos+node.splt.length;
|
||||
pos = buff.indexOf(node.splt,p);
|
||||
}
|
||||
if (count > 1) {
|
||||
node.pendingDones.forEach(d => d());
|
||||
node.pendingDones = [];
|
||||
}
|
||||
if ((node.stream !== true) && (p < buff.length)) {
|
||||
msg.payload = buff.slice(p,buff.length);
|
||||
msg.parts.index = node.c++;
|
||||
msg.parts.count = node.c++;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
send(RED.util.cloneMessage(msg));
|
||||
node.pendingDones.forEach(d => d());
|
||||
node.pendingDones = [];
|
||||
}
|
||||
else {
|
||||
node.buffer = buff.slice(p,buff.length);
|
||||
node.pendingDones.push(done);
|
||||
}
|
||||
if (node.buffer.length == 0) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
} else { // otherwise drop the message.
|
||||
done();
|
||||
}
|
||||
//else { } // otherwise drop the message.
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -264,16 +297,16 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
|
||||
function reduceMessageGroup(node,msgs,exp,fixup,count,accumulator,done) {
|
||||
var msg = msgs.shift();
|
||||
exp.assign("I", msg.parts.index);
|
||||
function reduceMessageGroup(node,msgInfos,exp,fixup,count,accumulator,done) {
|
||||
var msgInfo = msgInfos.shift();
|
||||
exp.assign("I", msgInfo.msg.parts.index);
|
||||
exp.assign("N", count);
|
||||
exp.assign("A", accumulator);
|
||||
RED.util.evaluateJSONataExpression(exp, msg, (err,result) => {
|
||||
RED.util.evaluateJSONataExpression(exp, msgInfo.msg, (err,result) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
if (msgs.length === 0) {
|
||||
if (msgInfos.length === 0) {
|
||||
if (fixup) {
|
||||
fixup.assign("N", count);
|
||||
fixup.assign("A", result);
|
||||
@ -281,39 +314,43 @@ module.exports = function(RED) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
node.send({payload: result});
|
||||
msgInfo.send({payload: result});
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
node.send({payload: result});
|
||||
msgInfo.send({payload: result});
|
||||
done();
|
||||
}
|
||||
} else {
|
||||
reduceMessageGroup(node,msgs,exp,fixup,count,result,done);
|
||||
reduceMessageGroup(node,msgInfos,exp,fixup,count,result,done);
|
||||
}
|
||||
});
|
||||
}
|
||||
function reduceAndSendGroup(node, group, done) {
|
||||
var is_right = node.reduce_right;
|
||||
var flag = is_right ? -1 : 1;
|
||||
var msgs = group.msgs;
|
||||
var msgInfos = group.msgs;
|
||||
const preservedMsgInfos = [...msgInfos];
|
||||
try {
|
||||
RED.util.evaluateNodeProperty(node.exp_init, node.exp_init_type, node, {}, (err,accum) => {
|
||||
var reduceExpression = node.reduceExpression;
|
||||
var fixupExpression = node.fixupExpression;
|
||||
var count = group.count;
|
||||
msgs.sort(function(x,y) {
|
||||
var ix = x.parts.index;
|
||||
var iy = y.parts.index;
|
||||
msgInfos.sort(function(x,y) {
|
||||
var ix = x.msg.parts.index;
|
||||
var iy = y.msg.parts.index;
|
||||
if (ix < iy) {return -flag;}
|
||||
if (ix > iy) {return flag;}
|
||||
return 0;
|
||||
});
|
||||
reduceMessageGroup(node, msgs,reduceExpression,fixupExpression,count,accum,(err,result) => {
|
||||
reduceMessageGroup(node, msgInfos,reduceExpression,fixupExpression,count,accum,(err,result) => {
|
||||
if (err) {
|
||||
preservedMsgInfos.pop(); // omit last message to emit error message
|
||||
preservedMsgInfos.forEach(mInfo => mInfo.done());
|
||||
done(err);
|
||||
return;
|
||||
} else {
|
||||
preservedMsgInfos.forEach(mInfo => mInfo.done());
|
||||
done();
|
||||
}
|
||||
})
|
||||
@ -323,7 +360,8 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
|
||||
function reduceMessage(node, msg, done) {
|
||||
function reduceMessage(node, msgInfo, done) {
|
||||
let msg = msgInfo.msg;
|
||||
if (msg.hasOwnProperty('parts')) {
|
||||
var parts = msg.parts;
|
||||
var pending = node.pending;
|
||||
@ -344,7 +382,7 @@ module.exports = function(RED) {
|
||||
if (parts.hasOwnProperty('count') && (group.count === undefined)) {
|
||||
group.count = parts.count;
|
||||
}
|
||||
msgs.push(msg);
|
||||
msgs.push(msgInfo);
|
||||
pending_count++;
|
||||
var completeProcess = function(err) {
|
||||
if (err) {
|
||||
@ -353,6 +391,13 @@ module.exports = function(RED) {
|
||||
node.pending_count = pending_count;
|
||||
var max_msgs = maxKeptMsgsCount(node);
|
||||
if ((max_msgs > 0) && (pending_count > max_msgs)) {
|
||||
Object.values(node.pending).forEach(group => {
|
||||
group.msgs.forEach(mInfo => {
|
||||
if (mInfo.msg._msgid !== msgInfo.msg._msgid) {
|
||||
mInfo.done();
|
||||
}
|
||||
});
|
||||
});
|
||||
node.pending = {};
|
||||
node.pending_count = 0;
|
||||
done(RED._("join.too-many"));
|
||||
@ -368,7 +413,8 @@ module.exports = function(RED) {
|
||||
completeProcess();
|
||||
}
|
||||
} else {
|
||||
node.send(msg);
|
||||
msgInfo.send(msg);
|
||||
msgInfo.done();
|
||||
done();
|
||||
}
|
||||
}
|
||||
@ -480,7 +526,9 @@ module.exports = function(RED) {
|
||||
delete group.msg.parts;
|
||||
}
|
||||
delete group.msg.complete;
|
||||
node.send(RED.util.cloneMessage(group.msg));
|
||||
group.send(RED.util.cloneMessage(group.msg));
|
||||
group.dones.forEach(f => f());
|
||||
group.dones = [];
|
||||
}
|
||||
|
||||
var pendingMessages = [];
|
||||
@ -489,10 +537,10 @@ module.exports = function(RED) {
|
||||
// groups may overlap and cause unexpected results. The use of JSONata
|
||||
// means some async processing *might* occur if flow/global context is
|
||||
// accessed.
|
||||
var processReduceMessageQueue = function(msg) {
|
||||
if (msg) {
|
||||
var processReduceMessageQueue = function(msgInfo) {
|
||||
if (msgInfo) {
|
||||
// A new message has arrived - add it to the message queue
|
||||
pendingMessages.push(msg);
|
||||
pendingMessages.push(msgInfo);
|
||||
if (activeMessage !== null) {
|
||||
// The node is currently processing a message, so do nothing
|
||||
// more with this message
|
||||
@ -508,22 +556,23 @@ module.exports = function(RED) {
|
||||
|
||||
// There are more messages to process. Get the next message and
|
||||
// start processing it. Recurse back in to check for any more
|
||||
var nextMsg = pendingMessages.shift();
|
||||
var nextMsgInfo = pendingMessages.shift();
|
||||
activeMessage = true;
|
||||
reduceMessage(node, nextMsg, err => {
|
||||
reduceMessage(node, nextMsgInfo, err => {
|
||||
if (err) {
|
||||
node.error(err,nextMsg);
|
||||
nextMsgInfo.done(err);//.error(err,nextMsg);
|
||||
}
|
||||
activeMessage = null;
|
||||
processReduceMessageQueue();
|
||||
})
|
||||
}
|
||||
|
||||
this.on("input", function(msg) {
|
||||
this.on("input", function(msg, send, done) {
|
||||
try {
|
||||
var property;
|
||||
if (node.mode === 'auto' && (!msg.hasOwnProperty("parts")||!msg.parts.hasOwnProperty("id"))) {
|
||||
node.warn("Message missing msg.parts property - cannot join in 'auto' mode")
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -535,6 +584,7 @@ module.exports = function(RED) {
|
||||
property = RED.util.getMessageProperty(msg,node.property);
|
||||
} catch(err) {
|
||||
node.warn("Message property "+node.property+" not found");
|
||||
done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -557,7 +607,7 @@ module.exports = function(RED) {
|
||||
propertyIndex = msg.parts.index;
|
||||
}
|
||||
else if (node.mode === 'reduce') {
|
||||
return processReduceMessageQueue(msg);
|
||||
return processReduceMessageQueue({msg, send, done});
|
||||
}
|
||||
else {
|
||||
// Use the node configuration to identify all of the group information
|
||||
@ -578,9 +628,11 @@ module.exports = function(RED) {
|
||||
if (inflight[partId].timeout) {
|
||||
clearTimeout(inflight[partId].timeout);
|
||||
}
|
||||
inflight[partId].dones.forEach(f => f());
|
||||
delete inflight[partId]
|
||||
}
|
||||
return
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((payloadType === 'object') && (propertyKey === null || propertyKey === undefined || propertyKey === "")) {
|
||||
@ -591,6 +643,7 @@ module.exports = function(RED) {
|
||||
if (msg.hasOwnProperty('complete')) {
|
||||
if (inflight[partId]) {
|
||||
inflight[partId].msg.complete = msg.complete;
|
||||
inflight[partId].send = send;
|
||||
completeSend(partId);
|
||||
}
|
||||
}
|
||||
@ -598,6 +651,7 @@ module.exports = function(RED) {
|
||||
node.warn("Message missing key property 'msg."+node.key+"' - cannot add to object")
|
||||
}
|
||||
}
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -608,7 +662,9 @@ module.exports = function(RED) {
|
||||
payload:{},
|
||||
targetCount:targetCount,
|
||||
type:"object",
|
||||
msg:RED.util.cloneMessage(msg)
|
||||
msg:RED.util.cloneMessage(msg),
|
||||
send: send,
|
||||
dones: []
|
||||
};
|
||||
}
|
||||
else {
|
||||
@ -617,7 +673,9 @@ module.exports = function(RED) {
|
||||
payload:[],
|
||||
targetCount:targetCount,
|
||||
type:payloadType,
|
||||
msg:RED.util.cloneMessage(msg)
|
||||
msg:RED.util.cloneMessage(msg),
|
||||
send: send,
|
||||
dones: []
|
||||
};
|
||||
if (payloadType === 'string') {
|
||||
inflight[partId].joinChar = joinChar;
|
||||
@ -634,6 +692,7 @@ module.exports = function(RED) {
|
||||
}, node.timer)
|
||||
}
|
||||
}
|
||||
inflight[partId].dones.push(done);
|
||||
|
||||
var group = inflight[partId];
|
||||
if (payloadType === 'buffer') {
|
||||
@ -642,7 +701,7 @@ module.exports = function(RED) {
|
||||
inflight[partId].bufferLen += property.length;
|
||||
}
|
||||
else {
|
||||
node.error(RED._("join.errors.invalid-type",{error:(typeof property)}),msg);
|
||||
done(RED._("join.errors.invalid-type",{error:(typeof property)}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -676,13 +735,18 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
group.msg = Object.assign(group.msg, msg);
|
||||
group.send = send;
|
||||
var tcnt = group.targetCount;
|
||||
if (msg.hasOwnProperty("parts")) { tcnt = group.targetCount || msg.parts.count; }
|
||||
if (msg.hasOwnProperty("parts")) {
|
||||
tcnt = group.targetCount || msg.parts.count;
|
||||
group.targetCount = tcnt;
|
||||
}
|
||||
if ((tcnt > 0 && group.currentCount >= tcnt) || msg.hasOwnProperty('complete')) {
|
||||
completeSend(partId);
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
done(err);
|
||||
console.log(err.stack);
|
||||
}
|
||||
});
|
||||
@ -691,9 +755,11 @@ module.exports = function(RED) {
|
||||
for (var i in inflight) {
|
||||
if (inflight.hasOwnProperty(i)) {
|
||||
clearTimeout(inflight[i].timeout);
|
||||
inflight[i].dones.forEach(d => d());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("join",JoinNode);
|
||||
}
|
||||
|
||||
|
@ -81,16 +81,16 @@ module.exports = function(RED) {
|
||||
|
||||
function sortMessageGroup(group) {
|
||||
var promise;
|
||||
var msgs = group.msgs;
|
||||
var msgInfos = group.msgInfos;
|
||||
if (key_is_exp) {
|
||||
var evaluatedDataPromises = msgs.map(msg => {
|
||||
var evaluatedDataPromises = msgInfos.map(mInfo => {
|
||||
return new Promise((resolve,reject) => {
|
||||
RED.util.evaluateJSONataExpression(key_exp, msg, (err, result) => {
|
||||
RED.util.evaluateJSONataExpression(key_exp, mInfo.msg, (err, result) => {
|
||||
if (err) {
|
||||
reject(RED._("sort.invalid-exp",{message:err.toString()}));
|
||||
} else {
|
||||
resolve({
|
||||
item: msg,
|
||||
item: mInfo,
|
||||
sortValue: result
|
||||
})
|
||||
}
|
||||
@ -106,20 +106,21 @@ module.exports = function(RED) {
|
||||
var key = function(msg) {
|
||||
return ;
|
||||
}
|
||||
var comp = generateComparisonFunction(msg => RED.util.getMessageProperty(msg, key_prop));
|
||||
var comp = generateComparisonFunction(mInfo => RED.util.getMessageProperty(mInfo.msg, key_prop));
|
||||
try {
|
||||
msgs.sort(comp);
|
||||
msgInfos.sort(comp);
|
||||
}
|
||||
catch (e) {
|
||||
return; // not send when error
|
||||
}
|
||||
promise = Promise.resolve(msgs);
|
||||
promise = Promise.resolve(msgInfos);
|
||||
}
|
||||
return promise.then(msgs => {
|
||||
for (var i = 0; i < msgs.length; i++) {
|
||||
var msg = msgs[i];
|
||||
return promise.then(msgInfos => {
|
||||
for (let i = 0; i < msgInfos.length; i++) {
|
||||
const msg = msgInfos[i].msg;
|
||||
msg.parts.index = i;
|
||||
node.send(msg);
|
||||
msgInfos[i].send(msg);
|
||||
msgInfos[i].done();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -181,65 +182,79 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
if(oldest !== undefined) {
|
||||
oldest.msgInfos[oldest.msgInfos.length - 1].done(RED._("sort.too-many"));
|
||||
for (let i = 0; i < oldest.msgInfos.length - 1; i++) {
|
||||
oldest.msgInfos[i].done();
|
||||
}
|
||||
delete pending[oldest_key];
|
||||
return oldest.msgs.length;
|
||||
return oldest.msgInfos.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function processMessage(msg) {
|
||||
function processMessage(msgInfo) {
|
||||
const msg = msgInfo.msg;
|
||||
if (target_is_prop) {
|
||||
sortMessageProperty(msg).then(send => {
|
||||
if (send) {
|
||||
node.send(msg);
|
||||
msgInfo.send(msg);
|
||||
}
|
||||
msgInfo.done();
|
||||
}).catch(err => {
|
||||
node.error(err,msg);
|
||||
msgInfo.done(err);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var parts = msg.parts;
|
||||
if (!parts || !parts.hasOwnProperty("id") || !parts.hasOwnProperty("index")) {
|
||||
msgInfo.done();
|
||||
return;
|
||||
}
|
||||
var gid = parts.id;
|
||||
if (!pending.hasOwnProperty(gid)) {
|
||||
pending[gid] = {
|
||||
count: undefined,
|
||||
msgs: [],
|
||||
msgInfos: [],
|
||||
seq_no: pending_id++
|
||||
};
|
||||
}
|
||||
var group = pending[gid];
|
||||
var msgs = group.msgs;
|
||||
msgs.push(msg);
|
||||
var msgInfos = group.msgInfos;
|
||||
msgInfos.push(msgInfo);
|
||||
if (parts.hasOwnProperty("count")) {
|
||||
group.count = parts.count;
|
||||
}
|
||||
pending_count++;
|
||||
if (group.count === msgs.length) {
|
||||
if (group.count === msgInfos.length) {
|
||||
delete pending[gid]
|
||||
sortMessageGroup(group).catch(err => {
|
||||
node.error(err,msg);
|
||||
// throw an error for last message, and just call done() for remaining messages
|
||||
msgInfos[msgInfos.length-1].done(err);
|
||||
for (let i = 0; i < msgInfos.length - 1; i++) {
|
||||
msgInfos[i].done()
|
||||
};
|
||||
});
|
||||
pending_count -= msgs.length;
|
||||
pending_count -= msgInfos.length;
|
||||
} else {
|
||||
var max_msgs = max_kept_msgs_count(node);
|
||||
if ((max_msgs > 0) && (pending_count > max_msgs)) {
|
||||
pending_count -= removeOldestPending();
|
||||
node.error(RED._("sort.too-many"), msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.on("input", function(msg) {
|
||||
processMessage(msg);
|
||||
this.on("input", function(msg, send, done) {
|
||||
processMessage({msg, send, done});
|
||||
});
|
||||
|
||||
this.on("close", function() {
|
||||
for(var key in pending) {
|
||||
if (pending.hasOwnProperty(key)) {
|
||||
node.log(RED._("sort.clear"), pending[key].msgs[0]);
|
||||
node.log(RED._("sort.clear"), pending[key].msgInfos[0]);
|
||||
const group = pending[key];
|
||||
group.msgInfos.forEach(mInfo => {
|
||||
mInfo.done();
|
||||
});
|
||||
delete pending[key];
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,11 @@ module.exports = function(RED) {
|
||||
return _max_kept_msgs_count;
|
||||
}
|
||||
|
||||
function send_msgs(node, msgs, clone_msg) {
|
||||
var count = msgs.length;
|
||||
var msg_id = msgs[0]._msgid;
|
||||
function send_msgs(node, msgInfos, clone_msg) {
|
||||
var count = msgInfos.length;
|
||||
var msg_id = msgInfos[0].msg._msgid;
|
||||
for (var i = 0; i < count; i++) {
|
||||
var msg = clone_msg ? RED.util.cloneMessage(msgs[i]) : msgs[i];
|
||||
var msg = clone_msg ? RED.util.cloneMessage(msgInfos[i].msg) : msgInfos[i].msg;
|
||||
if (!msg.hasOwnProperty("parts")) {
|
||||
msg.parts = {};
|
||||
}
|
||||
@ -44,14 +44,16 @@ module.exports = function(RED) {
|
||||
parts.id = msg_id;
|
||||
parts.index = i;
|
||||
parts.count = count;
|
||||
node.send(msg);
|
||||
msgInfos[i].send(msg);
|
||||
//msgInfos[i].done();
|
||||
}
|
||||
}
|
||||
|
||||
function send_interval(node, allow_empty_seq) {
|
||||
let msgs = node.pending;
|
||||
if (msgs.length > 0) {
|
||||
send_msgs(node, msgs, false);
|
||||
let msgInfos = node.pending;
|
||||
if (msgInfos.length > 0) {
|
||||
send_msgs(node, msgInfos, false);
|
||||
msgInfos.forEach(e => e.done());
|
||||
node.pending = [];
|
||||
}
|
||||
else {
|
||||
@ -108,19 +110,20 @@ module.exports = function(RED) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var msgs = [];
|
||||
var msgInfos = [];
|
||||
for (var topic of topics) {
|
||||
var t_msgs = get_msgs_of_topic(pending, topic);
|
||||
msgs = msgs.concat(t_msgs);
|
||||
var t_msgInfos = get_msgs_of_topic(pending, topic);
|
||||
msgInfos = msgInfos.concat(t_msgInfos);
|
||||
}
|
||||
for (var topic of topics) {
|
||||
remove_topic(pending, topic);
|
||||
}
|
||||
send_msgs(node, msgs, true);
|
||||
node.pending_count -= msgs.length;
|
||||
send_msgs(node, msgInfos, true);
|
||||
msgInfos.forEach(e => e.done() );
|
||||
node.pending_count -= msgInfos.length;
|
||||
}
|
||||
|
||||
function add_to_topic_group(pending, topic, gid, msg) {
|
||||
function add_to_topic_group(pending, topic, gid, msgInfo) {
|
||||
if (!pending.hasOwnProperty(topic)) {
|
||||
pending[topic] = { groups: {}, gids: [] };
|
||||
}
|
||||
@ -132,32 +135,43 @@ module.exports = function(RED) {
|
||||
gids.push(gid);
|
||||
}
|
||||
var group = groups[gid];
|
||||
group.msgs.push(msg);
|
||||
group.msgs.push(msgInfo);
|
||||
if ((group.count === undefined) &&
|
||||
msg.parts.hasOwnProperty('count')) {
|
||||
group.count = msg.parts.count;
|
||||
msgInfo.msg.parts.hasOwnProperty('count')) {
|
||||
group.count = msgInfo.msg.parts.count;
|
||||
}
|
||||
}
|
||||
|
||||
function concat_msg(node, msg) {
|
||||
function concat_msg(node, msg, send, done) {
|
||||
var topic = msg.topic;
|
||||
if(node.topics.indexOf(topic) >= 0) {
|
||||
if (!msg.hasOwnProperty("parts") ||
|
||||
!msg.parts.hasOwnProperty("id") ||
|
||||
!msg.parts.hasOwnProperty("index") ||
|
||||
!msg.parts.hasOwnProperty("count")) {
|
||||
node.error(RED._("batch.no-parts"), msg);
|
||||
done(RED._("batch.no-parts"));
|
||||
return;
|
||||
}
|
||||
var gid = msg.parts.id;
|
||||
var pending = node.pending;
|
||||
add_to_topic_group(pending, topic, gid, msg);
|
||||
add_to_topic_group(pending, topic, gid, {msg, send, done});
|
||||
node.pending_count++;
|
||||
var max_msgs = max_kept_msgs_count(node);
|
||||
if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
|
||||
Object.values(node.pending).forEach(p_topic => {
|
||||
Object.values(p_topic.groups).forEach(group => {
|
||||
group.msgs.forEach(msgInfo => {
|
||||
if (msgInfo.msg.id === msg.id) {
|
||||
// the message that caused the overflow
|
||||
msgInfo.done(RED._("batch.too-many"));
|
||||
} else {
|
||||
msgInfo.done();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
node.pending = {};
|
||||
node.pending_count = 0;
|
||||
node.error(RED._("batch.too-many"), msg);
|
||||
}
|
||||
try_concat(node, pending);
|
||||
}
|
||||
@ -178,29 +192,37 @@ module.exports = function(RED) {
|
||||
return;
|
||||
}
|
||||
node.pending = [];
|
||||
this.on("input", function(msg) {
|
||||
this.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
node.pending.forEach(e => e.done());
|
||||
node.pending = [];
|
||||
node.pending_count = 0;
|
||||
done();
|
||||
return;
|
||||
}
|
||||
var queue = node.pending;
|
||||
queue.push(msg);
|
||||
queue.push({msg, send, done});
|
||||
node.pending_count++;
|
||||
if (queue.length === count) {
|
||||
send_msgs(node, queue, is_overlap);
|
||||
for (let i = 0; i < queue.length-overlap; i++) {
|
||||
queue[i].done();
|
||||
}
|
||||
node.pending =
|
||||
(overlap === 0) ? [] : queue.slice(-overlap);
|
||||
node.pending_count = 0;
|
||||
}
|
||||
var max_msgs = max_kept_msgs_count(node);
|
||||
if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
|
||||
let lastMInfo = node.pending.pop();
|
||||
lastMInfo.done(RED._("batch.too-many"));
|
||||
node.pending.forEach(e => e.done());
|
||||
node.pending = [];
|
||||
node.pending_count = 0;
|
||||
node.error(RED._("batch.too-many"), msg);
|
||||
}
|
||||
});
|
||||
this.on("close", function() {
|
||||
node.pending.forEach(e=> e.done());
|
||||
node.pending_count = 0;
|
||||
node.pending = [];
|
||||
});
|
||||
@ -217,31 +239,36 @@ module.exports = function(RED) {
|
||||
if (interval > 0) {
|
||||
timer = setInterval(msgHandler, interval);
|
||||
}
|
||||
this.on("input", function(msg) {
|
||||
this.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (timer !== undefined) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
node.pending.forEach(e => e.done());
|
||||
node.pending = [];
|
||||
node.pending_count = 0;
|
||||
done();
|
||||
if (interval > 0) {
|
||||
timer = setInterval(msgHandler, interval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
node.pending.push(msg);
|
||||
node.pending.push({msg, send, done});
|
||||
node.pending_count++;
|
||||
var max_msgs = max_kept_msgs_count(node);
|
||||
if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
|
||||
let lastMInfo = node.pending.pop();
|
||||
lastMInfo.done(RED._("batch.too-many"));
|
||||
node.pending.forEach(e => e.done());
|
||||
node.pending = [];
|
||||
node.pending_count = 0;
|
||||
node.error(RED._("batch.too-many"), msg);
|
||||
}
|
||||
});
|
||||
this.on("close", function() {
|
||||
if (timer !== undefined) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
node.pending.forEach(e => e.done());
|
||||
node.pending = [];
|
||||
node.pending_count = 0;
|
||||
});
|
||||
@ -251,15 +278,26 @@ module.exports = function(RED) {
|
||||
return x.topic;
|
||||
});
|
||||
node.pending = {};
|
||||
this.on("input", function(msg) {
|
||||
this.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
Object.values(node.pending).forEach(p_topic => {
|
||||
Object.values(p_topic.groups).forEach(group => {
|
||||
group.msgs.forEach(e => e.done());
|
||||
});
|
||||
});
|
||||
node.pending = {};
|
||||
node.pending_count = 0;
|
||||
done();
|
||||
return;
|
||||
}
|
||||
concat_msg(node, msg);
|
||||
concat_msg(node, msg, send, done);
|
||||
});
|
||||
this.on("close", function() {
|
||||
Object.values(node.pending).forEach(p_topic => {
|
||||
Object.values(p_topic.groups).forEach(group => {
|
||||
group.msgs.forEach(e => e.done());
|
||||
});
|
||||
});
|
||||
node.pending = {};
|
||||
node.pending_count = 0;
|
||||
});
|
||||
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "330f4888.cccb28",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"ed11f8d6.5e3c88"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a0288b44.71d488",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": "",
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"369cbe42.4af9f2"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ed11f8d6.5e3c88",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "CSV data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "text",
|
||||
"syntax": "mustache",
|
||||
"template": "Apple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
|
||||
"output": "str",
|
||||
"x": 430,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"a0288b44.71d488"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "369cbe42.4af9f2",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "783cfaa6.52fbe4",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Parse CSV with default column name as messages",
|
||||
"info": "CSV node can parse input CSV data.\nParsed CSV record can be sent as a message sequence.\nEach message payload points to an object with `col`*N* as a key and CSV value as a value.\n",
|
||||
"x": 330,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "98c9d44d.4457b8",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"65476517.3d760c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "76df98f7.0dcd08",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": "",
|
||||
"hdrout": "none",
|
||||
"multi": "mult",
|
||||
"ret": "\\n",
|
||||
"temp": "",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"557979e0.e6b588"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "65476517.3d760c",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "CSV data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "text",
|
||||
"syntax": "mustache",
|
||||
"template": "Apple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
|
||||
"output": "str",
|
||||
"x": 430,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"76df98f7.0dcd08"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "557979e0.e6b588",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 360,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "187f4ab3.4c9ab5",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Parse CSV with default column name as array",
|
||||
"info": "CSV node can send a single message with array of parsed CSV records.\nEach element of the array consists of objects with key-value pair.",
|
||||
"x": 320,
|
||||
"y": 300,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "1216e95b.1b1e87",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"e41ffbbc.de2ed8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "286828bc.9233c8",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": "",
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price,origin",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"9d8218c.5550ee8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e41ffbbc.de2ed8",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "CSV data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "text",
|
||||
"syntax": "mustache",
|
||||
"template": "Apple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
|
||||
"output": "str",
|
||||
"x": 430,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"286828bc.9233c8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "9d8218c.5550ee8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 560,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "aaa1ee8f.21e2c",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Parse CSV with specified column name as messages",
|
||||
"info": "CSV node can specify column name of parsed objects in its settings panel.",
|
||||
"x": 340,
|
||||
"y": 500,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "24093558.0315aa",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"80abaee1.5fa7f"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d4d2ca3f.1d9488",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": true,
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"b52791c3.08967"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "80abaee1.5fa7f",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "CSV data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "text",
|
||||
"syntax": "mustache",
|
||||
"template": "kind,price,origin\nApple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
|
||||
"output": "str",
|
||||
"x": 430,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"d4d2ca3f.1d9488"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b52791c3.08967",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 740,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "85091361.85644",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Parse CSV with column name in first row as messages",
|
||||
"info": "CSV node can use first row of input CSV text as a column name of each record object.\n",
|
||||
"x": 340,
|
||||
"y": 680,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "9e93169c.b763a8",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert JavaScript object to CSV",
|
||||
"info": "CSV node can convert a JavaScript object to CSV text.\nEach object contains key-value pair of specified properties.\n",
|
||||
"x": 270,
|
||||
"y": 860,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "8ca41fee.3303d",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 920,
|
||||
"wires": [
|
||||
[
|
||||
"c466905b.e8c61"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "65146d20.d78204",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": false,
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 920,
|
||||
"wires": [
|
||||
[
|
||||
"92e99e67.a37d8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c466905b.e8c61",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
|
||||
"output": "json",
|
||||
"x": 430,
|
||||
"y": 920,
|
||||
"wires": [
|
||||
[
|
||||
"65146d20.d78204"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "92e99e67.a37d8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 920,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "e89019c5.70ae78",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert array of JavaScript objects to CSV",
|
||||
"info": "CSV node can convert an array of JavaScript objects to multi-line CSV text.",
|
||||
"x": 300,
|
||||
"y": 1020,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "bd0d82ed.7b28",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 1080,
|
||||
"wires": [
|
||||
[
|
||||
"1d857b8d.3a4014"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "66a37667.16ebd8",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": false,
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 1080,
|
||||
"wires": [
|
||||
[
|
||||
"859725fd.dc93d8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1d857b8d.3a4014",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "[\n {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n },\n {\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n },\n {\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n }\n]",
|
||||
"output": "json",
|
||||
"x": 430,
|
||||
"y": 1080,
|
||||
"wires": [
|
||||
[
|
||||
"66a37667.16ebd8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "859725fd.dc93d8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 1080,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "2ebdd51e.c5d17a",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert array of JavaScript objects to CSV with column name header",
|
||||
"info": "CSV node can convert an array of JavaScript objects to multi-line CSV text with column name header at first line.",
|
||||
"x": 390,
|
||||
"y": 1200,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2b4d538d.ada07c",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 1260,
|
||||
"wires": [
|
||||
[
|
||||
"3e5c9e8.5065b62"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "db02c7be.0984e8",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": false,
|
||||
"hdrout": "all",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 1260,
|
||||
"wires": [
|
||||
[
|
||||
"61f8b772.ddb1f8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3e5c9e8.5065b62",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "[\n {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n },\n {\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n },\n {\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n }\n]",
|
||||
"output": "json",
|
||||
"x": 430,
|
||||
"y": 1260,
|
||||
"wires": [
|
||||
[
|
||||
"db02c7be.0984e8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "61f8b772.ddb1f8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 1260,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,99 @@
|
||||
[
|
||||
{
|
||||
"id": "2ebdd51e.c5d17a",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert array of JavaScript objects to CSV with column name header",
|
||||
"info": "CSV node can convert an array of JavaScript objects to multi-line CSV text with column name header at first line.",
|
||||
"x": 390,
|
||||
"y": 1200,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2b4d538d.ada07c",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 1260,
|
||||
"wires": [
|
||||
[
|
||||
"3e5c9e8.5065b62"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "db02c7be.0984e8",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": false,
|
||||
"hdrout": "all",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 1260,
|
||||
"wires": [
|
||||
[
|
||||
"61f8b772.ddb1f8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3e5c9e8.5065b62",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "[\n {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n },\n {\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n },\n {\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n }\n]",
|
||||
"output": "json",
|
||||
"x": 430,
|
||||
"y": 1260,
|
||||
"wires": [
|
||||
[
|
||||
"db02c7be.0984e8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "61f8b772.ddb1f8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 780,
|
||||
"y": 1260,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,200 @@
|
||||
[
|
||||
{
|
||||
"id": "1ae28939.9f5fc7",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Send column name when reset property set",
|
||||
"info": "CSV node can send column names at first or `reset` property exists in input message.",
|
||||
"x": 310,
|
||||
"y": 1540,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "c16ad95b.4f9ac8",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Apple",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 250,
|
||||
"y": 1600,
|
||||
"wires": [
|
||||
[
|
||||
"7f7bfc72.aed104"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "870620b9.95343",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": false,
|
||||
"hdrout": "once",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 650,
|
||||
"y": 1720,
|
||||
"wires": [
|
||||
[
|
||||
"d960de42.619c7"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7f7bfc72.aed104",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
|
||||
"output": "json",
|
||||
"x": 470,
|
||||
"y": 1600,
|
||||
"wires": [
|
||||
[
|
||||
"870620b9.95343"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d960de42.619c7",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 830,
|
||||
"y": 1720,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "6f8296e.f95ca68",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Orange",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 250,
|
||||
"y": 1660,
|
||||
"wires": [
|
||||
[
|
||||
"c37d0dfa.ec1ab"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c37d0dfa.ec1ab",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n}\n",
|
||||
"output": "json",
|
||||
"x": 470,
|
||||
"y": 1660,
|
||||
"wires": [
|
||||
[
|
||||
"870620b9.95343"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "35209fe2.16926",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Banana & reset",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"p": "reset",
|
||||
"v": "",
|
||||
"vt": "date"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 280,
|
||||
"y": 1720,
|
||||
"wires": [
|
||||
[
|
||||
"afd4e6b3.624a28"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "afd4e6b3.624a28",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n}",
|
||||
"output": "json",
|
||||
"x": 470,
|
||||
"y": 1720,
|
||||
"wires": [
|
||||
[
|
||||
"870620b9.95343"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,150 @@
|
||||
[
|
||||
{
|
||||
"id": "195c168c.44f149",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 260,
|
||||
"y": 1900,
|
||||
"wires": [
|
||||
[
|
||||
"b270564c.171908"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8ec8cf9e.103fa",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": true,
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 600,
|
||||
"y": 1900,
|
||||
"wires": [
|
||||
[
|
||||
"5c5254a8.bc562c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b270564c.171908",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "CSV data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "text",
|
||||
"syntax": "mustache",
|
||||
"template": "kind,price,origin\nApple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
|
||||
"output": "str",
|
||||
"x": 430,
|
||||
"y": 1900,
|
||||
"wires": [
|
||||
[
|
||||
"8ec8cf9e.103fa"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1c7be442.6a4bdc",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 1090,
|
||||
"y": 1900,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "d3da7cfb.cf596",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Join parsed CSV message sequence using join node",
|
||||
"info": "Parset CSV message sequence can be joined by join node.",
|
||||
"x": 330,
|
||||
"y": 1840,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "a07c9e26.c84fd",
|
||||
"type": "csv",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"sep": ",",
|
||||
"hdrin": "",
|
||||
"hdrout": "none",
|
||||
"multi": "one",
|
||||
"ret": "\\n",
|
||||
"temp": "kind,price",
|
||||
"skip": "0",
|
||||
"strings": true,
|
||||
"include_empty_strings": "",
|
||||
"include_null_values": "",
|
||||
"x": 910,
|
||||
"y": 1900,
|
||||
"wires": [
|
||||
[
|
||||
"1c7be442.6a4bdc"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5c5254a8.bc562c",
|
||||
"type": "join",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"mode": "auto",
|
||||
"build": "string",
|
||||
"property": "payload",
|
||||
"propertyType": "msg",
|
||||
"key": "topic",
|
||||
"joiner": "\\n",
|
||||
"joinerType": "str",
|
||||
"accumulate": false,
|
||||
"timeout": "",
|
||||
"count": "",
|
||||
"reduceRight": false,
|
||||
"reduceExp": "",
|
||||
"reduceInit": "",
|
||||
"reduceInitType": "",
|
||||
"reduceFixup": "",
|
||||
"x": 750,
|
||||
"y": 1900,
|
||||
"wires": [
|
||||
[
|
||||
"a07c9e26.c84fd"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,94 @@
|
||||
[
|
||||
{
|
||||
"id": "8c5224a6.201b88",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"d6c67e51.0d709"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d6c67e51.0d709",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "HTML text",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "handlebars",
|
||||
"syntax": "plain",
|
||||
"template": "<html>\n <head>\n <title>List of Fruits</title>\n </head>\n <body>\n <ul>\n <li class=\"Item\">Apple</li>\n <li class=\"Item\">Orange</li>\n <li class=\"Item\">Banana</li>\n </ul>\n </body>\n</html>\n",
|
||||
"output": "str",
|
||||
"x": 390,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"599a1155.61a5c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "b0d5cd89.338df",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Extract array of HTML element by CSS selector",
|
||||
"info": "HTML node can be used to extract elements in HTML document as an array using CSS selector.",
|
||||
"x": 280,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "599a1155.61a5c",
|
||||
"type": "html",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"outproperty": "payload",
|
||||
"tag": ".Item",
|
||||
"ret": "html",
|
||||
"as": "single",
|
||||
"x": 550,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"942b23d1.cce09"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "942b23d1.cce09",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 710,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,94 @@
|
||||
[
|
||||
{
|
||||
"id": "a44973e8.6319b",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"de1b012e.96ec3"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "de1b012e.96ec3",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "HTML text",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "handlebars",
|
||||
"syntax": "plain",
|
||||
"template": "<html>\n <head>\n <title>List of Fruits</title>\n </head>\n <body>\n <ul>\n <li class=\"Item\">Apple</li>\n <li class=\"Item\">Orange</li>\n <li class=\"Item\">Banana</li>\n </ul>\n </body>\n</html>\n",
|
||||
"output": "str",
|
||||
"x": 390,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"cee70712.6f3538"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "99e32bc7.c8e508",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Extract sequence of HTML element by CSS selector",
|
||||
"info": "HTML node can be used to extract elements in HTML document as a messege sequence using CSS selector.",
|
||||
"x": 290,
|
||||
"y": 300,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "cee70712.6f3538",
|
||||
"type": "html",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"outproperty": "payload",
|
||||
"tag": ".Item",
|
||||
"ret": "html",
|
||||
"as": "multi",
|
||||
"x": 550,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"17f25482.d4b56b"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "17f25482.d4b56b",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 710,
|
||||
"y": 360,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,121 @@
|
||||
[
|
||||
{
|
||||
"id": "653ce9aa.b6a1c8",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"52a16f7f.447d8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "52a16f7f.447d8",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "HTML text",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "handlebars",
|
||||
"syntax": "plain",
|
||||
"template": "<html>\n <head>\n <title>List of Fruits</title>\n </head>\n <body>\n <ul>\n <li class=\"Item\">Apple</li>\n <li class=\"Item\">Orange</li>\n <li class=\"Item\">Banana</li>\n </ul>\n </body>\n</html>\n",
|
||||
"output": "str",
|
||||
"x": 390,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"a52319c3.89b008"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8bc35379.31d99",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Extract array of HTML element by CSS selector specified in message",
|
||||
"info": "CSS selector for HTML node can be specified by `select` property of input message.",
|
||||
"x": 350,
|
||||
"y": 500,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "9c49de8a.bad25",
|
||||
"type": "html",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"outproperty": "payload",
|
||||
"tag": "",
|
||||
"ret": "html",
|
||||
"as": "single",
|
||||
"x": 730,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"d4f4b987.278a68"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d4f4b987.278a68",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 890,
|
||||
"y": 560,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "a52319c3.89b008",
|
||||
"type": "change",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"rules": [
|
||||
{
|
||||
"t": "set",
|
||||
"p": "select",
|
||||
"pt": "msg",
|
||||
"to": ".Item",
|
||||
"tot": "str"
|
||||
}
|
||||
],
|
||||
"action": "",
|
||||
"property": "",
|
||||
"from": "",
|
||||
"to": "",
|
||||
"reg": false,
|
||||
"x": 560,
|
||||
"y": 560,
|
||||
"wires": [
|
||||
[
|
||||
"9c49de8a.bad25"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,122 @@
|
||||
[
|
||||
{
|
||||
"id": "66cff4ee.f2761c",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"2baaf6bf.0a02ca"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2baaf6bf.0a02ca",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "HTML text",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "handlebars",
|
||||
"syntax": "plain",
|
||||
"template": "<html>\n <head>\n <title>List of Fruits</title>\n </head>\n <body>\n <ul>\n <li class=\"Item\">Apple</li>\n <li class=\"Item\">Orange</li>\n <li class=\"Item\">Banana</li>\n </ul>\n </body>\n</html>\n",
|
||||
"output": "str",
|
||||
"x": 390,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"bbb22e6b.0fa25"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a57d35d0.8aa538",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Join extracted sequence of HTML element using join node",
|
||||
"info": "Message sequence extracted by HTML node can be combined using join node.",
|
||||
"x": 310,
|
||||
"y": 700,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "bbb22e6b.0fa25",
|
||||
"type": "html",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"outproperty": "payload",
|
||||
"tag": ".Item",
|
||||
"ret": "html",
|
||||
"as": "multi",
|
||||
"x": 550,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"bd01ca4.966ad38"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4d2616a8.84de88",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 850,
|
||||
"y": 760,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "bd01ca4.966ad38",
|
||||
"type": "join",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"mode": "custom",
|
||||
"build": "string",
|
||||
"property": "payload",
|
||||
"propertyType": "msg",
|
||||
"key": "topic",
|
||||
"joiner": ",",
|
||||
"joinerType": "str",
|
||||
"accumulate": false,
|
||||
"timeout": "",
|
||||
"count": "",
|
||||
"reduceRight": false,
|
||||
"reduceExp": "",
|
||||
"reduceInit": "",
|
||||
"reduceInitType": "",
|
||||
"reduceFixup": "",
|
||||
"x": 690,
|
||||
"y": 760,
|
||||
"wires": [
|
||||
[
|
||||
"4d2616a8.84de88"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"id": "9976e95d.2f8398",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 240,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"d94fc083.49d87"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6684abb1.8eb454",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert JSON string to JS object",
|
||||
"info": "JSON node can convert JSON string to JavaScript object.",
|
||||
"x": 250,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "d94fc083.49d87",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JSON string",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
|
||||
"output": "str",
|
||||
"x": 410,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"1a3dc54a.78598b"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8950a55d.023988",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 730,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "1a3dc54a.78598b",
|
||||
"type": "json",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 570,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"8950a55d.023988"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"id": "cb13761f.56c328",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 240,
|
||||
"y": 380,
|
||||
"wires": [
|
||||
[
|
||||
"c607642a.78c3c8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "180b1e22.0074e2",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert JS object to JSON string",
|
||||
"info": "JSON node can convert JavaScript object to JSON string.",
|
||||
"x": 250,
|
||||
"y": 320,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "c607642a.78c3c8",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
|
||||
"output": "json",
|
||||
"x": 400,
|
||||
"y": 380,
|
||||
"wires": [
|
||||
[
|
||||
"bf309844.fa12e8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5b6b130b.72a14c",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 730,
|
||||
"y": 380,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "bf309844.fa12e8",
|
||||
"type": "json",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 570,
|
||||
"y": 380,
|
||||
"wires": [
|
||||
[
|
||||
"5b6b130b.72a14c"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
160
packages/node_modules/@node-red/nodes/examples/parser/json/03 - Validate input JSON string.json
vendored
Normal file
160
packages/node_modules/@node-red/nodes/examples/parser/json/03 - Validate input JSON string.json
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
[
|
||||
{
|
||||
"id": "2b18621b.e2670e",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "OK",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 230,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"5986faee.aef954"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "59acf99.9a92308",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Validate input JSON string",
|
||||
"info": "JSON node can validate input JSON string using [JSON schema](https://json-schema.org/) when converting to JavaScript object.",
|
||||
"x": 230,
|
||||
"y": 520,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "5986faee.aef954",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JSON string",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
|
||||
"output": "str",
|
||||
"x": 410,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"f8a67c6d.4f1f1"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ca27c92c.ad7cb8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "payload",
|
||||
"targetType": "msg",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 910,
|
||||
"y": 580,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2fad9978.ea1916",
|
||||
"type": "json",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"action": "",
|
||||
"pretty": false,
|
||||
"x": 750,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"ca27c92c.ad7cb8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f8a67c6d.4f1f1",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Schema",
|
||||
"field": "schema",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"type\": \"string\"\n },\n \"price\": {\n \"type\": \"number\"\n },\n \"origin\": {\n \"type\": \"string\"\n }\n }\n}",
|
||||
"output": "json",
|
||||
"x": 590,
|
||||
"y": 580,
|
||||
"wires": [
|
||||
[
|
||||
"2fad9978.ea1916"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8337e847.ac18d8",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "NG",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 230,
|
||||
"y": 660,
|
||||
"wires": [
|
||||
[
|
||||
"fa14d8bf.1ac938"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fa14d8bf.1ac938",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JSON string",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": \"100\",\n \"origin\": \"Canada\"\n}",
|
||||
"output": "str",
|
||||
"x": 410,
|
||||
"y": 660,
|
||||
"wires": [
|
||||
[
|
||||
"f8a67c6d.4f1f1"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"id": "82f1bd0b.43474",
|
||||
"type": "xml",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"attr": "",
|
||||
"chr": "",
|
||||
"x": 530,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"1cd4ad02.9a5423"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "84222b92.d65d18",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 200,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"cdd1c154.3a655"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7b014430.dfd94c",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert JavaScript object to XML",
|
||||
"info": "XML node can convert JavaScript object to XML string.",
|
||||
"x": 240,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "1cd4ad02.9a5423",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 690,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "cdd1c154.3a655",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
|
||||
"output": "json",
|
||||
"x": 360,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"82f1bd0b.43474"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"id": "93e423a9.a407d",
|
||||
"type": "xml",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"attr": "",
|
||||
"chr": "",
|
||||
"x": 530,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"2d0dde7e.a50082"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ba1dab90.8d1da8",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 200,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"16617f26.14ced1"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a9f97b00.57d658",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert XML to JavaScript object",
|
||||
"info": "XML node can convert XML string to JavaScript object.",
|
||||
"x": 240,
|
||||
"y": 300,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2d0dde7e.a50082",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 690,
|
||||
"y": 360,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "16617f26.14ced1",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "XML string",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "html",
|
||||
"syntax": "plain",
|
||||
"template": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<fruit id=\"100\">\n <kind>Apple</kind>\n <price>100</price>\n <origin>Canada</origin>\n</fruit>",
|
||||
"output": "str",
|
||||
"x": 370,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"93e423a9.a407d"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,119 @@
|
||||
[
|
||||
{
|
||||
"id": "581bd648.636628",
|
||||
"type": "xml",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"property": "payload",
|
||||
"attr": "",
|
||||
"chr": "",
|
||||
"x": 710,
|
||||
"y": 540,
|
||||
"wires": [
|
||||
[
|
||||
"b74237dc.1e5028"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d0899f9b.f1ac6",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 200,
|
||||
"y": 540,
|
||||
"wires": [
|
||||
[
|
||||
"f04ffb9a.68edb8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8a214c05.dc61f",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Control conversion using options property",
|
||||
"info": "XML node can control conversion by setting `options` property (defined by [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md#options)) in input message.",
|
||||
"x": 260,
|
||||
"y": 480,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b74237dc.1e5028",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 870,
|
||||
"y": 540,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "f04ffb9a.68edb8",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "XML string",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "html",
|
||||
"syntax": "plain",
|
||||
"template": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<fruit id=\"100\">\n <kind>Apple</kind>\n <price>100</price>\n <origin>Canada</origin>\n</fruit>",
|
||||
"output": "str",
|
||||
"x": 370,
|
||||
"y": 540,
|
||||
"wires": [
|
||||
[
|
||||
"fedf79.5889c088"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fedf79.5889c088",
|
||||
"type": "change",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "set options",
|
||||
"rules": [
|
||||
{
|
||||
"t": "set",
|
||||
"p": "options",
|
||||
"pt": "msg",
|
||||
"to": "{\"explicitArray\":false}",
|
||||
"tot": "json"
|
||||
}
|
||||
],
|
||||
"action": "",
|
||||
"property": "",
|
||||
"from": "",
|
||||
"to": "",
|
||||
"reg": false,
|
||||
"x": 550,
|
||||
"y": 540,
|
||||
"wires": [
|
||||
[
|
||||
"581bd648.636628"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,90 @@
|
||||
[
|
||||
{
|
||||
"id": "84222b92.d65d18",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 200,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"cdd1c154.3a655"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7b014430.dfd94c",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert JavaScript object to YAML",
|
||||
"info": "YAML node can convert JavaScript object to YAML string.",
|
||||
"x": 240,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "1cd4ad02.9a5423",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 670,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "cdd1c154.3a655",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "JS object",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "json",
|
||||
"syntax": "plain",
|
||||
"template": "{\n \"fruits\" : {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n }\n}",
|
||||
"output": "json",
|
||||
"x": 360,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"aaf0100b.16628"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "aaf0100b.16628",
|
||||
"type": "yaml",
|
||||
"z": "4b63452d.672afc",
|
||||
"property": "payload",
|
||||
"name": "",
|
||||
"x": 510,
|
||||
"y": 180,
|
||||
"wires": [
|
||||
[
|
||||
"1cd4ad02.9a5423"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
@ -0,0 +1,90 @@
|
||||
[
|
||||
{
|
||||
"id": "ba1dab90.8d1da8",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 200,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"16617f26.14ced1"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a9f97b00.57d658",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Convert YAML to JavaScript object",
|
||||
"info": "YAML node can convert YAML string to JavaScript object.",
|
||||
"x": 240,
|
||||
"y": 300,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2d0dde7e.a50082",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 690,
|
||||
"y": 360,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "16617f26.14ced1",
|
||||
"type": "template",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "YAML string",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "yaml",
|
||||
"syntax": "plain",
|
||||
"template": "fruits:\n kind: Apple\n price: 100\n origin: Canada",
|
||||
"output": "str",
|
||||
"x": 370,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"e2e4f862.f9d7d8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "e2e4f862.f9d7d8",
|
||||
"type": "yaml",
|
||||
"z": "4b63452d.672afc",
|
||||
"property": "payload",
|
||||
"name": "",
|
||||
"x": 530,
|
||||
"y": 360,
|
||||
"wires": [
|
||||
[
|
||||
"2d0dde7e.a50082"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
113
packages/node_modules/@node-red/nodes/examples/storage/file-in/01 - Read string from a file.json
vendored
Normal file
113
packages/node_modules/@node-red/nodes/examples/storage/file-in/01 - Read string from a file.json
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"id": "84222b92.d65d18",
|
||||
"type": "inject",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "Hello, World!",
|
||||
"payloadType": "str",
|
||||
"x": 230,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"b4b9f603.739598"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7b014430.dfd94c",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Write string to a file, then read from the file",
|
||||
"info": "File-in node can read string from a file.",
|
||||
"x": 260,
|
||||
"y": 140,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b4b9f603.739598",
|
||||
"type": "file",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 420,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"6dc01cac.5c4bf4"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2587adb9.7e60f2",
|
||||
"type": "debug",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 810,
|
||||
"y": 220,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "6dc01cac.5c4bf4",
|
||||
"type": "file in",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 620,
|
||||
"y": 220,
|
||||
"wires": [
|
||||
[
|
||||
"2587adb9.7e60f2"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f4b4309a.3b78a",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 630,
|
||||
"y": 260,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "672d3693.3cabd8",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 440,
|
||||
"y": 180,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"id": "8997398f.c5d628",
|
||||
"type": "inject",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "😀",
|
||||
"payloadType": "str",
|
||||
"x": 210,
|
||||
"y": 480,
|
||||
"wires": [
|
||||
[
|
||||
"56e32d23.050f44"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4e598e65.1799d",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Read data in specified encoding",
|
||||
"info": "File-in node can specify encoding of data read from a file.",
|
||||
"x": 230,
|
||||
"y": 400,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "56e32d23.050f44",
|
||||
"type": "file",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 380,
|
||||
"y": 480,
|
||||
"wires": [
|
||||
[
|
||||
"38fa0579.f2cd8a"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "d28c8994.99c0a8",
|
||||
"type": "debug",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 770,
|
||||
"y": 480,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "38fa0579.f2cd8a",
|
||||
"type": "file in",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "base64",
|
||||
"x": 580,
|
||||
"y": 480,
|
||||
"wires": [
|
||||
[
|
||||
"d28c8994.99c0a8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "fa22ca20.ae4528",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read data from file as base64 string",
|
||||
"info": "",
|
||||
"x": 640,
|
||||
"y": 520,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "148e25ad.98891a",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 400,
|
||||
"y": 440,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,132 @@
|
||||
[
|
||||
{
|
||||
"id": "6a0b1d03.d4cee4",
|
||||
"type": "inject",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"d4b00cb7.a5a23"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f17ea1d1.8ecc3",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Read data breaking lines into individual messages",
|
||||
"info": "File-in node can break read text into messages with individual lines",
|
||||
"x": 290,
|
||||
"y": 660,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "99ae7806.1d6428",
|
||||
"type": "file",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 540,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"70d7892f.d27db8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7ed8282c.92b338",
|
||||
"type": "debug",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 810,
|
||||
"y": 800,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "70d7892f.d27db8",
|
||||
"type": "file in",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "lines",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 620,
|
||||
"y": 800,
|
||||
"wires": [
|
||||
[
|
||||
"7ed8282c.92b338"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c1b7e05.1d94b2",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read data from file breaking lines into messages",
|
||||
"info": "",
|
||||
"x": 720,
|
||||
"y": 840,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "a5f647b2.cf27a8",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 560,
|
||||
"y": 700,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "d4b00cb7.a5a23",
|
||||
"type": "template",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "handlebars",
|
||||
"syntax": "plain",
|
||||
"template": "one\ntwo\nthree!",
|
||||
"output": "str",
|
||||
"x": 370,
|
||||
"y": 740,
|
||||
"wires": [
|
||||
[
|
||||
"99ae7806.1d6428"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
201
packages/node_modules/@node-red/nodes/examples/storage/file-in/04 - Create a message stream.json
vendored
Normal file
201
packages/node_modules/@node-red/nodes/examples/storage/file-in/04 - Create a message stream.json
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
[
|
||||
{
|
||||
"id": "bdd57acc.2edc48",
|
||||
"type": "inject",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 1040,
|
||||
"wires": [
|
||||
[
|
||||
"7a069b01.0c2324"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1fd12220.33953e",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "Creating a message stream from lines of data",
|
||||
"info": "File-in node can break read text into messages with individual lines. The messages creates a stream of messages.",
|
||||
"x": 270,
|
||||
"y": 960,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "ab6eb213.2a08d",
|
||||
"type": "file",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 540,
|
||||
"y": 1040,
|
||||
"wires": [
|
||||
[
|
||||
"b7ed49b0.649fb8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c48d8ae0.9ff3a8",
|
||||
"type": "debug",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 810,
|
||||
"y": 1140,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b7ed49b0.649fb8",
|
||||
"type": "file in",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "lines",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 280,
|
||||
"y": 1140,
|
||||
"wires": [
|
||||
[
|
||||
"83073ebe.fcce4"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3c33e69f.6a04ba",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑read data from file breaking lines into messages",
|
||||
"info": "",
|
||||
"x": 380,
|
||||
"y": 1180,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "3598bf7d.5712a",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 560,
|
||||
"y": 1000,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "7a069b01.0c2324",
|
||||
"type": "template",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "data",
|
||||
"field": "payload",
|
||||
"fieldType": "msg",
|
||||
"format": "handlebars",
|
||||
"syntax": "plain",
|
||||
"template": "Apple\nBanana\nGrape\nOrange",
|
||||
"output": "str",
|
||||
"x": 370,
|
||||
"y": 1040,
|
||||
"wires": [
|
||||
[
|
||||
"ab6eb213.2a08d"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8d4ed1d0.821fe",
|
||||
"type": "join",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "",
|
||||
"mode": "auto",
|
||||
"build": "string",
|
||||
"property": "payload",
|
||||
"propertyType": "msg",
|
||||
"key": "topic",
|
||||
"joiner": "\\n",
|
||||
"joinerType": "str",
|
||||
"accumulate": "false",
|
||||
"timeout": "",
|
||||
"count": "",
|
||||
"reduceRight": false,
|
||||
"x": 630,
|
||||
"y": 1140,
|
||||
"wires": [
|
||||
[
|
||||
"c48d8ae0.9ff3a8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "83073ebe.fcce4",
|
||||
"type": "switch",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "< D",
|
||||
"property": "payload",
|
||||
"propertyType": "msg",
|
||||
"rules": [
|
||||
{
|
||||
"t": "lt",
|
||||
"v": "D",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"checkall": "true",
|
||||
"repair": true,
|
||||
"outputs": 1,
|
||||
"x": 470,
|
||||
"y": 1140,
|
||||
"wires": [
|
||||
[
|
||||
"8d4ed1d0.821fe"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2088e195.f7aebe",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↓filter data before \"D\"",
|
||||
"info": "",
|
||||
"x": 520,
|
||||
"y": 1100,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b848cdc7.61e06",
|
||||
"type": "comment",
|
||||
"z": "194a3e4f.a92772",
|
||||
"name": "↑join to single string",
|
||||
"info": "",
|
||||
"x": 670,
|
||||
"y": 1180,
|
||||
"wires": []
|
||||
}
|
||||
]
|
113
packages/node_modules/@node-red/nodes/examples/storage/file/01 - Write string to a file.json
vendored
Normal file
113
packages/node_modules/@node-red/nodes/examples/storage/file/01 - Write string to a file.json
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"id": "84222b92.d65d18",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "Hello, World!",
|
||||
"payloadType": "str",
|
||||
"x": 230,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"b4b9f603.739598"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "7b014430.dfd94c",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Write string to a file, then read from the file",
|
||||
"info": "File node can write string to a file.",
|
||||
"x": 260,
|
||||
"y": 120,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "b4b9f603.739598",
|
||||
"type": "file",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 420,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"6dc01cac.5c4bf4"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2587adb9.7e60f2",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 810,
|
||||
"y": 200,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "6dc01cac.5c4bf4",
|
||||
"type": "file in",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 620,
|
||||
"y": 200,
|
||||
"wires": [
|
||||
[
|
||||
"2587adb9.7e60f2"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f4b4309a.3b78a",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 630,
|
||||
"y": 240,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "672d3693.3cabd8",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓write to /tmp/hello.txt",
|
||||
"info": "",
|
||||
"x": 440,
|
||||
"y": 160,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,118 @@
|
||||
[
|
||||
{
|
||||
"id": "704479e1.399388",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "filename",
|
||||
"v": "/tmp/hello.txt",
|
||||
"vt": "str"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "Hello, World!",
|
||||
"payloadType": "str",
|
||||
"x": 230,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"402f3b7e.988014"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "8e876a75.e9beb8",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Write string to a file specied by filename property, the read from the file",
|
||||
"info": "File node can target file using `filename` property.",
|
||||
"x": 350,
|
||||
"y": 320,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "402f3b7e.988014",
|
||||
"type": "file",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "none",
|
||||
"x": 390,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"26e077d6.bbcd98"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "97b6b6b2.a54b38",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 770,
|
||||
"y": 400,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "26e077d6.bbcd98",
|
||||
"type": "file in",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 580,
|
||||
"y": 400,
|
||||
"wires": [
|
||||
[
|
||||
"97b6b6b2.a54b38"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "85062297.da79",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 590,
|
||||
"y": 440,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "7316c4fc.b1dcdc",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓write to file specified by filename property",
|
||||
"info": "",
|
||||
"x": 500,
|
||||
"y": 360,
|
||||
"wires": []
|
||||
}
|
||||
]
|
85
packages/node_modules/@node-red/nodes/examples/storage/file/03 - Delete a file.json
vendored
Normal file
85
packages/node_modules/@node-red/nodes/examples/storage/file/03 - Delete a file.json
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
[
|
||||
{
|
||||
"id": "4ac00fb0.d5f52",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "",
|
||||
"payloadType": "date",
|
||||
"x": 220,
|
||||
"y": 600,
|
||||
"wires": [
|
||||
[
|
||||
"542cc2f4.92857c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "671f8295.0e6f6c",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Delete a file",
|
||||
"info": "File node can delete a file.",
|
||||
"x": 170,
|
||||
"y": 540,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "542cc2f4.92857c",
|
||||
"type": "file",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "delete",
|
||||
"encoding": "none",
|
||||
"x": 420,
|
||||
"y": 600,
|
||||
"wires": [
|
||||
[
|
||||
"a24da523.5babe8"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "a24da523.5babe8",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 630,
|
||||
"y": 600,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "51157051.2f62",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓delete a file",
|
||||
"info": "",
|
||||
"x": 390,
|
||||
"y": 560,
|
||||
"wires": []
|
||||
}
|
||||
]
|
@ -0,0 +1,113 @@
|
||||
[
|
||||
{
|
||||
"id": "e4ef1f5e.7cd82",
|
||||
"type": "inject",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"props": [
|
||||
{
|
||||
"p": "payload"
|
||||
},
|
||||
{
|
||||
"p": "topic",
|
||||
"vt": "str"
|
||||
}
|
||||
],
|
||||
"repeat": "",
|
||||
"crontab": "",
|
||||
"once": false,
|
||||
"onceDelay": 0.1,
|
||||
"topic": "",
|
||||
"payload": "8J+YgA==",
|
||||
"payloadType": "str",
|
||||
"x": 220,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"72b37cc8.177054"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "f5997af4.5a9298",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "Specify encoding of written data",
|
||||
"info": "File node can specify encoding of data.",
|
||||
"x": 230,
|
||||
"y": 740,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "72b37cc8.177054",
|
||||
"type": "file",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"appendNewline": true,
|
||||
"createDir": false,
|
||||
"overwriteFile": "true",
|
||||
"encoding": "base64",
|
||||
"x": 400,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"2da33ec.f45cac2"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2e814354.278c8c",
|
||||
"type": "debug",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"active": true,
|
||||
"tosidebar": true,
|
||||
"console": false,
|
||||
"tostatus": false,
|
||||
"complete": "false",
|
||||
"statusVal": "",
|
||||
"statusType": "auto",
|
||||
"x": 790,
|
||||
"y": 820,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "2da33ec.f45cac2",
|
||||
"type": "file in",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "",
|
||||
"filename": "/tmp/hello.txt",
|
||||
"format": "utf8",
|
||||
"chunk": false,
|
||||
"sendError": false,
|
||||
"encoding": "none",
|
||||
"x": 600,
|
||||
"y": 820,
|
||||
"wires": [
|
||||
[
|
||||
"2e814354.278c8c"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ec754c99.84bfd",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↓write string with base64 encoding",
|
||||
"info": "",
|
||||
"x": 460,
|
||||
"y": 780,
|
||||
"wires": []
|
||||
},
|
||||
{
|
||||
"id": "3e6704ff.4ce25c",
|
||||
"type": "comment",
|
||||
"z": "4b63452d.672afc",
|
||||
"name": "↑read result from file",
|
||||
"info": "",
|
||||
"x": 610,
|
||||
"y": 860,
|
||||
"wires": []
|
||||
}
|
||||
]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user