diff --git a/.gitignore b/.gitignore
index c3fa9624a..7b1f1f219 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ packages/node_modules/@node-red/editor-client/public
!test/**/node_modules
docs
!packages/node_modules/**/docs
+.vscode
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index a101eecb0..26a0606fe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,15 @@
sudo: false
+addons:
+ chrome: stable
language: node_js
matrix:
include:
+ - node_js: "14"
- node_js: "12"
- node_js: "10"
script:
- ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
+ - scripts/install-ui-test-dependencies.sh && grunt test-ui
before_script:
- npm install -g istanbul coveralls
- node_js: "8"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d24243fb..f2993c591 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,195 @@
+### 1.1.0: Milestone Release
+
+Editor
+
+ - Align node labels on FF
+ - Fix node toggle button initial opacity
+ - Make color/icon/label-pos pickers keyboard navigable
+ - Default group label to be shown and improve toggle button
+ - Fix clearing group label
+ - Remove hardcoded css Fixes #2603
+ - Fix node button mouse pointer css
+ - Change node linebreak handling to use "\n "
+ - Handle import of node with non-default number of outputs
+ - Improve display of focussed form element
+ - Fix typedInput error on empty subflow input types #2624 (@HiroyasuNishiyama)
+ - Update JP message catalogue for subflow input type #2471 (@HiroyasuNishiyama)
+ - Outliner - add empty item when last config node moved
+ - Update zh-CN/zh-TW translations #2626 (@JiyeYu)
+ - Add default shortcut for `core:show-help-tab`
+ - Clear outline focus on config node sidebar panel
+ - Tweak group margin to fit node status and look better
+ - Fix reparenting nodes in outliner when they change
+
+Runtime
+
+ - Add developer options - permits npm run build-dev #2628 (@Steve-Mcl)
+
+Nodes
+ - Add example flows for lots of core nodes #2585 #2550 #2549 (@HiroyasuNishiyama)
+ - TCP: Fix tcp in node finishing packets when in streaming base64 receive mode.
+ - Join: Clear timeout when msg.reset received Fixes #2471
+ - Switch: JSONata expr does not require msg.parts.count
+ - Inject: fix backwards migration of inject without topic
+
+#### 1.1.0-beta.3: Beta Release
+
+Editor
+
+ - Fix wiring nodes from input back to output
+ - Fix sometimes unable to keyboard-move group to left/up
+ - Fix group position in outliner
+ - Handle unknown nodes with no icon
+ - Prevent node creep when switching tabs
+
+#### 1.1.0-beta.2: Beta Release
+
+Editor
+
+ - Add UI tests to travis build #2593 #2616 #2617 #2619 (@kazuhitoyokoi)
+ - Add Japanese translations for outliner, jsonata and runtime #2618 (@kazuhitoyokoi)
+ - Fix deleting node in group after changing selection
+ - Fixup padding of quick-add search box
+ - Move config nodes under type-level hierarchy in outline
+ - Emit nodes:change event for config node users list modified
+ - Increase group margin to avoid clash with status text
+ - Fix event order when quick-adding node to group
+ - Switch RED.events.DEBUG messages to warn to get stacktraces
+ - Fix empty item handling for subflows/config in outliner
+ - Fix search indexing of group nodes
+ - Avoid regenerating every node label on redraw
+ - Fix handling of multi-line node label
+ - Disable merge group menu for single item or non-group item #2611 (@HiroyasuNishiyama)
+ - Merge pull request #2609 from node-red-hitachi/fix-remove-from-group
+ - Fix position of empty group with multi-line label #2612 (@HiroyasuNishiyama)
+ - Make treelist of subflow/config nodes initially have empty placeholder
+ - Fix empty placeholder not shown on remove from group #2609 (@HiroyasuNishiyama)
+ - Prevent conversion of circular structure #2607 (@HiroyasuNishiyama)
+ - Handle null status text in the editor Fixes #2606
+ - Massively reduce our dependency on d3 to render the view
+ - EditableList/TreeList - defer adding elements to DOM
+ - Prevent RED.stop being called multiple times if >1 signal received
+ - Flag a node as removed when it is disabled
+ - Some performance improvements for TreeList
+ - Resize info/help sidebars whenever sidebar is opened
+ - Add search defaults to outliner searchBox
+ - Add search presets option to searchBox widget
+ - Add RED.popover.menu as a new type of menu widget
+ - Add support for is:XYZ search flags
+ - Track subflow instances on the subflow node itself
+ - Refresh outline filter whenever something changes Fixes #2601
+ - Fix Help tab search box appearance
+ - Rename Node Information to Information in sidebar
+ - Do a sync-redraw after clearing to ensure clean state
+ - Make catch/status/complete/link filter case-insensitive
+ - Add 'add' option to touch radialMenu for quick-add dialog
+ - Merge branch 'dev' of https://github.com/node-red/node-red into dev
+ - ensure trigger node detects changes to number of outputs
+ - Ignore whitespace when checking function setup/close code
+ - Preserve event handlers when moving outliner items
+ - Add tooltips to outliner buttons
+ - Only validate nodes once they have all been imported
+ - Ensure configNode.users is updated properly on import
+
+Runtime
+
+ - Bump node-red-admin 0.2.6
+
+Nodes
+
+ - WebSocket: Prevent charAt call on websocket listener #2610 ()
+ - Debug: fix status to migrate old nodes to correct default mode.
+ - Link: Fix Link node filter Fixes #2600
+
+
+#### 1.1.0-beta.1: Beta Release
+
+Runtime
+
+ - Allow HTTPS settings to be refreshed #2551 (@bartbutenaers)
+ - Add support for moment in JSONata expressions #2583 (@dxdc)
+ - Add httpAdminMiddleware for admin routes #2555
+ - Add admin api authentication function #2479 (@KazuhiroItoh)
+ - Add option support for overwriting settings.js #2463 (@HiroyasuNishiyama)
+ - Add support for credential-stored env var in subflow #2368
+ - Add node installation from other than public site #2378 (@KazuhiroItoh)
+ - Catch more signals to allow clean context flush on shutdown #2447
+ - Add `node-red admin` command #2592
+ - Move to `lodash.clonedeep` #2396 (@amodelbello)
+ - Tidy up unhandledRejection warning from context unit tests
+ - Add test cases for setMessageProperty with non-object properties
+ - Fix for settings.set subsequent updates #2584 (@sammachin)
+ - Turn off installer funding messages
+ - Remove unused \_info/\_type subflow env var magic values
+ - Add #! lines to project shell scripts #2548
+ - Add nodejs14 to Travis test matrix
+ - Remove duplicate NLS message #2516 (@alexk111)
+ - Let setMessageProperty return success flag #2439
+
+Editor
+
+ - Add ability to group nodes #2493
+ - Add loading progress bar #2558
+ - Add Outliner to Info sidebar and add help sidebar #2556
+ - Add action to toggle node label visibility #2569
+ - Add show-examples-import-dialog action
+ - Add more consistent events in the editor #2543
+ - Save the node description property to the library #2490 (@kazuhitoyokoi)
+ - Add credential type to TypedInput #2367
+ - Scroll the view with WASD/Cursor keys when nothing selected #2381
+ - Bump jquery/migrate to latest versions
+ - Fix editor underscore visibility on Linux systems #2579 (@ristomatti)
+ - Support setting title on typedInput multi-option #2586 (@Steve-Mcl)
+ - Projects: Allow remote branch dialog to create non-default remote branches
+ - Ensure auth failure on project fetch identifies the remote #2545
+ - Make all dialogs handle smaller height screens better
+ - Add basic Array.from polyfill for IE11
+ - Add some more trap form elements to workaround Chrome autofill
+ - [info-sidebar] Handle node/group/flows with \n in their name
+ - [popover] Allow hover-type popovers to contain buttons
+ - Modify RED.panels to use flexbox position
+ - Allow node edit dialog to be opened on a non-default tab
+ - Add createNodeIcon and getDarkerColor to RED.utils
+ - [search] Refactor search to use editor events to generate index
+ - Allow RED.notify.popover to have a position offset
+ - Make selected list item more distinct
+ - Allow node button to be clicked via api call
+ - Reorder initial load so projects:load event emits before any nodes:add
+ - Add polyfills for IE11
+ - Activate project menu after initial clone #2547 (@HiroyasuNishiyama)
+ - Fix replacement of unknown node in workspace when module installed #2524 (@HiroyasuNishiyama)
+ - Fix appearance of subflow template panel #2506 (@HiroyasuNishiyama)
+ - Fix workspace CSS properties syntax #2487 (@bonanitech)
+ - Consolidate duplicate selectors #2488 (@bonanitech)
+ - Update message catalogue for subflow UI #2466 (@HiroyasuNishiyama)
+
+Nodes
+
+ - Batch: Add reset feature to batch node #2553 (@HiroyasuNishiyama)
+ - Catch/Complete/Link/Status: #2588 Add compact searchBox to filter node lists
+ - Catch/Complete/Link/Status: Allow searchBox filter to filter on node type #2595 (@jeancarl)
+ - CSV: Add warn when unpaired quotes detected on input.
+ - CSV: allow node to only send headers once
+ - CSV: Allow CR and LF control chars to be a part of the value #2526 (@tmdoit)
+ - CSV: Add support for parsing empty strings and null values #2510 (@tmdoit)
+ - CSV: Update Japanese translations for CSV node #2562 (@kazuhitoyokoi)
+ - Debug: Add bulk-activate/deactive actions for debug node #2570 (@cinhcet)
+ - Debug: Show status independently of main output #2564
+ - Delay: Ensure delay node rate limit timer is cleared on reset
+ - Function: Make the function node top-level async
+ - Function: Add support of initialization & finalization to function node #2498 (@HiroyasuNishiyama)
+ - HTTP In: Remove nodejs deprecation warning #2540 (@vladimir-kazan)
+ - HTTP Request: Support sending body in GET requests #2478 (@hardillb)
+ - Inject: Adding user definable properties to inject node #2435 (@PaulWieland)
+ - TCP: Allow to know particular session from status node #2413 (@dvv)
+ - Trigger: Add optional second output
+ - Trigger: Ensure trigger sends complete 2nd msg if set to send latest msg
+ - Trigger: Allow trigger node to use other than msg.topic to separate streams
+ - XML: Moved XML options documentation property from Outputs to Inputs section #2572 (@jeancarl)
+ - Add some core node example flows #2455 (@HiroyasuNishiyama)
+ - Change types from text/x-red to text/html in node html files #2425 (@kazuhitoyokoi)
+
+
#### 1.0.6: Maintenance Release
Runtime
@@ -119,7 +311,7 @@ Runtime
- #2332 Fix error handling of nodes with multiple input handlers
- Add script to generate npm publish script
- #2371 Ensure folder is present before write (e.g. flows file not in user folder)
- - #2371 Handle windows UNC '\\' paths
+ - #2371 Handle windows UNC '\' paths
- #2366 Handle logging of non-JSON encodable objects
Editor
diff --git a/Gruntfile.js b/Gruntfile.js
index 7593fded9..8c18dc0fb 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -125,6 +125,7 @@ module.exports = function(grunt) {
src: [
// Ensure editor source files are concatenated in
// the right order
+ "packages/node_modules/@node-red/editor-client/src/js/polyfills.js",
"packages/node_modules/@node-red/editor-client/src/js/jquery-addons.js",
"packages/node_modules/@node-red/editor-client/src/js/red.js",
"packages/node_modules/@node-red/editor-client/src/js/events.js",
@@ -151,6 +152,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js",
+ "packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
@@ -163,6 +165,8 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/sidebar.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/palette.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js",
+ "packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js",
+ "packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
@@ -177,6 +181,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
+ "packages/node_modules/@node-red/editor-client/src/js/ui/group.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
@@ -618,6 +623,10 @@ module.exports = function(grunt) {
grunt.registerTask('build',
'Builds editor content',
['clean:build','jsonlint','concat:build','concat:vendor','copy:build','uglify:build','sass:build','attachCopyright']);
+
+ grunt.registerTask('build-dev',
+ 'Developer mode: build dev version',
+ ['clean:build','concat:build','concat:vendor','copy:build','sass:build','setDevEnv']);
grunt.registerTask('dev',
'Developer mode: run node-red, watch for source changes and build/restart',
diff --git a/package.json b/package.json
index 1dd0937ba..cd30686ce 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red",
- "version": "1.0.6",
+ "version": "1.1.0",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"license": "Apache-2.0",
@@ -13,6 +13,8 @@
"start": "node packages/node_modules/node-red/red.js",
"test": "grunt",
"build": "grunt build",
+ "dev": "grunt dev",
+ "build-dev": "grunt build-dev",
"docs": "grunt docs"
},
"contributors": [
@@ -24,20 +26,20 @@
}
],
"dependencies": {
- "ajv": "6.12.0",
+ "ajv": "6.12.2",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
"cheerio": "0.22.0",
"clone": "2.1.2",
"content-type": "1.0.4",
- "cookie": "0.4.0",
+ "cookie": "0.4.1",
"cookie-parser": "1.4.5",
"cors": "2.8.5",
"cron": "1.7.2",
"denque": "1.4.1",
"express": "4.17.1",
- "express-session": "1.17.0",
+ "express-session": "1.17.1",
"fs-extra": "8.1.0",
"fs.notify": "0.0.4",
"hash-sum": "2.0.0",
@@ -45,16 +47,19 @@
"i18next": "15.1.2",
"iconv-lite": "0.5.1",
"is-utf8": "0.2.1",
- "js-yaml": "3.13.1",
+ "js-yaml": "3.14.0",
"json-stringify-safe": "5.0.1",
"jsonata": "1.8.3",
+ "lodash.clonedeep": "^4.5.0",
"media-typer": "1.1.0",
"memorystore": "1.6.2",
- "mime": "2.4.4",
+ "mime": "2.4.6",
+ "moment-timezone": "^0.5.31",
"mqtt": "2.18.8",
"multer": "1.4.2",
"mustache": "4.0.1",
- "node-red-node-rbe": "^0.2.6",
+ "node-red-admin": "^0.2.6",
+ "node-red-node-rbe": "^0.2.9",
"node-red-node-sentiment": "^0.1.6",
"node-red-node-tail": "^0.1.0",
"nopt": "4.0.3",
@@ -66,7 +71,7 @@
"raw-body": "2.4.1",
"request": "2.88.0",
"semver": "6.3.0",
- "uglify-js": "3.8.1",
+ "uglify-js": "3.9.4",
"when": "3.7.8",
"ws": "6.2.1",
"xml2js": "0.4.23"
@@ -76,7 +81,7 @@
},
"devDependencies": {
"marked": "0.8.2",
- "dompurify": "2.0.8",
+ "dompurify": "2.0.11",
"grunt": "~1.0.4",
"grunt-chmod": "~1.1.1",
"grunt-cli": "~1.3.2",
@@ -97,14 +102,14 @@
"grunt-npm-command": "~0.1.2",
"grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1",
- "http-proxy": "1.18.0",
+ "http-proxy": "1.18.1",
"istanbul": "0.4.5",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"minami": "1.2.3",
"mocha": "^5.2.0",
"mosca": "^2.8.3",
- "node-red-node-test-helper": "^0.2.3",
- "node-sass": "^4.13.1",
+ "node-red-node-test-helper": "^0.2.5",
+ "node-sass": "^4.14.1",
"should": "^8.4.0",
"sinon": "1.17.7",
"stoppable": "^1.1.0",
diff --git a/packages/node_modules/@node-red/editor-api/lib/admin/nodes.js b/packages/node_modules/@node-red/editor-api/lib/admin/nodes.js
index 2787a5c36..b78de9d75 100644
--- a/packages/node_modules/@node-red/editor-api/lib/admin/nodes.js
+++ b/packages/node_modules/@node-red/editor-api/lib/admin/nodes.js
@@ -44,6 +44,7 @@ module.exports = {
user: req.user,
module: req.body.module,
version: req.body.version,
+ url: req.body.url,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.addModule(opts).then(function(info) {
diff --git a/packages/node_modules/@node-red/editor-api/lib/auth/index.js b/packages/node_modules/@node-red/editor-api/lib/auth/index.js
index 189f903d8..d4ec10f08 100644
--- a/packages/node_modules/@node-red/editor-api/lib/auth/index.js
+++ b/packages/node_modules/@node-red/editor-api/lib/auth/index.js
@@ -36,6 +36,7 @@ var log = require("@node-red/util").log; // TODO: separate module
passport.use(strategies.bearerStrategy.BearerStrategy);
passport.use(strategies.clientPasswordStrategy.ClientPasswordStrategy);
passport.use(strategies.anonymousStrategy);
+passport.use(strategies.tokensStrategy);
var server = oauth2orize.createServer();
@@ -60,7 +61,7 @@ function init(_settings,storage) {
function needsPermission(permission) {
return function(req,res,next) {
if (settings && settings.adminAuth) {
- return passport.authenticate(['bearer','anon'],{ session: false })(req,res,function() {
+ return passport.authenticate(['bearer','tokens','anon'],{ session: false })(req,res,function() {
if (!req.user) {
return next();
}
diff --git a/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js b/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js
index b17bf1473..87023a487 100644
--- a/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js
+++ b/packages/node_modules/@node-red/editor-api/lib/auth/strategies.js
@@ -123,9 +123,38 @@ AnonymousStrategy.prototype.authenticate = function(req) {
});
}
+function TokensStrategy() {
+ passport.Strategy.call(this);
+ this.name = 'tokens';
+}
+util.inherits(TokensStrategy, passport.Strategy);
+TokensStrategy.prototype.authenticate = function(req) {
+ var self = this;
+ var token = null;
+ if (Users.tokenHeader() === 'authorization') {
+ if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
+ token = req.headers.authorization.split(' ')[1];
+ }
+ } else {
+ token = req.headers[Users.tokenHeader()];
+ }
+ if (token) {
+ Users.tokens(token).then(function(admin) {
+ if (admin) {
+ self.success(admin,{scope:admin.permissions});
+ } else {
+ self.fail(401);
+ }
+ });
+ } else {
+ self.fail(401);
+ }
+}
+
module.exports = {
bearerStrategy: bearerStrategy,
clientPasswordStrategy: clientPasswordStrategy,
passwordTokenExchange: passwordTokenExchange,
- anonymousStrategy: new AnonymousStrategy()
+ anonymousStrategy: new AnonymousStrategy(),
+ tokensStrategy: new TokensStrategy()
}
diff --git a/packages/node_modules/@node-red/editor-api/lib/auth/users.js b/packages/node_modules/@node-red/editor-api/lib/auth/users.js
index 24a762958..f032332db 100644
--- a/packages/node_modules/@node-red/editor-api/lib/auth/users.js
+++ b/packages/node_modules/@node-red/editor-api/lib/auth/users.js
@@ -59,7 +59,9 @@ function getDefaultUser() {
var api = {
get: get,
authenticate: authenticate,
- default: getDefaultUser
+ default: getDefaultUser,
+ tokens: getDefaultUser,
+ tokenHeader: "authorization"
}
function init(config) {
@@ -105,6 +107,12 @@ function init(config) {
} else {
api.default = getDefaultUser;
}
+ if (config.tokens && typeof config.tokens === "function") {
+ api.tokens = config.tokens;
+ if (config.tokenHeader && typeof config.tokenHeader === "string") {
+ api.tokenHeader = config.tokenHeader.toLowerCase();
+ }
+ }
}
function cleanUser(user) {
if (user && user.hasOwnProperty('password')) {
@@ -118,5 +126,7 @@ module.exports = {
init: init,
get: function(username) { return api.get(username).then(cleanUser)},
authenticate: function() { return api.authenticate.apply(null, arguments) },
- default: function() { return api.default(); }
+ default: function() { return api.default(); },
+ tokens: function(token) { return api.tokens(token); },
+ tokenHeader: function() { return api.tokenHeader }
};
diff --git a/packages/node_modules/@node-red/editor-api/lib/index.js b/packages/node_modules/@node-red/editor-api/lib/index.js
index 0dc06ab71..534a77869 100644
--- a/packages/node_modules/@node-red/editor-api/lib/index.js
+++ b/packages/node_modules/@node-red/editor-api/lib/index.js
@@ -59,6 +59,12 @@ function init(settings,_server,storage,runtimeAPI) {
});
adminApp.use(corsHandler);
+ if (settings.httpAdminMiddleware) {
+ if (typeof settings.httpAdminMiddleware === "function") {
+ adminApp.use(settings.httpAdminMiddleware)
+ }
+ }
+
auth.init(settings,storage);
var maxApiRequestSize = settings.apiMaxLength || '5mb';
diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json
index 4f86c296d..16f82f676 100644
--- a/packages/node_modules/@node-red/editor-api/package.json
+++ b/packages/node_modules/@node-red/editor-api/package.json
@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
- "version": "1.0.6",
+ "version": "1.1.0",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,16 +16,16 @@
}
],
"dependencies": {
- "@node-red/util": "1.0.6",
- "@node-red/editor-client": "1.0.6",
+ "@node-red/util": "1.1.0",
+ "@node-red/editor-client": "1.1.0",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
"clone": "2.1.2",
"cors": "2.8.5",
- "express-session": "1.17.0",
+ "express-session": "1.17.1",
"express": "4.17.1",
"memorystore": "1.6.2",
- "mime": "2.4.4",
+ "mime": "2.4.6",
"mustache": "4.0.1",
"oauth2orize": "1.11.0",
"passport-http-bearer": "1.0.1",
diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
index ed4d4f9a6..309f9db89 100755
--- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
@@ -14,7 +14,15 @@
"back": "Back",
"next": "Next",
"clone": "Clone project",
- "cont": "Continue"
+ "cont": "Continue",
+ "style": "Style",
+ "line": "Outline",
+ "fill": "Fill",
+ "label": "Label",
+ "color": "Color",
+ "position": "Position",
+ "enable": "Enable",
+ "disable": "Disable"
},
"type": {
"string": "string",
@@ -28,6 +36,13 @@
"null": "null"
}
},
+ "event": {
+ "loadPalette": "Loading Palette",
+ "loadNodeCatalogs": "Loading Node catalogs",
+ "loadNodes": "Loading Nodes __count__",
+ "loadFlows": "Loading Flows",
+ "importFlows": "Adding Flows to workspace"
+ },
"workspace": {
"defaultName": "Flow __number__",
"editFlow": "Edit flow: __name__",
@@ -91,7 +106,12 @@
"projects-new": "New",
"projects-open": "Open",
"projects-settings": "Project Settings",
- "showNodeLabelDefault": "Show label of newly added nodes"
+ "showNodeLabelDefault": "Show label of newly added nodes",
+ "groups": "Groups",
+ "groupSelection": "Group selection",
+ "ungroupSelection": "Ungroup selection",
+ "groupMergeSelection": "Merge selection",
+ "groupRemoveSelection": "Remove from group"
}
},
"actions": {
@@ -171,6 +191,8 @@
"node_plural": "__count__ nodes",
"configNode": "__count__ configuration node",
"configNode_plural": "__count__ configuration nodes",
+ "group": "__count__ group",
+ "group_plural": "__count__ groups",
"flow": "__count__ flow",
"flow_plural": "__count__ flows",
"subflow": "__count__ subflow",
@@ -186,6 +208,9 @@
"nodesImported": "Imported:",
"nodeCopied": "__count__ node copied",
"nodeCopied_plural": "__count__ nodes copied",
+ "groupCopied": "__count__ group copied",
+ "groupCopied_plural": "__count__ groups copied",
+ "groupStyleCopied": "Group style copied",
"invalidFlow": "Invalid flow: __message__",
"export": {
"selected":"selected nodes",
@@ -308,6 +333,13 @@
"multipleInputsToSelection": "Cannot create subflow: multiple inputs to selection"
}
},
+ "group": {
+ "editGroup": "Edit group: __name__",
+ "errors": {
+ "cannotCreateDiffGroups": "Cannot create group using nodes from different groups",
+ "cannotAddSubflowPorts": "Cannot add subflow ports to a group"
+ }
+ },
"editor": {
"configEdit": "Edit",
"configAdd": "Add",
@@ -337,6 +369,7 @@
"locale": "Select UI Language",
"icon": "Icon",
"inputType": "Input type",
+ "selectType": "select types...",
"inputs" : {
"input": "input",
"select": "select",
@@ -351,7 +384,8 @@
"bool": "bool",
"json": "JSON",
"bin": "buffer",
- "env": "env variable"
+ "env": "env variable",
+ "cred": "credential"
},
"menu": {
"input": "input",
@@ -533,11 +567,12 @@
},
"sidebar": {
"info": {
- "name": "Node information",
+ "name": "Information",
"tabName": "Name",
"label": "info",
"node": "Node",
"type": "Type",
+ "group": "Group",
"module": "Module",
"id": "ID",
"status": "Status",
@@ -560,7 +595,29 @@
"nodeHelp": "Node Help",
"none":"None",
"arrayItems": "__count__ items",
- "showTips":"You can open the tips from the settings panel"
+ "showTips":"You can open the tips from the settings panel",
+ "outline": "Outline",
+ "empty": "empty",
+ "globalConfig": "Global Configuration Nodes",
+ "triggerAction": "Trigger action",
+ "find": "Find in workspace",
+ "search": {
+ "configNodes": "Configuration nodes",
+ "unusedConfigNodes": "Unused configuration nodes",
+ "invalidNodes": "Invalid nodes",
+ "uknownNodes": "Unknown nodes",
+ "unusedSubflows": "Unused subflows"
+ }
+ },
+ "help": {
+ "name": "Help",
+ "label": "help",
+ "search": "Search help",
+ "nodeHelp": "Node Help",
+ "showHelp": "Show help",
+ "showInOutline": "Show in outline",
+ "showTopics": "Show topics",
+ "noHelp": "No help topic selected"
},
"config": {
"name": "Configuration nodes",
@@ -613,7 +670,6 @@
"removeFromProject": "remove from project",
"addToProject": "add to project",
"files": "Files",
- "package": "Package",
"flow": "Flow",
"credentials": "Credentials",
"package":"Package",
@@ -757,7 +813,8 @@
"bin": "buffer",
"date": "timestamp",
"jsonata": "expression",
- "env": "env variable"
+ "env": "env variable",
+ "cred": "credential"
}
},
"editableList": {
@@ -804,9 +861,9 @@
"expandItems": "Expand items",
"collapseItems": "Collapse items",
"duplicate": "Duplicate",
- "error": {
- "invalidJSON": "Invalid JSON: "
- }
+ "error": {
+ "invalidJSON": "Invalid JSON: "
+ }
},
"markdownEditor": {
"title": "Markdown editor",
@@ -978,7 +1035,7 @@
"retry": "Retry",
"update-failed": "Failed to update auth",
"unhandled": "Unhandled error response",
- "host-key-verify-failed": "
Host key verification failed.
The repository host key could not be verified. Please update your known_hosts
file and try again."
+ "host-key-verify-failed": "
Host key verification failed.
The repository host key could not be verified. Please update your known_hosts
file and try again.
"
},
"create-branch-list": {
"invalid": "Invalid branch",
diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json b/packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
index d777d1919..57ebb00a7 100755
--- a/packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
+++ b/packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
@@ -266,5 +266,9 @@
"$type": {
"args": "value",
"desc": "Returns the type of `value` as a string. If `value` is undefined, this will return `undefined`"
+ },
+ "$moment": {
+ "args": "[str]",
+ "desc": "Gets a date object using the Moment library."
}
}
diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
old mode 100755
new mode 100644
index cf04ced1d..5422fe440
--- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
@@ -14,7 +14,15 @@
"back": "戻る",
"next": "進む",
"clone": "プロジェクトをクローン",
- "cont": "続ける"
+ "cont": "続ける",
+ "style": "形式",
+ "line": "線",
+ "fill": "塗りつぶし",
+ "label": "ラベル",
+ "color": "色",
+ "position": "配置",
+ "enable": "有効",
+ "disable": "無効"
},
"type": {
"string": "文字列",
@@ -28,6 +36,13 @@
"null": "null"
}
},
+ "event": {
+ "loadPalette": "パレットを読み込み中",
+ "loadNodeCatalogs": "ノードカタログを読み込み中",
+ "loadNodes": "ノードを読み込み中 __count__",
+ "loadFlows": "フローを読み込み中",
+ "importFlows": "ワークスペースにフローを追加中"
+ },
"workspace": {
"defaultName": "フロー __number__",
"editFlow": "フローを編集: __name__",
@@ -67,7 +82,7 @@
"settings": "設定",
"userSettings": "ユーザ設定",
"nodes": "ノード",
- "displayStatus": "ノードの状態を表示",
+ "displayStatus": "ノードのステータスを表示",
"displayConfig": "ノードの設定",
"import": "読み込み",
"export": "書き出し",
@@ -91,7 +106,12 @@
"projects-new": "新規",
"projects-open": "開く",
"projects-settings": "設定",
- "showNodeLabelDefault": "追加したノードのラベルを表示"
+ "showNodeLabelDefault": "追加したノードのラベルを表示",
+ "groups": "グループ",
+ "groupSelection": "選択部分をグループ化",
+ "ungroupSelection": "選択部分をグループ解除",
+ "groupMergeSelection": "選択部分をマージ",
+ "groupRemoveSelection": "グループから削除"
}
},
"actions": {
@@ -171,6 +191,8 @@
"node_plural": "__count__ 個のノード",
"configNode": "__count__ 個の設定ノード",
"configNode_plural": "__count__ 個の設定ノード",
+ "group": "__count__ 個のグループ",
+ "group_plural": "__count__ 個のグループ",
"flow": "__count__ 個のフロー",
"flow_plural": "__count__ 個のフロー",
"subflow": "__count__ 個のサブフロー",
@@ -186,6 +208,9 @@
"nodesImported": "読み込みました:",
"nodeCopied": "__count__ 個のノードをコピーしました",
"nodeCopied_plural": "__count__ 個のノードをコピーしました",
+ "groupCopied": "__count__ 個のグループをコピーしました",
+ "groupCopied_plural": "__count__ 個のグループをコピーしました",
+ "groupStyleCopied": "グループの形式をコピーしました",
"invalidFlow": "不正なフロー: __message__",
"export": {
"selected": "選択したフロー",
@@ -308,6 +333,13 @@
"multipleInputsToSelection": "サブフローを作成できません: 複数の入力が選択されています"
}
},
+ "group": {
+ "editGroup": "__name__ グループを編集",
+ "errors": {
+ "cannotCreateDiffGroups": "異なるグループのノードを使用してグループを作成することはできません",
+ "cannotAddSubflowPorts": "グループにサブフローの端子を追加できません"
+ }
+ },
"editor": {
"configEdit": "編集",
"configAdd": "追加",
@@ -337,6 +369,7 @@
"locale": "UI言語の選択",
"icon": "記号",
"inputType": "入力形式",
+ "selectType": "形式選択...",
"inputs": {
"input": "入力",
"select": "メニュー",
@@ -351,7 +384,8 @@
"bool": "真偽",
"json": "JSON",
"bin": "バッファ",
- "env": "環境変数"
+ "env": "環境変数",
+ "cred": "認証情報"
},
"menu": {
"input": "入力",
@@ -538,6 +572,7 @@
"label": "情報",
"node": "ノード",
"type": "型",
+ "group": "グループ",
"module": "モジュール",
"id": "ID",
"status": "状態",
@@ -560,7 +595,29 @@
"nodeHelp": "ノードのヘルプ",
"none": "なし",
"arrayItems": "__count__ 要素",
- "showTips": "設定からヒントを表示できます"
+ "showTips": "設定からヒントを表示できます",
+ "outline": "アウトライン",
+ "empty": "空",
+ "globalConfig": "グローバル設定ノード",
+ "triggerAction": "アクションを実行",
+ "find": "ワークスペース内を検索",
+ "search": {
+ "configNodes": "設定ノード",
+ "unusedConfigNodes": "未使用の設定ノード",
+ "invalidNodes": "不正なノード",
+ "uknownNodes": "未知のノード",
+ "unusedSubflows": "未使用のサブフロー"
+ }
+ },
+ "help": {
+ "name": "ヘルプ",
+ "label": "ヘルプ",
+ "search": "ヘルプを検索",
+ "nodeHelp": "ノードヘルプ",
+ "showHelp": "ヘルプを表示",
+ "showInOutline": "アウトラインに表示",
+ "showTopics": "トピックを表示",
+ "noHelp": "ヘルプのトピックが未選択"
},
"config": {
"name": "ノードの設定を表示",
@@ -613,9 +670,9 @@
"removeFromProject": "プロジェクトから削除",
"addToProject": "プロジェクトへ追加",
"files": "ファイル",
- "package": "パッケージ",
"flow": "フロー",
"credentials": "認証情報",
+ "package": "パッケージ",
"packageCreate": "変更が保存された時にファイルが作成されます",
"fileNotExist": "ファイルが存在しません",
"selectFile": "ファイルを選択",
@@ -756,7 +813,8 @@
"bin": "バッファ",
"date": "日時",
"jsonata": "JSONata式",
- "env": "環境変数"
+ "env": "環境変数",
+ "cred": "認証情報"
}
},
"editableList": {
@@ -976,7 +1034,8 @@
"passphrase": "パスフレーズ",
"retry": "リトライ",
"update-failed": "認証の更新に失敗しました",
- "unhandled": "エラー応答が処理されませんでした"
+ "unhandled": "エラー応答が処理されませんでした",
+ "host-key-verify-failed": "ホストキーの検証に失敗
リポジトリのホストキーを検証できませんでした。known_hosts
ファイルを更新して、もう一度試してください。
"
},
"create-branch-list": {
"invalid": "不正なブランチ",
diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/jsonata.json b/packages/node_modules/@node-red/editor-client/locales/ja/jsonata.json
old mode 100755
new mode 100644
index 659cf66df..02973a69a
--- a/packages/node_modules/@node-red/editor-client/locales/ja/jsonata.json
+++ b/packages/node_modules/@node-red/editor-client/locales/ja/jsonata.json
@@ -266,5 +266,9 @@
"$type": {
"args": "value",
"desc": "`value` の型を文字列として返します。もし `value` が未定義の場合、 `undefined` が返されます。"
+ },
+ "$moment": {
+ "args": "[str]",
+ "desc": "Momentライブラリを使用して日付オブジェクトを取得します。"
}
}
diff --git a/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json b/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json
index 95d3fa5ee..3da4a5822 100644
--- a/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json
@@ -14,7 +14,15 @@
"back": "后退",
"next": "下一个",
"clone": "克隆项目",
- "cont": "继续"
+ "cont": "继续",
+ "style": "风格",
+ "line": "大纲",
+ "fill": "填充",
+ "label": "标签",
+ "color": "颜色",
+ "position": "位置",
+ "enable": "启用",
+ "disable": "禁用"
},
"type": {
"string": "字符串",
@@ -28,11 +36,18 @@
"null": "空"
}
},
+ "event": {
+ "loadPalette": "加载控制板",
+ "loadNodeCatalogs": "加载节点目录",
+ "loadNodes": "加载 __count__ 个节点",
+ "loadFlows": "加载流程",
+ "importFlows": "往工作区中加载流程"
+ },
"workspace": {
- "defaultName": "流程__number__",
+ "defaultName": "流程 __number__",
"editFlow": "编辑流程: __name__",
"confirmDelete": "确认删除",
- "delete": "你确定想删除 '__label__'?",
+ "delete": "你确定要删除 __label__ ?",
"dropFlowHere": "把流程放到这里",
"addFlow": "添加流程",
"listFlows": "流程一览",
@@ -91,7 +106,12 @@
"projects-new": "新建",
"projects-open": "打开",
"projects-settings": "项目设定",
- "showNodeLabelDefault": "显示新添加的节点的标签"
+ "showNodeLabelDefault": "显示新添加的节点的标签",
+ "groups": "组",
+ "groupSelection": "选择组",
+ "ungroupSelection": "取消选择组",
+ "groupMergeSelection": "合并选择",
+ "groupRemoveSelection": "从组中移除"
}
},
"actions": {
@@ -101,7 +121,7 @@
"zoom-in": "放大"
},
"user": {
- "loggedInAs": "作为__name__登陆",
+ "loggedInAs": "作为 __name__ 登陆",
"username": "账号",
"password": "密码",
"login": "登陆",
@@ -127,13 +147,13 @@
"missing_flow_file": "找不到项目流程文件。
该项目未配置流程文件。
",
"missing_package_file": "找不到项目包文件。
项目缺少package.json文件。
",
"project_empty": "该项目为空。
是否要创建一组默认的项目文件?
否则,您将必须在编辑器外部手动将文件添加到项目中。
",
- "project_not_found": "未找到项目'__project__'。
",
+ "project_not_found": "未找到项目 __project__ 。
",
"git_merge_conflict": "自动合并更改失败。
修复未合并的冲突,然后提交结果。
"
},
"error": "错误: __message__",
"errors": {
"lostConnection": "丢失与服务器的连接,重新连接...",
- "lostConnectionReconnect": "丢失与服务器的连接,__time__秒后重新连接",
+ "lostConnectionReconnect": "丢失与服务器的连接, __time__ 秒后重新连接",
"lostConnectionTry": "现在尝试",
"cannotAddSubflowToItself": "无法向其自身添加子流程",
"cannotAddCircularReference": "无法添加子流程 - 循环引用",
@@ -167,14 +187,16 @@
"clipboard": {
"clipboard": "剪贴板",
"nodes": "节点",
- "node": "__count__节点",
- "node_plural": "__count__节点",
- "configNode": "__count__配置节点",
- "configNode_plural": "__count__配置节点",
- "flow": "__count__流程",
- "flow_plural": "__count__流程",
- "subflow": "__count__子流程",
- "subflow_plural": "__count__子流程",
+ "node": "__count__ 个节点",
+ "node_plural": "__count__ 个节点",
+ "configNode": "__count__ 个配置节点",
+ "configNode_plural": "__count__ 个配置节点",
+ "group": "__count__ 个组",
+ "group_plural": "__count__ 个组",
+ "flow": "__count__ 个流程",
+ "flow_plural": "__count__ 个流程",
+ "subflow": "__count__ 个子流程",
+ "subflow_plural": "__count__ 子流程",
"pasteNodes": "在这里粘贴节点",
"selectFile": "选择要导入的文件",
"importNodes": "导入节点",
@@ -184,8 +206,11 @@
"importUnrecognised_plural": "导入了无法识别的类型:",
"nodesExported": "节点导出到了剪贴板",
"nodesImported": "导入:",
- "nodeCopied": "已复制__count__个节点",
- "nodeCopied_plural": "已复制__count__个节点",
+ "nodeCopied": "已复制 __count__ 个节点",
+ "nodeCopied_plural": "已复制 __count__ 个节点",
+ "groupCopied": "复制 __count__ 个组",
+ "groupCopied_plural": "已复制 __count__ 个groups",
+ "groupStyleCopied": "已复制组风格",
"invalidFlow": "无效的流程: __message__",
"export": {
"selected": "已选择的节点",
@@ -204,9 +229,9 @@
"newFlow": "新流程",
"errors": {
"notArray": "输入的不是JSON数组",
- "itemNotObject": "输入的流无效 - 项目__index__不是节点对象",
+ "itemNotObject": "输入的流无效 - 项目 __index__ 不是节点对象",
"missingId": "输入的流无效-项 __index__ 缺少'id'属性",
- "missingType": "输入的流程无效-项__index__缺少'类型'属性"
+ "missingType": "输入的流程无效-项 __index__ 缺少'类型'属性"
}
},
"copyMessagePath": "已复制路径",
@@ -250,7 +275,7 @@
"conflictChecking": "检查是否可以自动合并更改",
"conflictAutoMerge": "此更改不包括冲突,可以自动合并",
"conflictManualMerge": "这些更改包括了在部署之前必须解决的冲突。",
- "plusNMore": "+ __count__更多"
+ "plusNMore": "+ __count__ 更多"
}
},
"eventLog": {
@@ -287,11 +312,11 @@
"newVersionError": "新版本不包含有效的JSON:"
},
"subflow": {
- "editSubflowInstance": "编辑子流实例:__name__",
- "editSubflow": "编辑流程模板: __name__",
+ "editSubflowInstance": "编辑子流实例: __name__",
+ "editSubflow": "编辑流程模板: __name__",
"edit": "编辑流程模板",
- "subflowInstances": "这个子流程模板有__count__个实例",
- "subflowInstances_plural": "这个子流程模板有__count__个实例",
+ "subflowInstances": "这个子流程模板有 __count__ 个实例",
+ "subflowInstances_plural": "这个子流程模板有 __count__ 个实例",
"editSubflowProperties": "编辑属性",
"input": "输入:",
"output": "输出:",
@@ -308,17 +333,24 @@
"multipleInputsToSelection": "无法创建子流程: 多个输入到了选择"
}
},
+ "group": {
+ "editGroup": "编辑组: __name__",
+ "errors": {
+ "cannotCreateDiffGroups": "无法使用来自不同组的节点创建组",
+ "cannotAddSubflowPorts": "无法将子流程的端口添加到组"
+ }
+ },
"editor": {
"configEdit": "编辑",
"configAdd": "添加",
"configUpdate": "更新",
"configDelete": "删除",
- "nodesUse": "__count__个节点使用此配置",
- "nodesUse_plural": "__count__个节点使用此配置",
- "addNewConfig": "添加新的__type__配置",
- "editNode": "编辑__type__节点",
- "editConfig": "编辑__type__配置",
- "addNewType": "添加新的__type__节点",
+ "nodesUse": "__count__ 个节点使用此配置",
+ "nodesUse_plural": "__count__ 个节点使用此配置",
+ "addNewConfig": "添加新的 __type__ 配置",
+ "editNode": "编辑 __type__ 节点",
+ "editConfig": "编辑 __type__ 配置",
+ "addNewType": "添加新的 __type__ 节点",
"nodeProperties": "节点属性",
"label": "标签",
"color": "颜色",
@@ -337,6 +369,7 @@
"locale": "选择界面语言",
"icon": "图标",
"inputType": "输入类型",
+ "selectType": "选择类型...",
"inputs": {
"input": "输入",
"select": "选择",
@@ -351,7 +384,8 @@
"bool": "布尔",
"json": "JSON",
"bin": "buffer",
- "env": "环境变量"
+ "env": "环境变量",
+ "cred": "证书"
},
"menu": {
"input": "输入",
@@ -381,7 +415,7 @@
"scope": "范围",
"unassigned": "未分配",
"global": "全局",
- "workspace": "工作组",
+ "workspace": "工作区",
"selectAll": "选择所有节点",
"selectAllConnected": "选择所有连接的节点",
"addRemoveNode": "从选择中添加/删除节点",
@@ -460,33 +494,33 @@
"times": {
"seconds": "秒前",
"minutes": "分前",
- "minutesV": "__count__分前",
- "hoursV": "__count__小时前",
- "hoursV_plural": "__count__小时前",
- "daysV": "__count__天前",
- "daysV_plural": "__count__天前",
- "weeksV": "__count__周前",
- "weeksV_plural": "__count__周前",
- "monthsV": "__count__月前",
- "monthsV_plural": "__count__月前",
- "yearsV": "__count__年前",
- "yearsV_plural": "__count__年前",
- "yearMonthsV": "__y__年, __count__月前",
- "yearMonthsV_plural": "__y__年, __count__月前",
- "yearsMonthsV": "__y__年, __count__月前",
- "yearsMonthsV_plural": "__y__年, __count__月前"
+ "minutesV": "__count__ 分前",
+ "hoursV": "__count__ 小时前",
+ "hoursV_plural": "__count__ 小时前",
+ "daysV": "__count__ 天前",
+ "daysV_plural": "__count__ 天前",
+ "weeksV": "__count__ 周前",
+ "weeksV_plural": "__count__ 周前",
+ "monthsV": "__count__ 月前",
+ "monthsV_plural": "__count__ 月前",
+ "yearsV": "__count__ 年前",
+ "yearsV_plural": "__count__ 年前",
+ "yearMonthsV": "__y__ 年, __count__ 月前",
+ "yearMonthsV_plural": "__y__ 年, __count__ 月前",
+ "yearsMonthsV": "__y__ 年, __count__ 月前",
+ "yearsMonthsV_plural": "__y__ 年, __count__ 月前"
},
- "nodeCount": "__label__个节点",
- "nodeCount_plural": "__label__个节点",
- "moduleCount": "__count__个可用模块",
- "moduleCount_plural": "__count__个可用模块",
+ "nodeCount": "__label__ 个节点",
+ "nodeCount_plural": "__label__ 个节点",
+ "moduleCount": "__count__ 个可用模块",
+ "moduleCount_plural": "__count__ 个可用模块",
"inuse": "使用中",
"enableall": "全部启用",
"disableall": "全部禁用",
"enable": "启用",
"disable": "禁用",
"remove": "移除",
- "update": "更新至__version__版本",
+ "update": "更新至 __version__ 版本",
"updated": "已更新",
"install": "安装",
"installed": "已安装",
@@ -498,7 +532,7 @@
"sort": "排序:",
"sortAZ": "a-z顺序",
"sortRecent": "日期顺序",
- "more": "增加__count__个",
+ "more": "增加 __count__ 个",
"errors": {
"catalogLoadFailed": "无法加载节点目录。
查看浏览器控制台了解更多信息",
"installFailed": "无法安装: __module__
__message__
查看日志了解更多信息",
@@ -539,6 +573,7 @@
"label": "信息",
"node": "节点",
"type": "类型",
+ "group": "组",
"module": "模组",
"id": "ID",
"status": "状态",
@@ -560,8 +595,30 @@
"subflowDesc": "子流程描述",
"nodeHelp": "节点帮助",
"none": "无",
- "arrayItems": "__count__个项目",
- "showTips": "您可以从设置面板启用提示信息"
+ "arrayItems": "__count__ 个项目",
+ "showTips": "您可以从设置面板启用提示信息",
+ "outline": "大纲",
+ "empty": "空的",
+ "globalConfig": "全局配置节点",
+ "triggerAction": "触发动作",
+ "find": "在工作区中查找",
+ "search": {
+ "configNodes": "配置节点",
+ "unusedConfigNodes": "未使用的配置节点",
+ "invalidNodes": "无效的节点",
+ "uknownNodes": "未知的节点",
+ "unusedSubflows": "未使用的子流程"
+ }
+ },
+ "help": {
+ "name": "帮助",
+ "label": "帮助",
+ "search": "搜索帮助",
+ "nodeHelp": "节点帮助",
+ "showHelp": "显示帮助",
+ "showInOutline": "在大纲中显示",
+ "showTopics": "显示主题",
+ "noHelp": "未选择帮助主题"
},
"config": {
"name": "配置节点",
@@ -614,9 +671,9 @@
"removeFromProject": "从项目中删除",
"addToProject": "添加到项目",
"files": "文件",
- "package": "包",
"flow": "流程",
"credentials": "证书",
+ "package": "包",
"packageCreate": "保存更改后将创建文件",
"fileNotExist": "文件不存在",
"selectFile": "选择文件",
@@ -628,7 +685,7 @@
"changeTheEncryptionKey": "更改加密密钥",
"currentKey": "当前密钥",
"newKey": "新密钥",
- "credentialsAlert": "这将删除所有现有凭证",
+ "credentialsAlert": "这将删除所有现有证书",
"versionControl": "版本控制",
"branches": "分支",
"noBranches": "没有分支",
@@ -668,7 +725,7 @@
"copyPublicKey": "将公钥复制到剪贴板",
"delete": "删除密钥",
"gitConfig": "Git配置",
- "deleteConfirm": "您确定要删除SSH密钥__name__吗?这不能被撤消。"
+ "deleteConfirm": "您确定要删除SSH密钥 __name__ 吗?这不能被撤消。"
},
"versionControl": {
"unstagedChanges": "未暂存的变更",
@@ -722,24 +779,24 @@
"pullChanges": "拉取更改",
"history": "历史",
"projectHistory": "项目历史",
- "daysAgo": "__count__天前",
- "daysAgo_plural": "__count__天前",
- "hoursAgo": "__count__小时前",
- "hoursAgo_plural": "__count__小时前",
- "minsAgo": "__count__分钟前",
- "minsAgo_plural": "__count__分钟前",
+ "daysAgo": "__count__ 天前",
+ "daysAgo_plural": "__count__ 天前",
+ "hoursAgo": "__count__ 小时前",
+ "hoursAgo_plural": "__count__ 小时前",
+ "minsAgo": "__count__ 分钟前",
+ "minsAgo_plural": "__count__ 分钟前",
"secondsAgo": "秒前",
"notTracking": "您的本地分支当前未跟踪一个远程分支。",
"statusUnmergedChanged": "您的仓库中有未合并的更改。您需要解决冲突并提交结果。",
"repositoryUpToDate": "您的仓库是最新的。",
- "commitsAhead": "您的存储库领先远程仓库__count__次提交。您现在可以推送这些提交。",
- "commitsAhead_plural": "您的存储库领先远程仓库__count__次提交。您现在可以推送这些提交。",
- "commitsBehind": "您的存储库落后远程仓库__count__次提交。您现在可以拉取这些提交。",
- "commitsBehind_plural": "您的存储库落后远程仓库__count__次提交。您现在可以拉取这些提交。",
- "commitsAheadAndBehind1": "您的存储库落后远程仓库__count__次提交",
- "commitsAheadAndBehind1_plural": "您的存储库落后远程仓库__count__次提交",
- "commitsAheadAndBehind2": "领先远程仓库__count__次提交。",
- "commitsAheadAndBehind2_plural": "领先远程仓库__count__次提交。",
+ "commitsAhead": "您的存储库领先远程仓库 __count__ 次提交。您现在可以推送这些提交。",
+ "commitsAhead_plural": "您的存储库领先远程仓库 __count__ 次提交。您现在可以推送这些提交。",
+ "commitsBehind": "您的存储库落后远程仓库 __count__ 次提交。您现在可以拉取这些提交。",
+ "commitsBehind_plural": "您的存储库落后远程仓库 __count__ 次提交。您现在可以拉取这些提交。",
+ "commitsAheadAndBehind1": "您的存储库落后远程仓库 __count__ 次提交",
+ "commitsAheadAndBehind1_plural": "您的存储库落后远程仓库 __count__ 次提交",
+ "commitsAheadAndBehind2": "领先远程仓库 __count__ 次提交。",
+ "commitsAheadAndBehind2_plural": "领先远程仓库 __count__ 次提交。",
"commitsAheadAndBehind3": "您必须先拉取远程提交,然后才能进行推送。",
"commitsAheadAndBehind3_plural": "您必须先拉取远程提交,然后才能进行推送。",
"refreshCommitHistory": "刷新提交历史",
@@ -757,7 +814,8 @@
"bin": "二进制流",
"date": "时间戳",
"jsonata": "表达式",
- "env": "环境变量"
+ "env": "环境变量",
+ "cred": "证书"
}
},
"editableList": {
@@ -977,7 +1035,8 @@
"passphrase": "密码短语",
"retry": "重试",
"update-failed": "无法更新身份验证",
- "unhandled": "未处理的错误响应"
+ "unhandled": "未处理的错误响应",
+ "host-key-verify-failed": "主机密钥验证失败。
无法验证存储库主机密钥。请更新您的known_hosts
文件,然后重试。
"
},
"create-branch-list": {
"invalid": "无效的分支",
diff --git a/packages/node_modules/@node-red/editor-client/locales/zh-CN/jsonata.json b/packages/node_modules/@node-red/editor-client/locales/zh-CN/jsonata.json
index f27ec1f51..a9e6a7b1f 100644
--- a/packages/node_modules/@node-red/editor-client/locales/zh-CN/jsonata.json
+++ b/packages/node_modules/@node-red/editor-client/locales/zh-CN/jsonata.json
@@ -1,15 +1,15 @@
{
"$string": {
"args": "arg",
- "desc": "通过以下的类型转换规则将参数*arg*转换成字符串:\n\n - 字符串不转换。\n -函数转换成空的字符串。\n - JSON的值无法用数字表示所以用无限大或者NaN(非数)表示。\n - 用’JSON.stringify’函数将其他值转换成JSON字符串。"
+ "desc": "通过以下的类型转换规则将参数 *arg* 转换成字符串:\n\n - 字符串不转换。\n -函数转换成空的字符串。\n - JSON的值无法用数字表示所以用无限大或者NaN(非数)表示。\n - 用 `JSON.stringify` 函数将其他值转换成JSON字符串。"
},
"$length": {
"args": "str",
- "desc": "输出字符串’str’的字数。如果’str’不是字符串,抛出错误。"
+ "desc": "输出字符串 `str` 的字数。如果 `str` 不是字符串,抛出错误。"
},
"$substring": {
"args": "str, start[, length]",
- "desc": "输出`start`位置后的的首次出现的包括`str`的子字符串。 如果`length`被指定,那么的字符串中将只包括前`length`个文字。如果`start`是负数则输出从`str`末尾开始的`length`个文字"
+ "desc": "输出 `start` 位置后的的首次出现的包括 `str` 的子字符串。 如果 `length` 被指定,那么的字符串中将只包括前 `length` 个文字。如果 `start` 是负数则输出从 `str` 末尾开始的 `length` 个文字"
},
"$substringBefore": {
"args": "str, chars",
@@ -17,11 +17,11 @@
},
"$substringAfter": {
"args": "str, chars",
- "desc": "输出’str’中首次出现的’chars’之后的子字符串,如果’str’中不包括’chars’则输出’str’。"
+ "desc": "输出 `str` 中首次出现的 `chars` 之后的子字符串,如果 `str` 中不包括 `chars` 则输出 `str` 。"
},
"$uppercase": {
"args": "str",
- "desc": "`将’str’中的所有字母变为大写后输出。"
+ "desc": "将 `str` 中的所有字母变为大写后输出。"
},
"$lowercase": {
"args": "str",
@@ -29,27 +29,27 @@
},
"$trim": {
"args": "str",
- "desc": "将以下步骤应用于`str`来去除所有空白文字并实现标准化。\n\n – 将全部tab制表符、回车键、换行字符用空白代替。\n- 将连续的空白文字变成一个空白文字。\n- 消除开头和末尾的空白文字。\n\n如果`str`没有被指定(即在无输入参数的情况下调用本函数),将上下文的值作为`str`来使用。 如果`str` 不是字符串则抛出错误。"
+ "desc": "将以下步骤应用于 `str` 来去除所有空白文字并实现标准化。\n\n – 将全部tab制表符、回车键、换行字符用空白代替。\n- 将连续的空白文字变成一个空白文字。\n- 消除开头和末尾的空白文字。\n\n如果 `str` 没有被指定(即在无输入参数的情况下调用本函数),将上下文的值作为 `str` 来使用。 如果 `str` 不是字符串则抛出错误。"
},
"$contains": {
"args": "str, pattern",
- "desc": "字符串`str` 和 `pattern`匹配的话输出`true`,不匹配的情况下输出 `false`。 不指定`str`的情况下(比如用一个参数调用本函数时)、将上下文的值作为`str`来使用。参数 `pattern`可以为字符串或正则表达。"
+ "desc": "字符串 `str` 和 `pattern` 匹配的话输出 `true` ,不匹配的情况下输出 `false` 。 不指定 `str` 的情况下(比如用一个参数调用本函数时)、将上下文的值作为 `str` 来使用。参数 `pattern` 可以为字符串或正则表达。"
},
"$split": {
"args": "str[, separator][, limit]",
- "desc": "将参数`str`分解成由子字符串组成的数组。 如果`str`不是字符串抛出错误。可以省略的参数 `separator`中指定字符串`str`的分隔符。分隔符可以是文字或正则表达式。在不指定`separator`的情况下、将分隔符看作空的字符串并把`str`拆分成由单个字母组成的数组。如果`separator`不是字符串则抛出错误。在可省略的参数`limit`中指定分割后的子字符串的最大个数。超出个数的子字符串将被舍弃。如果`limit`没有被指定,`str` 将不考虑子字符串的个数而将字符串完全分隔。如果`limit`是负数则抛出错误。"
+ "desc": "将参数 `str` 分解成由子字符串组成的数组。 如果 `str` 不是字符串抛出错误。可以省略的参数 `separator` 中指定字符串 `str` 的分隔符。分隔符可以是文字或正则表达式。在不指定 `separator` 的情况下、将分隔符看作空的字符串并把 `str` 拆分成由单个字母组成的数组。如果 `separator` 不是字符串则抛出错误。在可省略的参数 `limit` 中指定分割后的子字符串的最大个数。超出个数的子字符串将被舍弃。如果 `limit` 没有被指定,`str` 将不考虑子字符串的个数而将字符串完全分隔。如果 `limit` 是负数则抛出错误。"
},
"$join": {
"args": "array[, separator]",
- "desc": "用可以省略的参数 `separator`来把多个字符串连接。如果`array`不是字符串则抛出错误。 如果没有指定`separator`,则用空字符串来连接字符(即字符串之间没有`separator`)。 如果`separator`不是字符则抛出错误。"
+ "desc": "用可以省略的参数 `separator` 来把多个字符串连接。如果 `array` 不是字符串则抛出错误。 如果没有指定 `separator` ,则用空字符串来连接字符(即字符串之间没有 `separator` )。 如果 `separator` 不是字符则抛出错误。"
},
"$match": {
"args": "str, pattern [, limit]",
- "desc": "对字符串`str`使用正则表达式`pattern`并输出与`str`相匹配的部分信息。"
+ "desc": "对字符串 `str` 使用正则表达式 `pattern` 并输出与 `str` 相匹配的部分信息。"
},
"$replace": {
"args": "str, pattern, replacement [, limit]",
- "desc": "在字符串`str`中搜索`pattern`并用`replacement`来替换。\n\n可选参数`limit`用来指定替换次数的上限。"
+ "desc": "在字符串 `str` 中搜索 `pattern` 并用 `replacement` 来替换。\n\n可选参数 `limit` 用来指定替换次数的上限。"
},
"$now": {
"args": "",
@@ -65,31 +65,31 @@
},
"$number": {
"args": "arg",
- "desc": "用下述的规则将参数 `arg`转换为数值。:\n\n – 数值不做转换。\n – 将字符串中合法的JSON数値表示转换成数値。\n – 其他形式的值则抛出错误。"
+ "desc": "用下述的规则将参数 `arg` 转换为数值。:\n\n – 数值不做转换。\n – 将字符串中合法的JSON数値表示转换成数値。\n – 其他形式的值则抛出错误。"
},
"$abs": {
"args": "number",
- "desc": "输出参数`number`的绝对值。"
+ "desc": "输出参数 `number` 的绝对值。"
},
"$floor": {
"args": "number",
- "desc": "输出比`number`的值小的最大整数。"
+ "desc": "输出比 `number` 的值小的最大整数。"
},
"$ceil": {
"args": "number",
- "desc": "输出比`number`的值大的最小整数。"
+ "desc": "输出比 `number` 的值大的最小整数。"
},
"$round": {
"args": "number [, precision]",
- "desc": "输出四舍五入后的参数`number`。可省略的参数 `precision`指定四舍五入后小数点下的位数。"
+ "desc": "输出四舍五入后的参数 `number` 。可省略的参数 `precision` 指定四舍五入后小数点下的位数。"
},
"$power": {
"args": "base, exponent",
- "desc": "输出底数`base`的`exponent`次幂。"
+ "desc": "输出底数 `base` 的 `exponent` 次幂。"
},
"$sqrt": {
"args": "number",
- "desc": "输出参数 `number`的平方根。"
+ "desc": "输出参数 `number` 的平方根。"
},
"$random": {
"args": "",
@@ -97,35 +97,35 @@
},
"$millis": {
"args": "",
- "desc": "返回从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。在同一个表达式的测试中所有对`$millis()`的调用将会返回相同的值。"
+ "desc": "返回从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。在同一个表达式的测试中所有对 `$millis()` 的调用将会返回相同的值。"
},
"$sum": {
"args": "array",
- "desc": "输出数组`array`的总和。如果`array`不是数值则抛出错误。"
+ "desc": "输出数组 `array` 的总和。如果 `array` 不是数值则抛出错误。"
},
"$max": {
"args": "array",
- "desc": "输出数组`array`的最大值。如果`array`不是数值则抛出错误。"
+ "desc": "输出数组 `array` 的最大值。如果 `array` 不是数值则抛出错误。"
},
"$min": {
"args": "array",
- "desc": "输出数组`array`的最小值。如果`array`不是数值则抛出错误。。"
+ "desc": "输出数组 `array` 的最小值。如果 `array` 不是数值则抛出错误。。"
},
"$average": {
"args": "array",
- "desc": "输出数组`array`的平均数。如果`array`不是数值则抛出错误。。"
+ "desc": "输出数组 `array` 的平均数。如果 `array` 不是数值则抛出错误。。"
},
"$boolean": {
"args": "arg",
- "desc": "用下述规则将数据转换成布尔值。:\n\n - 不转换布尔值`Boolean`。\n – 将空的字符串`string`转换为`false`\n – 将不为空的字符串`string`转换为`true`\n – 将为0的数字`number`转换成`false`\n –将不为0的数字`number`转换成`true`\n –将`null`转换成`false`\n –将空的数组`array`转换成`false`\n –如果数组`array`中含有可以转换成`true`的要素则转换成`true`\n –如果`array`中没有可转换成`true`的要素则转换成`false`\n – 空的对象`object`转换成`false`\n – 非空的对象`object`转换成`true`\n –将函数`function`转换成`false`"
+ "desc": "用下述规则将数据转换成布尔值。:\n\n - 不转换布尔值 `Boolean` 。\n – 将空的字符串 `string` 转换为 `false` \n – 将不为空的字符串 `string` 转换为 `true` \n – 将为0的数字 `number` 转换成 `false` \n –将不为0的数字 `number` 转换成 `true` \n –将 `null` 转换成 `false` \n –将空的数组 `array` 转换成 `false` \n –如果数组 `array` 中含有可以转换成 `true` 的要素则转换成 `true` \n –如果 `array` 中没有可转换成 `true` 的要素则转换成 `false` \n – 空的对象 `object` 转换成 `false` \n – 非空的对象 `object` 转换成 `true` \n –将函数 `function` 转换成 `false` "
},
"$not": {
"args": "arg",
- "desc": "输出做取反运算后的布尔值。首先将`arg`转换为布尔值。"
+ "desc": "输出做取反运算后的布尔值。首先将 `arg` 转换为布尔值。"
},
"$exists": {
"args": "arg",
- "desc": "如果算式`arg`的值存在则输出`true`。如果算式的值不存在(比如指向不存在区域的引用)则输出`false`。"
+ "desc": "如果算式 `arg` 的值存在则输出 `true` 。如果算式的值不存在(比如指向不存在区域的引用)则输出 `false` 。"
},
"$count": {
"args": "array",
@@ -137,15 +137,15 @@
},
"$sort": {
"args": "array [, function]",
- "desc": "输出排序后的数组`array`。\n\n如果使用了比较函数`function`,则下述两个参数需要被指定。\n\n`function(left, right)`\n\n该比较函数是为了比较left和right两个值而被排序算法调用的。如果用户希望left的值被置于right的值之后,那么该函数必须输出布尔值`true`来表示位置交换。而在不需要位置交换时函数必须输出`false`。"
+ "desc": "输出排序后的数组 `array` 。\n\n如果使用了比较函数 `function` ,则下述两个参数需要被指定。\n\n `function(left, right)` \n\n该比较函数是为了比较left和right两个值而被排序算法调用的。如果用户希望left的值被置于right的值之后,那么该函数必须输出布尔值 `true` 来表示位置交换。而在不需要位置交换时函数必须输出 `false` 。"
},
"$reverse": {
"args": "array",
- "desc": "输出倒序后的数组`array`。"
+ "desc": "输出倒序后的数组 `array` 。"
},
"$shuffle": {
"args": "array",
- "desc": "输出随机排序后的数组 `array`。"
+ "desc": "输出随机排序后的数组 `array` 。"
},
"$zip": {
"args": "array, ...",
@@ -157,35 +157,35 @@
},
"$lookup": {
"args": "object, key",
- "desc": "输出对象中与参数`key`对应的值。如果第一个参数`object`是数组,那么数组中所有的对象都将被搜索并输出这些对象中与参数`key`对应的值。"
+ "desc": "输出对象中与参数 `key` 对应的值。如果第一个参数 `object` 是数组,那么数组中所有的对象都将被搜索并输出这些对象中与参数 `key` 对应的值。"
},
"$spread": {
"args": "object",
- "desc": "将对象中的键值对分隔成每个要素中只含有一个键值对的数组。如果参数`object`是数组,那么返回值的数组中包含所有对象中的键值对。"
+ "desc": "将对象中的键值对分隔成每个要素中只含有一个键值对的数组。如果参数 `object` 是数组,那么返回值的数组中包含所有对象中的键值对。"
},
"$merge": {
"args": "array<object>",
- "desc": "将输入数组`objects`中所有的键值对合并到一个`object`中并返回。如果输入数组的要素中含有重复的键,则返回的`object`中将只包含数组中最后出现要素的值。如果输入数组中包括对象以外的元素,则抛出错误。"
+ "desc": "将输入数组 `objects` 中所有的键值对合并到一个 `object` 中并返回。如果输入数组的要素中含有重复的键,则返回的 `object` 中将只包含数组中最后出现要素的值。如果输入数组中包括对象以外的元素,则抛出错误。"
},
"$sift": {
"args": "object, function",
- "desc": "输出参数`object`中符合`function`的键值对。\n\n`function`必须含有下述参数。\n\n`function(value [, key [, object]])`"
+ "desc": "输出参数 `object` 中符合 `function` 的键值对。\n\n `function` 必须含有下述参数。\n\n `function(value [, key [, object]])` "
},
"$each": {
"args": "object, function",
- "desc": "将函数`function`应用于`object`中的所有键值对并输出由所有返回值组成的数组。"
+ "desc": "将函数 `function` 应用于 `object` 中的所有键值对并输出由所有返回值组成的数组。"
},
"$map": {
"args": "array, function",
- "desc": "将函数`function`应用于数组`array`中所有的值并输出由返回值组成的数组。\n\n`function`中必须含有下述参数。\n\n`function(value [, index [, array]])`"
+ "desc": "将函数 `function` 应用于数组 `array` 中所有的值并输出由返回值组成的数组。\n\n `function` 中必须含有下述参数。\n\n`function(value [, index [, array]])` "
},
"$filter": {
"args": "array, function",
- "desc": "输出数组`array`中符合函数`function`条件的值组成的数组。\n\n`function`必须包括下述参数。\n\n`function(value [, index [, array]])`"
+ "desc": "输出数组 `array` 中符合函数 `function` 条件的值组成的数组。\n\n `function` 必须包括下述参数。\n\n `function(value [, index [, array]])`"
},
"$reduce": {
"args": "array, function [, init]",
- "desc": "将`function`依次应用于数组中的各要素值。 其中,前一个要素值的计算结果将参与到下一次的函数运算中。。\n\n函数`function`接受两个参数并作为中缀表示法中的操作符。\n\n可省略的参数`init`将作为运算的初始值。"
+ "desc": "将 `function` 依次应用于数组中的各要素值。 其中,前一个要素值的计算结果将参与到下一次的函数运算中。。\n\n函数 `function` 接受两个参数并作为中缀表示法中的操作符。\n\n可省略的参数 `init` 将作为运算的初始值。"
},
"$flowContext": {
"args": "string",
@@ -197,7 +197,7 @@
},
"$pad": {
"args": "string, width [, char]",
- "desc": "根据需要,向字符串`string`的副本中填充文字使该字符串的字数达到`width`的绝对值并返回填充文字后的字符串。\n\n如果`width`的值为正,则向字符串`string`的右侧填充文字,如果`width`为负,则向字符串`string`的左侧填充文字。\n\n可选参数`char`用来指定填充的文字。如果未指定该参数,则填充空白文字。"
+ "desc": "根据需要,向字符串 `string` 的副本中填充文字使该字符串的字数达到 `width` 的绝对值并返回填充文字后的字符串。\n\n如果 `width` 的值为正,则向字符串 `string` 的右侧填充文字,如果 `width` 为负,则向字符串 `string` 的左侧填充文字。\n\n可选参数 `char` 用来指定填充的文字。如果未指定该参数,则填充空白文字。"
},
"$fromMillis": {
"args": "number",
@@ -205,15 +205,15 @@
},
"$formatNumber": {
"args": "number, picture [, options]",
- "desc": "将`number`转换成具有`picture`所指定的数值格式的字符串。\n\n此函数的功能与XPath F&O 3.1规格中定义的XPath/XQuery函数的fn:format-number功能相一致。参数`picture`用于指定数值的转换格式,其语法与fn:format-number中的定义一致。\n\n可选的第三参数`options`用来覆盖默认的局部环境格式,如小数点分隔符。如果指定该参数,那么该参数必须是包含name/value对的对象,并且name/value对必须符合XPath F&O 3.1规格中记述的数值格式。"
+ "desc": "将 `number` 转换成具有 `picture` 所指定的数值格式的字符串。\n\n此函数的功能与XPath F&O 3.1规格中定义的XPath/XQuery函数的fn:format-number功能相一致。参数 `picture` 用于指定数值的转换格式,其语法与fn:format-number中的定义一致。\n\n可选的第三参数 `options` 用来覆盖默认的局部环境格式,如小数点分隔符。如果指定该参数,那么该参数必须是包含name/value对的对象,并且name/value对必须符合XPath F&O 3.1规格中记述的数值格式。"
},
"$formatBase": {
"args": "number [, radix]",
- "desc": "将`number`变换为以参数`radix`的值为基数形式的字符串。如果不指定`radix`的值,则默认基数为10。指定的`radix`值必须在2~36之间,否则抛出错误。"
+ "desc": "将 `number` 变换为以参数 `radix` 的值为基数形式的字符串。如果不指定 `radix` 的值,则默认基数为10。指定的 `radix` 值必须在2~36之间,否则抛出错误。"
},
"$toMillis": {
"args": "timestamp",
- "desc": "将ISO 8601格式的字符串`timestamp`转换为从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。如果该字符串的格式不正确,则抛出错误。"
+ "desc": "将ISO 8601格式的字符串 `timestamp` 转换为从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。如果该字符串的格式不正确,则抛出错误。"
},
"$env": {
"args": "arg",
@@ -221,7 +221,7 @@
},
"$eval": {
"args": "expr [, context]",
- "desc": "使用当前上下文来作为评估依据,分析并评估字符串`expr`,其中包含文字JSON或JSONata表达式。"
+ "desc": "使用当前上下文来作为评估依据,分析并评估字符串 `expr` ,其中包含文字JSON或JSONata表达式。"
},
"$formatInteger": {
"args": "number, picture",
@@ -233,19 +233,19 @@
},
"$error": {
"args": "[str]",
- "desc": "引发错误并显示一条消息。 可选的`str`将替代$error()函数评估的默认消息。"
+ "desc": "引发错误并显示一条消息。 可选的 `str` 将替代$error()函数评估的默认消息。"
},
"$assert": {
"args": "arg, str",
- "desc": "如果`arg`为真,则该函数返回。 如果arg为假,则抛出带有str的异常作为异常消息。"
+ "desc": "如果 `arg` 为真,则该函数返回。 如果arg为假,则抛出带有str的异常作为异常消息。"
},
"$single": {
"args": "array, function",
- "desc": "返回满足参数function谓语的array参数中的唯一值 (比如:传递值时,函数返回布尔值“true”)。如果匹配值的数量不唯一时,则抛出异常。\n\n应在以下签名中提供函数:`function(value [,index [,array []]])`其中value是数组的每个输入,index是该值的位置,整个数组作为第三个参数传递。"
+ "desc": "返回满足参数function谓语的array参数中的唯一值 (比如:传递值时,函数返回布尔值“true”)。如果匹配值的数量不唯一时,则抛出异常。\n\n应在以下签名中提供函数: `function(value [,index [,array []]])` 其中value是数组的每个输入,index是该值的位置,整个数组作为第三个参数传递。"
},
"$encodeUrl": {
"args": "str",
- "desc": "通过用表示字符的UTF-8编码的一个,两个,三个或四个转义序列替换某些字符的每个实例,对统一资源定位符(URL)组件进行编码。\n\n示例:`$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
+ "desc": "通过用表示字符的UTF-8编码的一个,两个,三个或四个转义序列替换某些字符的每个实例,对统一资源定位符(URL)组件进行编码。\n\n示例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
},
"$encodeUrlComponent": {
"args": "str",
@@ -261,10 +261,14 @@
},
"$distinct": {
"args": "array",
- "desc": "返回一个数组,其中重复的值已从`数组`中删除"
+ "desc": "返回一个数组,其中重复的值已从 `数组` 中删除"
},
"$type": {
"args": "value",
- "desc": "以字符串形式返回`值`的类型。 如果该`值`未定义,则将返回`未定义`"
+ "desc": "以字符串形式返回 `值` 的类型。 如果该 `值` 未定义,则将返回 `未定义` "
+ },
+ "$moment": {
+ "args": "[str]",
+ "desc": "使用Moment库获取日期对象。"
}
}
diff --git a/packages/node_modules/@node-red/editor-client/locales/zh-TW/editor.json b/packages/node_modules/@node-red/editor-client/locales/zh-TW/editor.json
index 897599bc7..644d28b12 100644
--- a/packages/node_modules/@node-red/editor-client/locales/zh-TW/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/zh-TW/editor.json
@@ -14,7 +14,15 @@
"back": "返回",
"next": "下一步",
"clone": "複製專案",
- "cont": "Continue"
+ "cont": "繼續",
+ "style": "風格",
+ "line": "大綱",
+ "fill": "填充",
+ "label": "標籤",
+ "color": "顏色",
+ "position": "位置",
+ "enable": "啟用",
+ "disable": "禁用"
},
"type": {
"string": "字符串",
@@ -28,6 +36,13 @@
"null": "空"
}
},
+ "event": {
+ "loadPalette": "加載控制板",
+ "loadNodeCatalogs": "加載節點目錄",
+ "loadNodes": "加載 __count__ 個節點",
+ "loadFlows": "加載流程",
+ "importFlows": "往工作區中加載流程"
+ },
"workspace": {
"defaultName": "流程__number__",
"editFlow": "編輯流程: __name__",
@@ -91,7 +106,12 @@
"projects-new": "新專案",
"projects-open": "開啟專案",
"projects-settings": "專案設定",
- "showNodeLabelDefault": "顯示新添加節點的標籤"
+ "showNodeLabelDefault": "顯示新添加節點的標籤",
+ "groups": "組",
+ "groupSelection": "選擇組",
+ "ungroupSelection": "取消選擇組",
+ "groupMergeSelection": "合并選擇",
+ "groupRemoveSelection": "從組中移除"
}
},
"actions": {
@@ -101,7 +121,7 @@
"zoom-in": "放大"
},
"user": {
- "loggedInAs": "作為__name__登入",
+ "loggedInAs": "作為 __name__ 登入",
"username": "帳號",
"password": "密碼",
"login": "登入",
@@ -133,7 +153,7 @@
"error": "Error: __message__",
"errors": {
"lostConnection": "丟失與伺服器的連接,重新連接...",
- "lostConnectionReconnect": "丟失與伺服器的連接,__time__秒後重新連接",
+ "lostConnectionReconnect": "丟失與伺服器的連接,__time__ 秒後重新連接",
"lostConnectionTry": "現在嘗試",
"cannotAddSubflowToItself": "無法向其自身添加子流程",
"cannotAddCircularReference": "無法添加子流程 - 迴圈引用",
@@ -146,7 +166,7 @@
"loaded": "已加載項目'__project__'",
"updated": "已更新項目'__project__'",
"pull": "已重新加載項目'__project__'",
- "revert": "項目“__project__”已還原",
+ "revert": "項目'__project__'已還原",
"merge-complete": "Git合併完成",
"setupCredentials": "設定證書",
"setupProjectFiles": "設置項目文件",
@@ -171,6 +191,8 @@
"node_plural": "__count__ 多個節點",
"configNode": "__count__ 節點組態",
"configNode_plural": "__count__ 多節點組態",
+ "group": "__count__ 個組",
+ "group_plural": "__count__ 個組",
"flow": "__count__ 流程",
"flow_plural": "__count__ 多流程",
"subflow": "__count__ 子流程",
@@ -184,8 +206,11 @@
"importUnrecognised_plural": "匯入了無法識別的類型:",
"nodesExported": "節點匯出到了剪貼簿",
"nodesImported": "已匯入:",
- "nodeCopied": "已複製__count__個節點",
- "nodeCopied_plural": "已複製__count__個節點",
+ "nodeCopied": "已複製 __count__ 個節點",
+ "nodeCopied_plural": "已複製 __count__ 個節點",
+ "groupCopied": "複製 __count__ 個組",
+ "groupCopied_plural": "已複製 __count__ 個groups",
+ "groupStyleCopied": "已複製組風格",
"invalidFlow": "無效的流程: __message__",
"export": {
"selected": "已選擇的節點",
@@ -204,9 +229,9 @@
"newFlow": "新流程",
"errors": {
"notArray": "輸入的不是JSON數組",
- "itemNotObject": "輸入的流程無效-項目__index__不是節點對象",
- "missingId": "輸入的流程無效-項__index__缺少“ id”屬性",
- "missingType": "輸入的流程無效-項__index__缺少“類型”屬性"
+ "itemNotObject": "輸入的流程無效-項目 __index__ 不是節點對象",
+ "missingId": "輸入的流程無效-項 __index__ 缺少“ id”屬性",
+ "missingType": "輸入的流程無效-項 __index__ 缺少“類型”屬性"
}
},
"copyMessagePath": "已複製路徑",
@@ -250,7 +275,7 @@
"conflictChecking": "檢查是否可以自動合併更改",
"conflictAutoMerge": "此更改不包括衝突,可以自動合併",
"conflictManualMerge": "這些更改包括了在部署之前必須解決的衝突。",
- "plusNMore": "+更多的__count__"
+ "plusNMore": "+更多的 __count__"
}
},
"eventLog": {
@@ -258,8 +283,8 @@
"view": "查看日誌"
},
"diff": {
- "unresolvedCount": "__count__個未解決的衝突",
- "unresolvedCount_plural": "__count__個未解決的衝突",
+ "unresolvedCount": "__count__ 個未解決的衝突",
+ "unresolvedCount_plural": "__count__ 個未解決的衝突",
"globalNodes": "全局節點",
"flowProperties": "流程屬性",
"type": {
@@ -269,11 +294,11 @@
"deleted": "已刪除",
"flowDeleted": "已刪除流程",
"flowAdded": "已添加流程",
- "movedTo": "移動至__id__",
- "movedFrom": "從__id__移動"
+ "movedTo": "移動至 __id__",
+ "movedFrom": "從 __id__ 移動"
},
- "nodeCount": "__count__個節點",
- "nodeCount_plural": "__count__個節點",
+ "nodeCount": "__count__ 個節點",
+ "nodeCount_plural": "__count__ 個節點",
"local": "本地",
"remote": "遠端",
"reviewChanges": "查看變更",
@@ -287,11 +312,11 @@
"newVersionError": "新版本不包含有效的JSON:"
},
"subflow": {
- "editSubflowInstance": "編輯子流程實例:__name__",
- "editSubflow": "編輯流程範本: __name__",
+ "editSubflowInstance": "編輯子流程實例: __name__",
+ "editSubflow": "編輯流程範本: __name__",
"edit": "編輯流程範本",
- "subflowInstances": "這個子流程範本有__count__個實例",
- "subflowInstances_plural": "這個子流程範本有__count__個實例",
+ "subflowInstances": "這個子流程範本有 __count__ 個實例",
+ "subflowInstances_plural": "這個子流程範本有 __count__ 個實例",
"editSubflowProperties": "編輯屬性",
"input": "輸入:",
"output": "輸出:",
@@ -308,17 +333,24 @@
"multipleInputsToSelection": "無法創建子流程: 多個輸入到了選擇"
}
},
+ "group": {
+ "editGroup": "編輯組: __name__",
+ "errors": {
+ "cannotCreateDiffGroups": "無法使用來自不同組的節點創建組",
+ "cannotAddSubflowPorts": "無法將子流程的端口添加到組"
+ }
+ },
"editor": {
"configEdit": "編輯",
"configAdd": "添加",
"configUpdate": "更新",
"configDelete": "刪除",
- "nodesUse": "__count__個節點使用此配置",
- "nodesUse_plural": "__count__個節點使用此配置",
- "addNewConfig": "添加新的__type__配置",
- "editNode": "編輯__type__節點",
- "editConfig": "編輯__type__配置",
- "addNewType": "添加新的__type__節點",
+ "nodesUse": "__count__ 個節點使用此配置",
+ "nodesUse_plural": "__count__ 個節點使用此配置",
+ "addNewConfig": "添加新的 __type__ 配置",
+ "editNode": "編輯 __type__ 節點",
+ "editConfig": "編輯 __type__ 配置",
+ "addNewType": "添加新的 __type__ 節點",
"nodeProperties": "節點屬性",
"label": "Label",
"color": "顏色",
@@ -337,6 +369,7 @@
"locale": "選擇界面語言",
"icon": "圖標",
"inputType": "輸入類型",
+ "selectType": "選擇類型...",
"inputs": {
"input": "輸入",
"select": "選擇",
@@ -351,7 +384,8 @@
"bool": "布爾",
"json": "JSON",
"bin": "buffer",
- "env": "環境變量"
+ "env": "環境變量",
+ "cred": "證書"
},
"menu": {
"input": "輸入",
@@ -405,13 +439,13 @@
"library": "庫",
"openLibrary": "打開庫...",
"saveToLibrary": "保存到庫...",
- "typeLibrary": "__type__型別程式庫",
- "unnamedType": "無名__type__",
+ "typeLibrary": "__type__ 型別程式庫",
+ "unnamedType": "無名 __type__",
"exportedToLibrary": "節點導出到庫",
- "dialogSaveOverwrite": "一個叫做__libraryName__的__libraryType__已經存在,您需要覆蓋麼?",
+ "dialogSaveOverwrite": "一個叫做 __libraryName__ 的 __libraryType__ 已經存在,您需要覆蓋麼?",
"invalidFilename": "無效的檔案名",
"savedNodes": "保存的節點",
- "savedType": "已保存__type__",
+ "savedType": "已保存 __type__",
"saveFailed": "保存失敗: __message__",
"newFolder": "新文件夾",
"types": {
@@ -460,33 +494,33 @@
"times": {
"seconds": "秒前",
"minutes": "分前",
- "minutesV": "__count__分前",
- "hoursV": "__count__小時前",
- "hoursV_plural": "__count__小時前",
- "daysV": "__count__天前",
- "daysV_plural": "__count__天前",
- "weeksV": "__count__周前",
- "weeksV_plural": "__count__周前",
- "monthsV": "__count__月前",
- "monthsV_plural": "__count__月前",
- "yearsV": "__count__年前",
- "yearsV_plural": "__count__年前",
- "yearMonthsV": "__y__年, __count__月前",
- "yearMonthsV_plural": "__y__年, __count__月前",
- "yearsMonthsV": "__y__年, __count__月前",
- "yearsMonthsV_plural": "__y__年, __count__月前"
+ "minutesV": "__count__ 分前",
+ "hoursV": "__count__ 小時前",
+ "hoursV_plural": "__count__ 小時前",
+ "daysV": "__count__ 天前",
+ "daysV_plural": "__count__ 天前",
+ "weeksV": "__count__ 周前",
+ "weeksV_plural": "__count__ 周前",
+ "monthsV": "__count__ 月前",
+ "monthsV_plural": "__count__ 月前",
+ "yearsV": "__count__ 年前",
+ "yearsV_plural": "__count__ 年前",
+ "yearMonthsV": "__y__ 年, __count__ 月前",
+ "yearMonthsV_plural": "__y__ 年, __count__ 月前",
+ "yearsMonthsV": "__y__ 年, __count__ 月前",
+ "yearsMonthsV_plural": "__y__ 年, __count__ 月前"
},
- "nodeCount": "__label__個節點",
- "nodeCount_plural": "__label__個節點",
- "moduleCount": "__count__個可用模組",
- "moduleCount_plural": "__count__個可用模組",
+ "nodeCount": "__label__ 個節點",
+ "nodeCount_plural": "__label__ 個節點",
+ "moduleCount": "__count__ 個可用模組",
+ "moduleCount_plural": "__count__ 個可用模組",
"inuse": "使用中",
"enableall": "全部啟用",
"disableall": "全部禁用",
"enable": "啟用",
"disable": "禁用",
"remove": "移除",
- "update": "更新至__version__版本",
+ "update": "更新至 __version__ 版本",
"updated": "已更新",
"install": "安裝",
"installed": "已安裝",
@@ -498,7 +532,7 @@
"sort": "排序:",
"sortAZ": "a-z順序",
"sortRecent": "日期順序",
- "more": "增加__count__個",
+ "more": "增加 __count__ 個",
"errors": {
"catalogLoadFailed": "無法載入節點目錄。
查看瀏覽器控制臺瞭解更多資訊",
"installFailed": "無法安裝: __module__
__message__
查看日誌瞭解更多資訊",
@@ -539,6 +573,7 @@
"label": "信息",
"node": "節點",
"type": "類型",
+ "group": "組",
"module": "Module",
"id": "ID",
"status": "狀態",
@@ -560,8 +595,30 @@
"subflowDesc": "子流程描述",
"nodeHelp": "節點幫助",
"none": "無",
- "arrayItems": "__count__個項目",
- "showTips": "您可以從設置面板啟用提示資訊"
+ "arrayItems": "__count__ 個項目",
+ "showTips": "您可以從設置面板啟用提示資訊",
+ "outline": "大綱",
+ "empty": "空的",
+ "globalConfig": "全局配置節點",
+ "triggerAction": "觸發動作",
+ "find": "在工作區中查找",
+ "search": {
+ "configNodes": "配置節點",
+ "unusedConfigNodes": "未使用的配置節點",
+ "invalidNodes": "無效的節點",
+ "uknownNodes": "未知的節點",
+ "unusedSubflows": "未使用的子流程"
+ }
+ },
+ "help": {
+ "name": "幫助",
+ "label": "幫助",
+ "search": "搜索幫助",
+ "nodeHelp": "節點幫助",
+ "showHelp": "顯示幫助",
+ "showInOutline": "在大綱中顯示",
+ "showTopics": "顯示主題",
+ "noHelp": "未選擇幫助主題"
},
"config": {
"name": "配置節點",
@@ -614,9 +671,9 @@
"removeFromProject": "從項目中刪除",
"addToProject": "添加到項目",
"files": "文件",
- "package": "包",
"flow": "流程",
"credentials": "證書",
+ "package": "包",
"packageCreate": "保存更改後將創建文件",
"fileNotExist": "文件不存在",
"selectFile": "選擇文件",
@@ -668,7 +725,7 @@
"copyPublicKey": "將公鑰複製到剪貼板",
"delete": "刪除密鑰",
"gitConfig": "Git配置",
- "deleteConfirm": "您確定要刪除SSH密鑰__name__嗎? 這不能被撤消。"
+ "deleteConfirm": "您確定要刪除SSH密鑰 __name__ 嗎? 這不能被撤消。"
},
"versionControl": {
"unstagedChanges": "未暫存的更改",
@@ -722,24 +779,24 @@
"pullChanges": "Pull變更",
"history": "歷史",
"projectHistory": "項目歷史",
- "daysAgo": "__count__天前",
- "daysAgo_plural": "__count__天前",
- "hoursAgo": "__count__小時前",
- "hoursAgo_plural": "__count__小時前",
- "minsAgo": "__count__分鐘前",
- "minsAgo_plural": "__count__分鐘前",
+ "daysAgo": "__count__ 天前",
+ "daysAgo_plural": "__count__ 天前",
+ "hoursAgo": "__count__ 小時前",
+ "hoursAgo_plural": "__count__ 小時前",
+ "minsAgo": "__count__ 分鐘前",
+ "minsAgo_plural": "__count__ 分鐘前",
"secondsAgo": "秒前",
"notTracking": "您的本地分支當前未跟蹤遠程分支。",
"statusUnmergedChanged": "您的存儲庫中有未合併的更改。您需要解決衝突並提交結果。",
"repositoryUpToDate": "您的存儲庫是最新的。",
- "commitsAhead": "您的倉庫領先遠程倉庫__count__次提交。您現在可以push這些提交。",
- "commitsAhead_plural": "您的倉庫領先遠程倉庫__count__次提交。您現在可以push這些提交。",
- "commitsBehind": "您的倉庫落後遠程倉庫__count__次提交。您現在可以pull這些提交。",
- "commitsBehind_plural": "您的倉庫落後遠程倉庫__count__次提交。您現在可以pull這些提交。",
- "commitsAheadAndBehind1": "您的倉庫落後遠程倉庫__count__次提交",
- "commitsAheadAndBehind1_plural": "您的倉庫落後遠程倉庫__count__次提交",
- "commitsAheadAndBehind2": "領先遠程倉庫__count__次提交。",
- "commitsAheadAndBehind2_plural": "領先遠程倉庫__count__次提交。",
+ "commitsAhead": "您的倉庫領先遠程倉庫 __count__ 次提交。您現在可以push這些提交。",
+ "commitsAhead_plural": "您的倉庫領先遠程倉庫 __count__ 次提交。您現在可以push這些提交。",
+ "commitsBehind": "您的倉庫落後遠程倉庫 __count__ 次提交。您現在可以pull這些提交。",
+ "commitsBehind_plural": "您的倉庫落後遠程倉庫 __count__ 次提交。您現在可以pull這些提交。",
+ "commitsAheadAndBehind1": "您的倉庫落後遠程倉庫 __count__ 次提交",
+ "commitsAheadAndBehind1_plural": "您的倉庫落後遠程倉庫 __count__ 次提交",
+ "commitsAheadAndBehind2": "領先遠程倉庫 __count__ 次提交。",
+ "commitsAheadAndBehind2_plural": "領先遠程倉庫 __count__ 次提交。",
"commitsAheadAndBehind3": "您必須先pull遠程提交,然後再進行push。",
"commitsAheadAndBehind3_plural": "您必須先pull遠程提交,然後再進行push。",
"refreshCommitHistory": "刷新提交歷史",
@@ -757,7 +814,8 @@
"bin": "二進位流",
"date": "時間戳記",
"jsonata": "expression",
- "env": "env variable"
+ "env": "env variable",
+ "cred": "證書"
}
},
"editableList": {
@@ -977,7 +1035,8 @@
"passphrase": "密碼短語",
"retry": "重試",
"update-failed": "無法更新身份驗證",
- "unhandled": "未處理的錯誤響應"
+ "unhandled": "未處理的錯誤響應",
+ "host-key-verify-failed": "主機密鑰驗證失敗。
無法驗證存儲庫主機密鑰。請更新您的known_hosts
文件,然後重試。
"
},
"create-branch-list": {
"invalid": "無效的分支",
diff --git a/packages/node_modules/@node-red/editor-client/locales/zh-TW/jsonata.json b/packages/node_modules/@node-red/editor-client/locales/zh-TW/jsonata.json
index 6d99ffc6a..3765ab3dd 100644
--- a/packages/node_modules/@node-red/editor-client/locales/zh-TW/jsonata.json
+++ b/packages/node_modules/@node-red/editor-client/locales/zh-TW/jsonata.json
@@ -266,5 +266,9 @@
"$type": {
"args": "value",
"desc": "以字符串形式返回`值`的類型。 如果該`值`未定義,則將返回`未定義`"
+ },
+ "$moment": {
+ "args": "[str]",
+ "desc": "使用Moment庫獲取日期對象。"
}
}
diff --git a/packages/node_modules/@node-red/editor-client/package.json b/packages/node_modules/@node-red/editor-client/package.json
index 22fe38f4b..6774df246 100644
--- a/packages/node_modules/@node-red/editor-client/package.json
+++ b/packages/node_modules/@node-red/editor-client/package.json
@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
- "version": "1.0.6",
+ "version": "1.1.0",
"license": "Apache-2.0",
"repository": {
"type": "git",
diff --git a/packages/node_modules/@node-red/editor-client/src/js/events.js b/packages/node_modules/@node-red/editor-client/src/js/events.js
index f79cc864f..bd2abd8d0 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/events.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/events.js
@@ -32,14 +32,19 @@
}
}
}
- function emit(evt,arg) {
+ function emit() {
+ var evt = arguments[0]
+ var args = Array.prototype.slice.call(arguments,1);
+ if (RED.events.DEBUG) {
+ console.warn(evt,args);
+ }
if (handlers[evt]) {
for (var i=0;i n.ports.length) {
- n.ports.push(n.ports.length);
- }
n.resize = true;
n.dirty = true;
});
}
+ if (ev.groups) {
+ inverseEv.groups = [];
+ var groupsToAdd = {};
+ ev.groups.forEach(function(g) { groupsToAdd[g.id] = g; });
+ for (i=0;i n.outputs)) { n.outputs = n.wires.length; }
- if (n.outputs) {
- for (var i=0;i=0; i--) {
+ removeGroup(removedGroups[i]);
+ }
+ RED.events.emit('flows:remove',ws);
}
- for (n=0;ndiv:not(.node-input-env-container-row)");
var height = size.height;
@@ -412,15 +470,20 @@ RED.nodes = (function() {
module: "node-red"
}
});
+ sf.instances = [];
sf._def = RED.nodes.getType("subflow:"+sf.id);
+ RED.events.emit("subflows:add",sf);
}
function getSubflow(id) {
return subflows[id];
}
function removeSubflow(sf) {
- delete subflows[sf.id];
- delete nodeTabMap[sf.id];
- registry.removeNodeType("subflow:"+sf.id);
+ if (subflows[sf.id]) {
+ delete subflows[sf.id];
+ delete nodeTabMap[sf.id];
+ registry.removeNodeType("subflow:"+sf.id);
+ RED.events.emit("subflows:remove",sf);
+ }
}
function subflowContains(sfid,nodeid) {
@@ -493,6 +556,9 @@ RED.nodes = (function() {
if (n.d === true) {
node.d = true;
}
+ if (n.g) {
+ node.g = n.g;
+ }
if (node.type == "unknown") {
for (var p in n._orig) {
if (n._orig.hasOwnProperty(p)) {
@@ -505,19 +571,33 @@ RED.nodes = (function() {
node[d] = n[d];
}
}
- if(exportCreds && n.credentials) {
+ if (exportCreds) {
var credentialSet = {};
- node.credentials = {};
- for (var cred in n._def.credentials) {
- if (n._def.credentials.hasOwnProperty(cred)) {
- if (n._def.credentials[cred].type == 'password') {
+ if (/^subflow:/.test(node.type) && n.credentials) {
+ // A subflow instance node can have arbitrary creds
+ for (var sfCred in n.credentials) {
+ if (n.credentials.hasOwnProperty(sfCred)) {
if (!n.credentials._ ||
- n.credentials["has_"+cred] != n.credentials._["has_"+cred] ||
- (n.credentials["has_"+cred] && n.credentials[cred])) {
+ n.credentials["has_"+sfCred] != n.credentials._["has_"+sfCred] ||
+ (n.credentials["has_"+sfCred] && n.credentials[sfCred])) {
+ credentialSet[sfCred] = n.credentials[sfCred];
+ }
+ }
+ }
+ } else if (n.credentials) {
+ node.credentials = {};
+ // All other nodes have a well-defined list of possible credentials
+ for (var cred in n._def.credentials) {
+ if (n._def.credentials.hasOwnProperty(cred)) {
+ if (n._def.credentials[cred].type == 'password') {
+ if (!n.credentials._ ||
+ n.credentials["has_"+cred] != n.credentials._["has_"+cred] ||
+ (n.credentials["has_"+cred] && n.credentials[cred])) {
+ credentialSet[cred] = n.credentials[cred];
+ }
+ } else if (n.credentials[cred] != null && (!n.credentials._ || n.credentials[cred] != n.credentials._[cred])) {
credentialSet[cred] = n.credentials[cred];
}
- } else if (n.credentials[cred] != null && (!n.credentials._ || n.credentials[cred] != n.credentials._[cred])) {
- credentialSet[cred] = n.credentials[cred];
}
}
}
@@ -526,6 +606,13 @@ RED.nodes = (function() {
}
}
}
+ if (n.type === "group") {
+ node.x = n.x;
+ node.y = n.y;
+ node.w = n.w;
+ node.h = n.h;
+ node.nodes = node.nodes.map(function(n) { return n.id });
+ }
if (n._def.category != "config") {
node.x = n.x;
node.y = n.y;
@@ -568,7 +655,7 @@ RED.nodes = (function() {
return node;
}
- function convertSubflow(n) {
+ function convertSubflow(n, exportCreds) {
var node = {};
node.id = n.id;
node.type = n.type;
@@ -578,6 +665,24 @@ RED.nodes = (function() {
node.in = [];
node.out = [];
node.env = n.env;
+
+ if (exportCreds) {
+ var credentialSet = {};
+ // A subflow node can have arbitrary creds
+ for (var sfCred in n.credentials) {
+ if (n.credentials.hasOwnProperty(sfCred)) {
+ if (!n.credentials._ ||
+ n.credentials["has_"+sfCred] != n.credentials._["has_"+sfCred] ||
+ (n.credentials["has_"+sfCred] && n.credentials[sfCred])) {
+ credentialSet[sfCred] = n.credentials[sfCred];
+ }
+ }
+ }
+ if (Object.keys(credentialSet).length > 0) {
+ node.credentials = credentialSet;
+ }
+ }
+
node.color = n.color;
n.in.forEach(function(p) {
@@ -633,8 +738,18 @@ RED.nodes = (function() {
/**
* Converts the current node selection to an exportable JSON Object
**/
- function createExportableNodeSet(set, exportedSubflows, exportedConfigNodes) {
+ function createExportableNodeSet(set, exportedIds, exportedSubflows, exportedConfigNodes) {
var nns = [];
+
+ exportedIds = exportedIds || {};
+ set = set.filter(function(n) {
+ if (exportedIds[n.id]) {
+ return false;
+ }
+ exportedIds[n.id] = true;
+ return true;
+ })
+
exportedConfigNodes = exportedConfigNodes || {};
exportedSubflows = exportedSubflows || {};
for (var n=0;n 1) {
+ throw new Error("Node-RED's IE11 Array.from polyfill doesn't support multiple arguments");
+ }
+ var arrayLike = arguments[0]
+ var result = [];
+ if (arrayLike.forEach) {
+ arrayLike.forEach(function(i) {
+ result.push(i);
+ })
+ } else {
+ for (var i=0;i)/);
+ 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) {
$("#red-ui-editor").i18n();
$("#red-ui-palette > .red-ui-palette-spinner").hide();
$(".red-ui-palette-scroll").removeClass("hide");
$("#red-ui-palette-search").removeClass("hide");
- loadFlows(function() {
- if (RED.settings.theme("projects.enabled",false)) {
- RED.projects.refresh(function(activeProject) {
+ if (RED.settings.theme("projects.enabled",false)) {
+ RED.projects.refresh(function(activeProject) {
+ loadFlows(function() {
RED.sidebar.info.refresh()
if (!activeProject) {
// Projects enabled but no active project
@@ -140,12 +147,14 @@ var RED = (function() {
}
completeLoad();
});
- } else {
+ });
+ } else {
+ loadFlows(function() {
// Projects disabled by the user
RED.sidebar.info.refresh()
completeLoad();
- }
- });
+ });
+ }
} else {
var config = configs.shift();
appendNodeConfig(config,stepConfig);
@@ -157,6 +166,7 @@ var RED = (function() {
}
function loadFlows(done) {
+ loader.reportProgress(RED._("event.loadFlows"),80 )
$.ajax({
headers: {
"Accept":"application/json",
@@ -167,6 +177,7 @@ var RED = (function() {
if (nodes) {
var currentHash = window.location.hash;
RED.nodes.version(nodes.rev);
+ loader.reportProgress(RED._("event.importFlows"),90 )
RED.nodes.import(nodes.flows);
RED.nodes.dirty(false);
RED.view.redraw(true);
@@ -193,6 +204,7 @@ var RED = (function() {
return;
}
if (notificationId === "project-update") {
+ loader.start("Loading project",0)
RED.nodes.clear();
RED.history.clear();
RED.view.redraw(true);
@@ -208,6 +220,7 @@ var RED = (function() {
"revert": RED._("notification.project.revert", {project: msg.project}),
"merge-complete": RED._("notification.project.merge-complete")
}[msg.action];
+ loader.end()
RED.notify(""+message+"
");
RED.sidebar.info.refresh()
});
@@ -353,7 +366,7 @@ var RED = (function() {
var parts = topic.split("/");
var node = RED.nodes.node(parts[1]);
if (node) {
- if (msg.hasOwnProperty("text") && /^[a-zA-Z]/.test(msg.text)) {
+ if (msg.hasOwnProperty("text") && msg.text !== null && /^[a-zA-Z]/.test(msg.text)) {
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
}
node.status = msg;
@@ -423,6 +436,12 @@ var RED = (function() {
var id = topic.substring(9);
RED.eventLog.log(id,payload);
});
+
+ $(".red-ui-header-toolbar").show();
+
+ setTimeout(function() {
+ loader.end();
+ },100);
}
function showAbout() {
@@ -431,8 +450,7 @@ var RED = (function() {
''+
'';
- RED.sidebar.info.set(aboutHeader+RED.utils.renderMarkdown(data));
- RED.sidebar.info.show();
+ RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data));
});
}
@@ -472,6 +490,14 @@ var RED = (function() {
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"},
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"},
]});
+ menuOptions.push({id:"menu-item-group",label:RED._("menu.label.groups"), options: [
+ {id:"menu-item-group-group",label:RED._("menu.label.groupSelection"),disabled:true,onselect:"core:group-selection"},
+ {id:"menu-item-group-ungroup",label:RED._("menu.label.ungroupSelection"),disabled:true,onselect:"core:ungroup-selection"},
+ null,
+ {id:"menu-item-group-merge",label:RED._("menu.label.groupMergeSelection"),disabled:true,onselect:"core:merge-selection-to-group"},
+ {id:"menu-item-group-remove",label:RED._("menu.label.groupRemoveSelection"),disabled:true,onselect:"core:remove-selection-from-group"}
+ ]});
+
menuOptions.push(null);
if (RED.settings.theme('palette.editable') !== false) {
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
@@ -497,7 +523,6 @@ var RED = (function() {
}
function loadEditor() {
-
RED.workspaces.init();
RED.statusBar.init();
RED.view.init();
@@ -524,6 +549,7 @@ var RED = (function() {
}
RED.subflow.init();
+ RED.group.init();
RED.clipboard.init();
RED.search.init();
RED.actionList.init();
@@ -539,13 +565,14 @@ var RED = (function() {
RED.comms.connect();
$("#red-ui-main-container").show();
- $(".red-ui-header-toolbar").show();
+
RED.actions.add("core:show-about", showAbout);
loadNodeList();
}
+
function buildEditor(options) {
var header = $('').appendTo(options.target);
var logo = $('').appendTo(header);
@@ -560,6 +587,10 @@ var RED = (function() {
'').appendTo(options.target);
$('').appendTo(options.target);
$('').appendTo(options.target);
+
+ loader.init().appendTo("#red-ui-main-container");
+ loader.start("...",0);
+
$.getJSON(options.apiRootUrl+"theme", function(theme) {
if (theme.header) {
if (theme.header.url) {
@@ -592,12 +623,39 @@ var RED = (function() {
options.target.addClass("red-ui-editor");
buildEditor(options);
+
RED.i18n.init(options, function() {
RED.settings.init(options, loadEditor);
})
}
+ var loader = {
+ init: function() {
+ var wrapper = $('').hide();
+ var container = $('').appendTo(wrapper);
+ var label = $('
',{class:"red-ui-loading-bar-label"}).appendTo(container);
+ var bar = $('
',{class:"red-ui-loading-bar"}).appendTo(container);
+ var fill =$('').appendTo(bar);
+ return wrapper;
+ },
+ start: function(text, prcnt) {
+ if (text) {
+ loader.reportProgress(text,prcnt)
+ }
+ $("#red-ui-loading-progress").show();
+ },
+ reportProgress: function(text, prcnt) {
+ $(".red-ui-loading-bar-label").text(text);
+ $(".red-ui-loading-bar span").width(prcnt+"%")
+ },
+ end: function() {
+ $("#red-ui-loading-progress").hide();
+ loader.reportProgress("",0);
+ }
+ }
+
return {
- init: init
+ init: init,
+ loader: loader
}
})();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js
index cdff62919..33b306752 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js
@@ -184,7 +184,7 @@ RED.clipboard = (function() {
'
'+
'