Compare commits
	
		
			77 Commits
		
	
	
		
			fix-ungrou
			...
			v2.x
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | f91762ec8f | ||
|  | 7f698610df | ||
|  | bee06f64f5 | ||
|  | 53af4231af | ||
|  | 2ea4b15dca | ||
|  | ce09f56dcc | ||
|  | 6c648e4bab | ||
|  | 72661aa159 | ||
|  | 16e79d6bd2 | ||
|  | 726fac97d2 | ||
|  | efc3882961 | ||
|  | 489c456271 | ||
|  | 970be7b5f2 | ||
|  | b94fdd2f79 | ||
|  | 66f6bc59fa | ||
|  | 455f2dc800 | ||
|  | aed2b8e46d | ||
|  | 633afbbb44 | ||
|  | 6c797e35cf | ||
|  | 30b8a95421 | ||
|  | 7665971b52 | ||
|  | ba6dc3117f | ||
|  | 73fcc05a54 | ||
|  | fd409b0636 | ||
|  | 29287149b4 | ||
|  | 18c0ec990a | ||
|  | ee2b151b7a | ||
|  | 2d7a068644 | ||
|  | 5c5855751c | ||
|  | 396b3b64ff | ||
|  | 48e33a472b | ||
|  | a7375e4e8f | ||
|  | 42732db2b0 | ||
|  | 7c830856df | ||
|  | 5dad33dc77 | ||
|  | cbdb988d02 | ||
|  | e944dfecc2 | ||
|  | b2c2b9bd14 | ||
|  | 0ed7f6ce4e | ||
|  | 74e3b9e9ed | ||
|  | 7fd884c68f | ||
|  | 3f29283724 | ||
|  | ea303495b0 | ||
|  | 9d39709038 | ||
|  | facb6143c3 | ||
|  | 68a2786ff2 | ||
|  | b2b31670f8 | ||
|  | 355fb724f8 | ||
|  | d925f12aea | ||
|  | 428ed090f3 | ||
|  | 9946132658 | ||
|  | 30f08a9f17 | ||
|  | 83f1729d83 | ||
|  | 3667de18a9 | ||
|  | bda8e86ea4 | ||
|  | 7920fa1dd4 | ||
|  | cb06690553 | ||
|  | 4b4e5a0861 | ||
|  | e5952f082e | ||
|  | c7994b6393 | ||
|  | 39ac6b0d46 | ||
|  | e22bf22b61 | ||
|  | 92dd80ac49 | ||
|  | 9442e2a993 | ||
|  | 6df7f50f9f | ||
|  | 933cad888f | ||
|  | 8133c5e834 | ||
|  | e7f6549cb6 | ||
|  | 2ded07c765 | ||
|  | 6a799e7e2a | ||
|  | 1d40378f8c | ||
|  | bcab1cf096 | ||
|  | 03484fd5cd | ||
|  | 1eea371124 | ||
|  | 02d9ad479d | ||
|  | 3be75fa822 | ||
|  | ca204dea2d | 
							
								
								
									
										2
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -26,7 +26,7 @@ jobs: | ||||
|             path: 'node-red.github.io' | ||||
|       - uses: actions/setup-node@v1 | ||||
|         with: | ||||
|             node-version: '16' | ||||
|             node-version: '12' | ||||
|       - run: node ./node-red/.github/scripts/update-node-red-docker.js | ||||
|       - name: Create Docker Pull Request | ||||
|         uses: peter-evans/create-pull-request@v2 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -11,7 +11,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       matrix: | ||||
|         node-version: [14, 16] | ||||
|         node-version: [12, 14, 16] | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
|     - name: Use Node.js ${{ matrix.node-version }} | ||||
|   | ||||
							
								
								
									
										89
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						| @@ -1,31 +1,18 @@ | ||||
| #### 3.0.0-beta.1: Beta Release | ||||
|  | ||||
| **Migration from 2.x** | ||||
|  | ||||
|  - Node-RED now requires Node.js 14.x or later. | ||||
|  - New installs of Node-RED will default to the monaco editor. | ||||
|  | ||||
| #### 2.2.3: Maintenance Release | ||||
|  | ||||
| Editor | ||||
|  | ||||
|  - Add Junctions (#3462) @knolleary | ||||
|  - Allow node name to be auto-generated when added (#3478, #3538) @knolleary | ||||
|  - Set monaco as default code editor as of v3.x (#3543) @Steve-Mcl | ||||
|  - Update Monaco to V0.33.0 (#3522) @Steve-Mcl | ||||
|  - Auto-complete Improvements (#3521) @Steve-Mcl | ||||
|  - Add a tooltip to debug sidebar messages to reveal full path to node (#3503) @knolleary | ||||
|  - Fix down arrow triggering menu in search box (#3507) @Steve-Mcl | ||||
|  - Add Japanese translations for v3.0 (#3512) @kazuhitoyokoi | ||||
|  - Add feature: Continuous search tools (search previous, search next) (#3405) @Steve-Mcl | ||||
|  - Add feature: split-wire-to-links (#3399, #3476) @Steve-Mcl | ||||
|  - Add copy button to node properties tables (#3390) @knolleary | ||||
|  - Add info-tab search options dropdown to the regular search (#3395) @Steve-Mcl | ||||
|  - New Feature: Add ability to find modified nodes/flows. (#3392) @Steve-Mcl | ||||
|  - Code editor ux improvements around remembering state of each code editor in a flow (#3553) @Steve-Mcl | ||||
|  - Make it easier to apply themes on SVG icons (#3515) @bonanitech | ||||
|  - Add support of property validation message (#3438) @HiroyasuNishiyama | ||||
|  - Ensure node validation tooltip is closed when field becomes valid (#3570) @knolleary | ||||
|  - Add "search for" buttons to notifications (#3567) @Steve-Mcl | ||||
|  - Fix storing subflow credential type when input has multiple types (backport to v2.x) (#3828) @Steve-Mcl | ||||
|  - Fix markdown editor to mark up orderedlists correctly | ||||
|  - Ensure 'hidden flow' count doesn't include subflows (backport to v2.x) (#3823) @Steve-Mcl | ||||
|  - Fix credential type input item of subflow template (backport to v2.x) (#3822) @Steve-Mcl | ||||
|  - Fix to extend escaped subflow category characters (backport #3647 to v2.x) (#3665) @Steve-Mcl | ||||
|  - Reset mouse state when switching tabs (Backport #3643 to v2.x) (#3664) @Steve-Mcl | ||||
|  - Fix to sanitize tab name (Backport #3646 to v2.x) (#3663) @Steve-Mcl | ||||
|  - fix new folder menu of save to library dialog (backport #3633 to v2.x) (#3661) @Steve-Mcl | ||||
|  - Ensure ACE worker options are set (Backport 3611 to v2.x) (#3657) @Steve-Mcl | ||||
|  - Fix browser console error Uncaught TypeError when searching certain terms (Backport #3548 to v2.x) (#3656) @Steve-Mcl | ||||
|  - Remove duplicate history add of ungroup event (backport #3581to v2.x) (#3655) @Steve-Mcl | ||||
|  - Don't let themes change node config colors (#3564) @bonanitech | ||||
|  - Fix gap between typedInput containers borders (#3560) @bonanitech | ||||
|  - Fix recording removed links in edit history (#3547) @knolleary | ||||
| @@ -37,43 +24,39 @@ Editor | ||||
|  - Prevent shortcut deploy when deploy button shaded (#3517) @Steve-Mcl | ||||
|  - Fix: Sidebar "Configuration" filter button tooltip (#3500) @ralphwetzel | ||||
|  - Add the ability to customize diff colors even more (#3499) @bonanitech | ||||
|  - Do JSON comparison of old value/new value in editor (#3481) @Steve-Mcl | ||||
|  - Fix nodes losing their wires when in an iframe (#3484) @zettca | ||||
|  - do JSON comparison of old value/new value (#3481) @Steve-Mcl | ||||
|  - fix nodes losing their wires when in an iframe (#3484) @zettca | ||||
|  - Improve scroll into view (#3468) @Steve-Mcl | ||||
|  - Do not show 1st tab if hidden when loading (#3464) @Steve-Mcl | ||||
|  - Dont show 1st tab if hidden when loading (#3464) @Steve-Mcl | ||||
|  | ||||
| Runtime | ||||
|  | ||||
|  - Fix importing external module from node-red module (#3541) @knolleary | ||||
|  - Add support for multiple static paths with optional static root (#3542) @Steve-Mcl | ||||
|  - Store external token when authenticating if provided (#3460) @ArFe | ||||
|  - Support OAuth/OpenID logout (#3388) @mw75 | ||||
|  - Allow adminAuth to auto-login users when using passport strategy (#3519) @knolleary | ||||
|  - Add runtime diagnostics admin endpoint (#3511) @Steve-Mcl | ||||
|  - Do not remove unknown credentials of Subflow Modules (backport to v2.x) (#3826) @Steve-Mcl | ||||
|  - Backports to v2.x (#3735) @kazuhitoyokoi | ||||
|  - Backports to v2.x (#3705) @kazuhitoyokoi | ||||
|  - fix buffer parse error message of evaluateNodeProperty (backports #3624 for v2.x) (#3659) @Steve-Mcl | ||||
|  - Don't start if user has no home directory (#3540) @hardillb | ||||
|  - Error on invalid encrypted credentials (#3498) @sammachin | ||||
|  | ||||
| Nodes | ||||
|  | ||||
|  - Debug: Add message count option to Debug status (#3544 #3551) @rafaelmuynarsk @knolleary | ||||
|  - File: Change basic Filename field to a typedInput (#3533) @Steve-Mcl | ||||
|  - HTTP Request: Add UI for Http Request node headers (#3488) @Steve-Mcl | ||||
|  - Inject: let inject optionally fire at start in only at time mode. (#3385) @dceejay | ||||
|  - Link Call: Dynamic link call (#3463) @Steve-Mcl | ||||
|  - Link Call: Display link targets of nodes in a regular flow, for Link Call nodes inside a subflow (#3528) @Steve-Mcl | ||||
|  - MQTT: MQTT payload auto parsing improvements (#3530) @Steve-Mcl | ||||
|  - MQTT: Add client and Runtime MQTT topic validation (#3563) @Steve-Mcl [dev] | ||||
|  - MQTT: save and restore v5 config user props (#3562) @Steve-Mcl | ||||
|  - MQTT: Fix incorrect MQTT status (#3552) @Steve-Mcl | ||||
|  - MQTT: fix reference error of msg.status in debug node (#3526) @HiroyasuNishiyama | ||||
|  - MQTT: Add unit tests for MQTT nodes (#3497) @Steve-Mcl | ||||
|  - MQTT: fix typo of will properties (#3502) @Steve-Mcl | ||||
|  - MQTT: ensure mqtt v5 props can be set false (#3472) @Steve-Mcl | ||||
|  - Switch: add check for NaN in is of type number to be false (#3409) @dceejay | ||||
|  - TCP: TCP node better split (#3465) @dceejay | ||||
|  - Watch: Update Watch node to use node-watch module (#3559 #3569) @knolleary | ||||
|  - WebSocket: call done after ws disconnects (#3531) @Steve-Mcl | ||||
|  | ||||
|  - Allow HTTP Headers not in spec (backport to v2.x) (#3829) @Steve-Mcl | ||||
|  - Fix change node, not handling from field properly when using context (backport to v2.x) (#3827) @Steve-Mcl | ||||
|  - undo regression to tcp-in node | ||||
|  - Fix CSV node to handle when outputting text fields (backport to v2.x) (#3825) @Steve-Mcl | ||||
|  - Fix delay rate limit last timing when empty (backport to v2.x) (#3824) @Steve-Mcl | ||||
|  - Join-reduce keep existing msg properties (backport to v2.x) (#3821) @Steve-Mcl | ||||
|  - Fix ESM module loading in Function node (Backport #3645 to v2.x) (#3662) @Steve-Mcl | ||||
|  - Fix JSONata evaluation of inject button (Backport 3632 to v2.x) (#3660) @Steve-Mcl | ||||
|  - Dont delete TCP socket twice (backport Backport: #3630 to v2.x) (#3658) @Steve-Mcl | ||||
|  - Mqtt fixes in v3 for v2.x (backports #3563 #3594 #3626 to v2.x) (#3654) @Steve-Mcl | ||||
|  - MQTT Node - save and restore v5 config user props (#3562) @Steve-Mcl | ||||
|  - Fix incorrect MQTT status (#3552) @Steve-Mcl | ||||
|  - fix reference error of msg.status in debug node (#3526) @HiroyasuNishiyama | ||||
|  - call done after ws disconnects (#3531) @Steve-Mcl | ||||
|  - Add unit tests for MQTT nodes (#3497) @Steve-Mcl | ||||
|  - fix typo of will properties (properies) (#3502) @Steve-Mcl | ||||
|  - fix: ensure mqtt v5 props can be set false (#3472) @Steve-Mcl | ||||
|  | ||||
| #### 2.2.2: Maintenance Release | ||||
|  | ||||
|   | ||||
| @@ -165,7 +165,6 @@ module.exports = function(grunt) { | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.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/diagnostics.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/diff.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js", | ||||
|   | ||||
							
								
								
									
										61
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "node-red", | ||||
|     "version": "3.0.0-beta.1", | ||||
|     "version": "2.2.3", | ||||
|     "description": "Low-code programming for event-driven applications", | ||||
|     "homepage": "http://nodered.org", | ||||
|     "license": "Apache-2.0", | ||||
| @@ -26,57 +26,56 @@ | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "acorn": "8.7.1", | ||||
|         "acorn": "8.7.0", | ||||
|         "acorn-walk": "8.2.0", | ||||
|         "ajv": "8.11.0", | ||||
|         "ajv": "8.10.0", | ||||
|         "async-mutex": "0.3.2", | ||||
|         "basic-auth": "2.0.1", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "body-parser": "1.20.0", | ||||
|         "body-parser": "1.19.1", | ||||
|         "cheerio": "1.0.0-rc.10", | ||||
|         "clone": "2.1.2", | ||||
|         "content-type": "1.0.4", | ||||
|         "cookie": "0.5.0", | ||||
|         "cookie": "0.4.2", | ||||
|         "cookie-parser": "1.4.6", | ||||
|         "cors": "2.8.5", | ||||
|         "cronosjs": "1.7.1", | ||||
|         "denque": "2.0.1", | ||||
|         "express": "4.18.1", | ||||
|         "express": "4.17.2", | ||||
|         "express-session": "1.17.2", | ||||
|         "form-data": "4.0.0", | ||||
|         "fs-extra": "10.1.0", | ||||
|         "fs-extra": "10.0.0", | ||||
|         "fs.notify": "0.0.4", | ||||
|         "got": "11.8.3", | ||||
|         "hash-sum": "2.0.0", | ||||
|         "hpagent": "1.0.0", | ||||
|         "https-proxy-agent": "5.0.1", | ||||
|         "i18next": "21.6.16", | ||||
|         "hpagent": "0.1.2", | ||||
|         "https-proxy-agent": "5.0.0", | ||||
|         "i18next": "21.6.11", | ||||
|         "iconv-lite": "0.6.3", | ||||
|         "is-utf8": "0.2.1", | ||||
|         "js-yaml": "4.1.0", | ||||
|         "js-yaml": "3.14.1", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "jsonata": "1.8.6", | ||||
|         "lodash.clonedeep": "^4.5.0", | ||||
|         "media-typer": "1.1.0", | ||||
|         "memorystore": "1.6.7", | ||||
|         "mime": "3.0.0", | ||||
|         "moment": "2.29.3", | ||||
|         "moment-timezone": "0.5.34", | ||||
|         "mqtt": "4.3.7", | ||||
|         "mqtt": "4.3.5", | ||||
|         "multer": "1.4.4", | ||||
|         "mustache": "4.2.0", | ||||
|         "node-red-admin": "^3.0.0", | ||||
|         "node-watch": "0.7.3", | ||||
|         "node-red-admin": "^2.2.3", | ||||
|         "nopt": "5.0.0", | ||||
|         "oauth2orize": "1.11.1", | ||||
|         "on-headers": "1.0.2", | ||||
|         "passport": "0.5.2", | ||||
|         "passport-http-bearer": "1.0.1", | ||||
|         "passport-oauth2-client-password": "0.1.2", | ||||
|         "raw-body": "2.5.1", | ||||
|         "semver": "7.3.7", | ||||
|         "raw-body": "2.4.3", | ||||
|         "semver": "7.3.5", | ||||
|         "tar": "6.1.11", | ||||
|         "tough-cookie": "4.0.0", | ||||
|         "uglify-js": "3.15.4", | ||||
|         "uglify-js": "3.15.1", | ||||
|         "uuid": "8.3.2", | ||||
|         "ws": "7.5.6", | ||||
|         "xml2js": "0.4.23" | ||||
| @@ -90,13 +89,13 @@ | ||||
|         "grunt-chmod": "~1.1.1", | ||||
|         "grunt-cli": "~1.4.3", | ||||
|         "grunt-concurrent": "3.0.0", | ||||
|         "grunt-contrib-clean": "2.0.1", | ||||
|         "grunt-contrib-clean": "~2.0.0", | ||||
|         "grunt-contrib-compress": "2.0.0", | ||||
|         "grunt-contrib-concat": "2.1.0", | ||||
|         "grunt-contrib-copy": "1.0.0", | ||||
|         "grunt-contrib-jshint": "3.2.0", | ||||
|         "grunt-contrib-uglify": "5.2.1", | ||||
|         "grunt-contrib-watch": "1.1.0", | ||||
|         "grunt-contrib-concat": "~1.0.1", | ||||
|         "grunt-contrib-copy": "~1.0.0", | ||||
|         "grunt-contrib-jshint": "3.1.1", | ||||
|         "grunt-contrib-uglify": "5.0.1", | ||||
|         "grunt-contrib-watch": "~1.1.0", | ||||
|         "grunt-jsdoc": "2.4.1", | ||||
|         "grunt-jsdoc-to-markdown": "6.0.0", | ||||
|         "grunt-jsonlint": "2.1.3", | ||||
| @@ -105,22 +104,22 @@ | ||||
|         "grunt-sass": "~3.1.0", | ||||
|         "grunt-simple-mocha": "~0.4.1", | ||||
|         "grunt-simple-nyc": "^3.0.1", | ||||
|         "i18next-http-backend": "1.4.0", | ||||
|         "i18next-http-backend": "1.3.2", | ||||
|         "jquery-i18next": "1.2.1", | ||||
|         "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", | ||||
|         "marked": "4.0.15", | ||||
|         "marked": "4.0.12", | ||||
|         "minami": "1.2.3", | ||||
|         "mocha": "9.2.2", | ||||
|         "mocha": "9.2.0", | ||||
|         "node-red-node-test-helper": "^0.2.7", | ||||
|         "nodemon": "2.0.16", | ||||
|         "nodemon": "2.0.15", | ||||
|         "proxy": "^1.0.2", | ||||
|         "sass": "1.51.0", | ||||
|         "sass": "1.49.7", | ||||
|         "should": "13.2.3", | ||||
|         "sinon": "11.1.2", | ||||
|         "stoppable": "^1.1.0", | ||||
|         "supertest": "6.2.3" | ||||
|         "supertest": "6.2.2" | ||||
|     }, | ||||
|     "engines": { | ||||
|         "node": ">=14" | ||||
|         "node": ">=12" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,23 +0,0 @@ | ||||
| let runtimeAPI; | ||||
| let settings; | ||||
| const apiUtil = require("../util"); | ||||
| module.exports = { | ||||
|     init: function(_settings, _runtimeAPI) { | ||||
|         settings = _settings; | ||||
|         runtimeAPI = _runtimeAPI; | ||||
|     }, | ||||
|     getReport: function(req, res) { | ||||
|         const diagnosticsOpts = settings.diagnostics || {}; | ||||
|         const opts = { | ||||
|             user: req.user, | ||||
|             scope: diagnosticsOpts.level || "basic" | ||||
|         } | ||||
|         if(diagnosticsOpts.enabled === false || diagnosticsOpts.enabled === "false") { | ||||
|             apiUtil.rejectHandler(req, res, {message: "diagnostics are disabled", status: 403, code: "diagnostics.disabled" }) | ||||
|         } else { | ||||
|             runtimeAPI.diagnostics.get(opts) | ||||
|             .then(function(result) { res.json(result); }) | ||||
|             .catch(err => apiUtil.rejectHandler(req, res, err)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -23,7 +23,6 @@ var context = require("./context"); | ||||
| var auth = require("../auth"); | ||||
| var info = require("./settings"); | ||||
| var plugins = require("./plugins"); | ||||
| var diagnostics = require("./diagnostics"); | ||||
|  | ||||
| var apiUtil = require("../util"); | ||||
|  | ||||
| @@ -35,7 +34,6 @@ module.exports = { | ||||
|         context.init(runtimeAPI); | ||||
|         info.init(settings,runtimeAPI); | ||||
|         plugins.init(runtimeAPI); | ||||
|         diagnostics.init(settings, runtimeAPI); | ||||
|  | ||||
|         var needsPermission = auth.needsPermission; | ||||
|  | ||||
| @@ -97,8 +95,6 @@ module.exports = { | ||||
|         adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler); | ||||
|         adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler); | ||||
|  | ||||
|         adminApp.get("/diagnostics", needsPermission("diagnostics.read"), diagnostics.getReport, apiUtil.errorHandler); | ||||
|  | ||||
|         return adminApp; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -106,15 +106,9 @@ async function login(req,res) { | ||||
|                 urlPrefix += "/"; | ||||
|             } | ||||
|             response = { | ||||
|                 "type":"strategy" | ||||
|                 "type":"strategy", | ||||
|                 "prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}] | ||||
|             } | ||||
|             if (mergedAdminAuth.strategy.autoLogin) { | ||||
|                 response.autoLogin = true | ||||
|                 response.loginRedirect = urlPrefix + "auth/strategy" | ||||
|             } | ||||
|             response.prompts = [ | ||||
|                 {type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"} | ||||
|             ] | ||||
|             if (mergedAdminAuth.strategy.icon) { | ||||
|                 response.prompts[0].icon = mergedAdminAuth.strategy.icon; | ||||
|             } | ||||
| @@ -191,7 +185,7 @@ function genericStrategy(adminApp,strategy) { | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             options.verify.apply(this,args); | ||||
|             options.verify.apply(null,args); | ||||
|         } else { | ||||
|             var profile = arguments[arguments.length - 2]; | ||||
|             return completeVerify(profile,originalDone); | ||||
|   | ||||
| @@ -92,16 +92,10 @@ var passwordTokenExchange = function(client, username, password, scope, done) { | ||||
|                 loginAttempts = loginAttempts.filter(function(logEntry) { | ||||
|                     return logEntry.user !== username; | ||||
|                 }); | ||||
|                 // Check if the user contains a user defined token and use it | ||||
|                 // instead of generating a new token | ||||
|                 if(user.token){ | ||||
|                     done(null,user.token,null,null); | ||||
|                 } else { | ||||
|                     Tokens.create(username,client.id,scope).then(function(tokens) { | ||||
|                         log.audit({event: "auth.login",user,username:username,client:client.id,scope:scope}); | ||||
|                         done(null,tokens.accessToken,null,{expires_in:tokens.expires_in}); | ||||
|                     }); | ||||
|                 } | ||||
|                 Tokens.create(username,client.id,scope).then(function(tokens) { | ||||
|                     log.audit({event: "auth.login",user,username:username,client:client.id,scope:scope}); | ||||
|                     done(null,tokens.accessToken,null,{expires_in:tokens.expires_in}); | ||||
|                 }); | ||||
|             } else { | ||||
|                 log.audit({event: "auth.login.fail.permissions",username:username,client:client.id,scope:scope}); | ||||
|                 done(null,false); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/editor-api", | ||||
|     "version": "3.0.0-beta.1", | ||||
|     "version": "2.2.3", | ||||
|     "license": "Apache-2.0", | ||||
|     "main": "./lib/index.js", | ||||
|     "repository": { | ||||
| @@ -16,14 +16,14 @@ | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "@node-red/util": "3.0.0-beta.1", | ||||
|         "@node-red/editor-client": "3.0.0-beta.1", | ||||
|         "@node-red/util": "2.2.3", | ||||
|         "@node-red/editor-client": "2.2.3", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "body-parser": "1.20.0", | ||||
|         "body-parser": "1.19.1", | ||||
|         "clone": "2.1.2", | ||||
|         "cors": "2.8.5", | ||||
|         "express-session": "1.17.2", | ||||
|         "express": "4.18.1", | ||||
|         "express": "4.17.2", | ||||
|         "memorystore": "1.6.7", | ||||
|         "mime": "3.0.0", | ||||
|         "multer": "1.4.4", | ||||
|   | ||||
| @@ -185,8 +185,7 @@ | ||||
|             "create-default-package": "Standardpaketdatei erstellen", | ||||
|             "no-thanks": "Nein, Danke", | ||||
|             "create-default-project": "Standardprojektdateien erstellen", | ||||
|             "show-merge-conflicts": "Merge-Konflikte anzeigen", | ||||
|             "unknownNodesButton": "Finden Sie unbekannte nodes" | ||||
|             "show-merge-conflicts": "Merge-Konflikte anzeigen" | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
| @@ -270,9 +269,7 @@ | ||||
|         "successfulRestart": "Flows erfolgreich neugestartet", | ||||
|         "deployFailed": "Übernahme (deploy) fehlgeschlagen: __message__", | ||||
|         "unusedConfigNodes": "Einige Konfigurations-Nodes werden nicht verwendet.", | ||||
|         "unusedConfigNodesButton":"Finden Sie ungenutzte konfig nodes", | ||||
|         "unknownNodesButton":"Finden Sie unbekannte nodes", | ||||
|         "invalidNodesButton":"Finden Sie ungültige nodes", | ||||
|         "unusedConfigNodesLink": "Hier klicken, um sie anzuschauen.", | ||||
|         "errors": { | ||||
|             "noResponse": "Keine Antwort vom Server" | ||||
|         }, | ||||
| @@ -637,7 +634,14 @@ | ||||
|             "empty": "leer", | ||||
|             "globalConfig": "Globale Konfigurations-Nodes", | ||||
|             "triggerAction": "Auslösen", | ||||
|             "find": "Suche im Arbeitsbereich" | ||||
|             "find": "Suche im Arbeitsbereich", | ||||
|             "search": { | ||||
|                 "configNodes": "Konfigurations-Nodes", | ||||
|                 "unusedConfigNodes": "Unbenutzte Konfigurations-Nodes", | ||||
|                 "invalidNodes": "Ungültige Nodes", | ||||
|                 "uknownNodes": "Unbekannte Nodes", | ||||
|                 "unusedSubflows": "Unbenutzte Subflows" | ||||
|             } | ||||
|         }, | ||||
|         "help": { | ||||
|             "name": "Hilfe", | ||||
| @@ -859,14 +863,7 @@ | ||||
|     }, | ||||
|     "search": { | ||||
|         "empty": "Keine Übereinstimmungen gefunden", | ||||
|         "addNode": "Node hinzufügen ...", | ||||
|         "options": { | ||||
|             "configNodes": "Konfigurations-Nodes", | ||||
|             "unusedConfigNodes": "Unbenutzte Konfigurations-Nodes", | ||||
|             "invalidNodes": "Ungültige Nodes", | ||||
|             "uknownNodes": "Unbekannte Nodes", | ||||
|             "unusedSubflows": "Unbenutzte Subflows" | ||||
|         } | ||||
|         "addNode": "Node hinzufügen ..." | ||||
|     }, | ||||
|     "expressionEditor": { | ||||
|         "functions": "Funktionen", | ||||
|   | ||||
| @@ -149,11 +149,7 @@ | ||||
|         "toggle-navigator": "Toggle navigator", | ||||
|         "zoom-out": "Zoom out", | ||||
|         "zoom-reset": "Reset zoom", | ||||
|         "zoom-in": "Zoom in", | ||||
|         "search-flows": "Search flows", | ||||
|         "search-prev": "Previous", | ||||
|         "search-next": "Next", | ||||
|         "search-counter": "\"__term__\" __result__ of __count__" | ||||
|         "zoom-in": "Zoom in" | ||||
|     }, | ||||
|     "user": { | ||||
|         "loggedInAs": "Logged in as __name__", | ||||
| @@ -217,8 +213,7 @@ | ||||
|             "create-default-package": "Create default package file", | ||||
|             "no-thanks": "No thanks", | ||||
|             "create-default-project": "Create default project files", | ||||
|             "show-merge-conflicts": "Show merge conflicts", | ||||
|             "unknownNodesButton": "Search for unknown nodes" | ||||
|             "show-merge-conflicts": "Show merge conflicts" | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
| @@ -302,9 +297,7 @@ | ||||
|         "successfulRestart": "Successfully restarted flows", | ||||
|         "deployFailed": "Deploy failed: __message__", | ||||
|         "unusedConfigNodes":"You have some unused configuration nodes.", | ||||
|         "unusedConfigNodesButton":"Search unused config nodes", | ||||
|         "unknownNodesButton":"Search for unknown nodes", | ||||
|         "invalidNodesButton":"Search for invalid nodes", | ||||
|         "unusedConfigNodesLink":"Click here to see them", | ||||
|         "errors": { | ||||
|             "noResponse": "no response from server" | ||||
|         }, | ||||
| @@ -504,8 +497,7 @@ | ||||
|         "redoChange": "Redo", | ||||
|         "searchBox": "Open search box", | ||||
|         "managePalette": "Manage palette", | ||||
|         "actionList": "Action list", | ||||
|         "splitWireWithLinks": "Split selection with Link nodes" | ||||
|         "actionList":"Action list" | ||||
|     }, | ||||
|     "library": { | ||||
|         "library": "Library", | ||||
| @@ -675,7 +667,15 @@ | ||||
|             "empty": "empty", | ||||
|             "globalConfig": "Global Configuration Nodes", | ||||
|             "triggerAction": "Trigger action", | ||||
|             "find": "Find in workspace" | ||||
|             "find": "Find in workspace", | ||||
|             "search": { | ||||
|                 "configNodes": "Configuration nodes", | ||||
|                 "unusedConfigNodes": "Unused configuration nodes", | ||||
|                 "invalidNodes": "Invalid nodes", | ||||
|                 "uknownNodes": "Unknown nodes", | ||||
|                 "unusedSubflows": "Unused subflows", | ||||
|                 "hiddenFlows": "Hidden flows" | ||||
|             } | ||||
|         }, | ||||
|         "help": { | ||||
|             "name": "Help", | ||||
| @@ -899,16 +899,7 @@ | ||||
|         "history": "Search history", | ||||
|         "clear": "clear all", | ||||
|         "empty": "No matches found", | ||||
|         "addNode": "add a node...", | ||||
|         "options": { | ||||
|             "configNodes": "Configuration nodes", | ||||
|             "unusedConfigNodes": "Unused configuration nodes", | ||||
|             "invalidNodes": "Invalid nodes", | ||||
|             "uknownNodes": "Unknown nodes", | ||||
|             "unusedSubflows": "Unused subflows", | ||||
|             "hiddenFlows": "Hidden flows", | ||||
|             "modifiedNodes": "Modified nodes and flows" | ||||
|         } | ||||
|         "addNode": "add a node..." | ||||
|     }, | ||||
|     "expressionEditor": { | ||||
|         "functions": "Functions", | ||||
| @@ -943,8 +934,6 @@ | ||||
|         "format": "format JSON", | ||||
|         "rawMode": "Edit JSON", | ||||
|         "uiMode": "Visual editor", | ||||
|         "rawMode-readonly": "JSON", | ||||
|         "uiMode-readonly": "Visual", | ||||
|         "insertAbove": "Insert above", | ||||
|         "insertBelow": "Insert below", | ||||
|         "addItem": "Add item", | ||||
| @@ -1159,9 +1148,6 @@ | ||||
|         "start": "Start", | ||||
|         "next": "Next" | ||||
|     }, | ||||
|     "diagnostics": { | ||||
|         "title": "System Info" | ||||
|     }, | ||||
|     "languages" : { | ||||
|         "de": "German", | ||||
|         "en-US": "English", | ||||
| @@ -1170,21 +1156,5 @@ | ||||
|         "ru": "Russian", | ||||
|         "zh-CN": "Chinese(Simplified)", | ||||
|         "zh-TW": "Chinese(Traditional)" | ||||
|     }, | ||||
|     "validator": { | ||||
|         "errors": { | ||||
| 	    "invalid-json": "Invalid JSON data: __error__", | ||||
| 	    "invalid-json-prop": "__prop__: invalid JSON data: __error__", | ||||
| 	    "invalid-prop": "Invalid property expression", | ||||
| 	    "invalid-prop-prop": "__prop__: invalid property expression", | ||||
| 	    "invalid-num": "Invalid number", | ||||
| 	    "invalid-num-prop": "__prop__: invalid number", | ||||
| 	    "invalid-regexp": "Invalid input pattern", | ||||
| 	    "invalid-regex-prop": "__prop__: invalid input pattern", | ||||
| 	    "missing-required-prop": "__prop__: property value missing", | ||||
| 	    "invalid-config": "__prop__: invalid configuration node", | ||||
| 	    "missing-config": "__prop__: missing configuration node", | ||||
| 	    "validation-error": "__prop__: validation error: __node__, __id__: __error__" | ||||
| 	} | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -149,11 +149,7 @@ | ||||
|         "toggle-navigator": "ナビゲータの表示/非表示を切替", | ||||
|         "zoom-out": "縮小", | ||||
|         "zoom-reset": "拡大/縮小を初期化", | ||||
|         "zoom-in": "拡大", | ||||
|         "search-flows": "フローを検索", | ||||
|         "search-prev": "前へ", | ||||
|         "search-next": "次へ", | ||||
|         "search-counter": "\"__term__\" __count__ 件中の __result__ 件目" | ||||
|         "zoom-in": "拡大" | ||||
|     }, | ||||
|     "user": { | ||||
|         "loggedInAs": "__name__ としてログインしました", | ||||
| @@ -217,8 +213,7 @@ | ||||
|             "create-default-package": "デフォルトパッケージファイルの作成", | ||||
|             "no-thanks": "不要", | ||||
|             "create-default-project": "デフォルトプロジェクトファイルの作成", | ||||
|             "show-merge-conflicts": "マージ競合を表示", | ||||
|             "unknownNodesButton": "不明なノードを検索する" | ||||
|             "show-merge-conflicts": "マージ競合を表示" | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
| @@ -302,9 +297,7 @@ | ||||
|         "successfulRestart": "フローの再起動が成功しました", | ||||
|         "deployFailed": "デプロイが失敗しました: __message__", | ||||
|         "unusedConfigNodes": "使われていない設定ノードがあります。", | ||||
|         "unusedConfigNodesButton": "未使用の構成ノードを検索", | ||||
|         "unknownNodesButton": "不明なノードを検索する", | ||||
|         "invalidNodesButton": "無効なノードを検索する", | ||||
|         "unusedConfigNodesLink": "設定を参照する", | ||||
|         "errors": { | ||||
|             "noResponse": "サーバの応答がありません" | ||||
|         }, | ||||
| @@ -504,8 +497,7 @@ | ||||
|         "redoChange": "変更操作をやり直し", | ||||
|         "searchBox": "ノードを検索", | ||||
|         "managePalette": "パレットの管理", | ||||
|         "actionList": "動作一覧", | ||||
|         "splitWireWithLinks": "選択したワイヤーをlinkノードで分離" | ||||
|         "actionList": "動作一覧" | ||||
|     }, | ||||
|     "library": { | ||||
|         "library": "ライブラリ", | ||||
| @@ -675,7 +667,15 @@ | ||||
|             "empty": "空", | ||||
|             "globalConfig": "グローバル設定ノード", | ||||
|             "triggerAction": "アクションを実行", | ||||
|             "find": "ワークスペース内を検索" | ||||
|             "find": "ワークスペース内を検索", | ||||
|             "search": { | ||||
|                 "configNodes": "設定ノード", | ||||
|                 "unusedConfigNodes": "未使用の設定ノード", | ||||
|                 "invalidNodes": "不正なノード", | ||||
|                 "uknownNodes": "未知のノード", | ||||
|                 "unusedSubflows": "未使用のサブフロー", | ||||
|                 "hiddenFlows": "非表示のフロー" | ||||
|             } | ||||
|         }, | ||||
|         "help": { | ||||
|             "name": "ヘルプ", | ||||
| @@ -845,7 +845,7 @@ | ||||
|                 "pushFailed": "リモートに新しいコミットがあるため、プッシュに失敗しました。プルしてマージしてから、再度プッシュしてください。", | ||||
|                 "push": "プッシュ", | ||||
|                 "pull": "プル", | ||||
|                 "unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更を上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>", | ||||
|                 "unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更が上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>", | ||||
|                 "showUnstagedChanges": "ステージングされていない変更を表示", | ||||
|                 "connectionFailed": "リモートリポジトリに接続できません: ", | ||||
|                 "pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>", | ||||
| @@ -899,16 +899,7 @@ | ||||
|         "history": "検索履歴", | ||||
|         "clear": "全て削除", | ||||
|         "empty": "一致したものが見つかりませんでした", | ||||
|         "addNode": "ノードを追加...", | ||||
|         "options": { | ||||
|             "configNodes": "設定ノード", | ||||
|             "unusedConfigNodes": "未使用の設定ノード", | ||||
|             "invalidNodes": "不正なノード", | ||||
|             "uknownNodes": "未知のノード", | ||||
|             "unusedSubflows": "未使用のサブフロー", | ||||
|             "hiddenFlows": "非表示のフロー", | ||||
|             "modifiedNodes": "修正したノードやフロー" | ||||
|         } | ||||
|         "addNode": "ノードを追加..." | ||||
|     }, | ||||
|     "expressionEditor": { | ||||
|         "functions": "関数", | ||||
| @@ -943,8 +934,6 @@ | ||||
|         "format": "JSONフォーマット", | ||||
|         "rawMode": "JSONを編集", | ||||
|         "uiMode": "ビジュアルエディタ", | ||||
|         "rawMode-readonly": "JSON", | ||||
|         "uiMode-readonly": "ビジュアル", | ||||
|         "insertAbove": "上に挿入", | ||||
|         "insertBelow": "下に挿入", | ||||
|         "addItem": "要素を追加", | ||||
| @@ -1159,9 +1148,6 @@ | ||||
|         "start": "開始", | ||||
|         "next": "次へ" | ||||
|     }, | ||||
|     "diagnostics": { | ||||
|         "title": "システム情報" | ||||
|     }, | ||||
|     "languages": { | ||||
|         "de": "ドイツ語", | ||||
|         "en-US": "英語", | ||||
| @@ -1171,22 +1157,6 @@ | ||||
|         "zh-CN": "中国語(簡体)", | ||||
|         "zh-TW": "中国語(繁体)" | ||||
|     }, | ||||
|     "validator": { | ||||
|         "errors": { | ||||
|             "invalid-json": "JSONデータが不正: __error__", | ||||
|             "invalid-json-prop": "__prop__: JSONデータが不正: __error__", | ||||
|             "invalid-prop": "プロパティ式が不正", | ||||
|             "invalid-prop-prop": "__prop__: プロパティ式が不正", | ||||
|             "invalid-num": "数値が不正", | ||||
|             "invalid-num-prop": "__prop__: 数値が不正", | ||||
|             "invalid-regexp": "入力パターンが不正", | ||||
|             "invalid-regex-prop": "__prop__: 入力パターンが不正", | ||||
|             "missing-required-prop": "__prop__: プロパティが未設定", | ||||
|             "invalid-config": "__prop__: 設定ノードが不正", | ||||
|             "missing-config": "__prop__: 設定ノードが存在しません", | ||||
|             "validation-error": "__prop__: チェックエラー: __node__, __id__: __error__" | ||||
|         } | ||||
|     }, | ||||
|     "action-list": { | ||||
|         "toggle-show-tips": "ヒント表示切替", | ||||
|         "show-about": "Node-REDの説明を表示", | ||||
| @@ -1204,7 +1174,6 @@ | ||||
|         "hide-all-flows": "全てのフローを非表示", | ||||
|         "show-all-flows": "全てのフローを表示", | ||||
|         "show-last-hidden-flow": "最後に非表示にしたフローを表示", | ||||
|         "list-modified-nodes": "修正したフローを表示", | ||||
|         "list-hidden-flows": "非表示フローを表示", | ||||
|         "list-flows": "フロー一覧", | ||||
|         "list-subflows": "サブフロー一覧", | ||||
| @@ -1271,8 +1240,6 @@ | ||||
|         "distribute-selection-vertically": "選択を上下に整列", | ||||
|         "wire-series-of-nodes": "ノードを一続きに接続", | ||||
|         "wire-node-to-multiple": "ノードを複数に接続", | ||||
|         "split-wire-with-link-nodes": "ワイヤーをlinkノードで分割", | ||||
|         "generate-node-names": "ノード名を生成", | ||||
|         "show-user-settings": "ユーザ設定を表示", | ||||
|         "show-help": "ヘルプを表示", | ||||
|         "toggle-palette": "パレットの表示切替", | ||||
| @@ -1299,8 +1266,6 @@ | ||||
|         "show-library-import-dialog": "ライブラリ読み込みダイアログを表示", | ||||
|         "show-examples-import-dialog": "サンプル読み込みダイアログを表示", | ||||
|         "search": "検索", | ||||
|         "search-previous": "前を検索", | ||||
|         "search-next": "次を検索", | ||||
|         "show-action-list": "アクション一覧を表示", | ||||
|         "confirm-edit-tray": "編集を完了", | ||||
|         "cancel-edit-tray": "編集をキャンセル", | ||||
| @@ -1311,8 +1276,8 @@ | ||||
|         "set-deploy-type-to-modified-flows": "デプロイを「変更したフロー」に設定", | ||||
|         "set-deploy-type-to-modified-nodes": "デプロイを「変更したノード」に設定", | ||||
|         "show-debug-tab": "デバッグタブを表示", | ||||
|         "clear-debug-messages": "デバッグメッセージを削除", | ||||
|         "clear-filtered-debug-messages": "フィルタしたデバッグメッセージを削除", | ||||
|         "clear-debug-messages": "デバッグメッセージをクリア", | ||||
|         "clear-filtered-debug-messages": "フィルタしたデバッグメッセージをクリア", | ||||
|         "activate-selected-debug-nodes": "選択したデバッグノードを有効化", | ||||
|         "activate-all-debug-nodes": "全てのデバッグノードを有効化", | ||||
|         "activate-all-flow-debug-nodes": "フロー内の全デバッグノードを有効化", | ||||
| @@ -1323,6 +1288,9 @@ | ||||
|         "zoom-out": "ズームアウト", | ||||
|         "zoom-reset": "ズームリセット", | ||||
|         "toggle-navigator": "ナビゲータ表示切替", | ||||
|         "show-system-info": "システムインフォメーション" | ||||
|         "new-project": "新しいプロジェクト", | ||||
|         "open-project": "プロジェクトを開く", | ||||
|         "show-project-settings": "プロジェクト設定を表示", | ||||
|         "show-version-control-tab": "バージョンコントロールタブを表示" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|         "tip14": "[shift] を押しながらノードを [click] すると、接続された全てのノードを選択できます。", | ||||
|         "tip15": "[ctrl] を押しながらノードを [click] すると、選択/非選択を切り替えできます。", | ||||
|         "tip16": "{{core:show-previous-tab}} や {{core:show-next-tab}} で、タブの切り替えができます。", | ||||
|         "tip17": "ノードのプロバティ設定画面にて {{core:confirm-edit-tray}} を押すと、変更を確定できます。また、 {{core:cancel-edit-tray}} を押すと、変更を取り消せます。", | ||||
|         "tip17": "ノードのプロパティ設定画面にて {{core:confirm-edit-tray}} を押すと、変更を確定できます。また、 {{core:cancel-edit-tray}} を押すと、変更を取り消せます。", | ||||
|         "tip18": "ノードを選択し、 {{core:edit-selected-node}} を押すとプロパティ設定画面が表示されます。" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -141,8 +141,7 @@ | ||||
|       "create-default-package": "기본 패키지 파일 생성", | ||||
|       "no-thanks": "괜찮습니다", | ||||
|       "create-default-project": "기본 프로젝트 파일 생성", | ||||
|       "show-merge-conflicts": "병합 충돌 보여주기", | ||||
|       "unknownNodesButton": "알 수 없는 노드 검색" | ||||
|       "show-merge-conflicts": "병합 충돌 보여주기" | ||||
|     } | ||||
|   }, | ||||
|   "clipboard": { | ||||
| @@ -204,9 +203,7 @@ | ||||
|     "successfulRestart": "플로우 재시작을 성공했습니다", | ||||
|     "deployFailed": "배포 실패 : __message__", | ||||
|     "unusedConfigNodes": "사용되지 않는 설정노드가 있습니다", | ||||
|     "unusedConfigNodesButton":"사용하지 않는 구성 노드 검색", | ||||
|     "unknownNodesButton":"알 수 없는 노드 검색", | ||||
|     "invalidNodesButton":"잘못된 노드 검색", | ||||
|     "unusedConfigNodesLink": "여기를 클릭하면 볼 수 있습니다", | ||||
|     "errors": { | ||||
|       "noResponse": "서버의 응답이 없습니다" | ||||
|     }, | ||||
|   | ||||
| @@ -183,8 +183,7 @@ | ||||
|             "create-default-package": "Создать файл пакета по умолчанию", | ||||
|             "no-thanks": "Нет, спасибо", | ||||
|             "create-default-project": "Создать файлы проекта по умолчанию", | ||||
|             "show-merge-conflicts": "Показать конфликты слияния", | ||||
|             "unknownNodesButton": "Поиск неизвестных узлов" | ||||
|             "show-merge-conflicts": "Показать конфликты слияния" | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
| @@ -278,9 +277,7 @@ | ||||
|         "successfulRestart": "Потоки успешно перезапущены", | ||||
|         "deployFailed": "Развертывание не удалось: __message__", | ||||
|         "unusedConfigNodes":"У вас есть неиспользуемых узлы конфигурации.", | ||||
|         "unusedConfigNodesButton":"Поиск неиспользуемых узлов конфигурации", | ||||
|         "unknownNodesButton":"Поиск неизвестных узлов", | ||||
|         "invalidNodesButton":"Поиск недопустимых узлов", | ||||
|         "unusedConfigNodesLink":"Нажмите здесь, чтобы их увидеть", | ||||
|         "errors": { | ||||
|             "noResponse": "нет ответа от сервера" | ||||
|         }, | ||||
| @@ -653,7 +650,14 @@ | ||||
|             "empty": "пусто", | ||||
|             "globalConfig": "Глобальные конфиг узлы", | ||||
|             "triggerAction": "Вызвать действие", | ||||
|             "find": "Найти в рабочей области" | ||||
|             "find": "Найти в рабочей области", | ||||
|             "search": { | ||||
|                 "configNodes": "Узлы конфигурации", | ||||
|                 "unusedConfigNodes": "Неиспользуемые узлы конфигурации", | ||||
|                 "invalidNodes": "Недействительные узлы", | ||||
|                 "uknownNodes": "Неизвестные узлы", | ||||
|                 "unusedSubflows": "Неиспользуемые подпотоки" | ||||
|             } | ||||
|         }, | ||||
|         "help": { | ||||
|             "name": "Справка", | ||||
| @@ -884,14 +888,7 @@ | ||||
|     }, | ||||
|     "search": { | ||||
|         "empty": "Ничего не найдено", | ||||
|         "addNode": "добавить узел...", | ||||
|         "options": { | ||||
|             "configNodes": "Узлы конфигурации", | ||||
|             "unusedConfigNodes": "Неиспользуемые узлы конфигурации", | ||||
|             "invalidNodes": "Недействительные узлы", | ||||
|             "uknownNodes": "Неизвестные узлы", | ||||
|             "unusedSubflows": "Неиспользуемые подпотоки" | ||||
|         } | ||||
|         "addNode": "добавить узел..." | ||||
|     }, | ||||
|     "expressionEditor": { | ||||
|         "functions": "Функции", | ||||
|   | ||||
| @@ -182,8 +182,7 @@ | ||||
|             "create-default-package": "创建默认的包文件", | ||||
|             "no-thanks": "不了,谢谢", | ||||
|             "create-default-project": "创建默认项目文件", | ||||
|             "show-merge-conflicts": "显示合并冲突", | ||||
|             "unknownNodesButton": "搜索未知节点" | ||||
|             "show-merge-conflicts": "显示合并冲突" | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
| @@ -265,9 +264,7 @@ | ||||
|         "successfulRestart": "成功重启流程", | ||||
|         "deployFailed": "部署失败: __message__", | ||||
|         "unusedConfigNodes": "您有一些未使用的配置节点", | ||||
|         "unusedConfigNodesButton":"搜索未使用的配置节点", | ||||
|         "unknownNodesButton":"搜索未知节点", | ||||
|         "invalidNodesButton":"搜索无效节点", | ||||
|         "unusedConfigNodesLink": "点击此处查看它们", | ||||
|         "errors": { | ||||
|             "noResponse": "服务器没有响应" | ||||
|         }, | ||||
| @@ -617,7 +614,14 @@ | ||||
|             "empty": "空的", | ||||
|             "globalConfig": "全局配置节点", | ||||
|             "triggerAction": "触发动作", | ||||
|             "find": "在工作区中查找" | ||||
|             "find": "在工作区中查找", | ||||
|             "search": { | ||||
|                 "configNodes": "配置节点", | ||||
|                 "unusedConfigNodes": "未使用的配置节点", | ||||
|                 "invalidNodes": "无效的节点", | ||||
|                 "uknownNodes": "未知的节点", | ||||
|                 "unusedSubflows": "未使用的子流程" | ||||
|             } | ||||
|         }, | ||||
|         "help": { | ||||
|             "name": "帮助", | ||||
| @@ -838,14 +842,7 @@ | ||||
|     }, | ||||
|     "search": { | ||||
|         "empty": "找不到匹配", | ||||
|         "addNode": "添加一个节点...", | ||||
|         "options": { | ||||
|             "configNodes": "配置节点", | ||||
|             "unusedConfigNodes": "未使用的配置节点", | ||||
|             "invalidNodes": "无效的节点", | ||||
|             "uknownNodes": "未知的节点", | ||||
|             "unusedSubflows": "未使用的子流程" | ||||
|         } | ||||
|         "addNode": "添加一个节点..." | ||||
|     }, | ||||
|     "expressionEditor": { | ||||
|         "functions": "功能", | ||||
|   | ||||
| @@ -182,8 +182,7 @@ | ||||
|             "create-default-package": "創建默認的包文件", | ||||
|             "no-thanks": "不了,謝謝", | ||||
|             "create-default-project": "創建默認項目文件", | ||||
|             "show-merge-conflicts": "顯示合併衝突", | ||||
|             "unknownNodesButton": "搜索未知節點" | ||||
|             "show-merge-conflicts": "顯示合併衝突" | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
| @@ -265,9 +264,7 @@ | ||||
|         "successfulRestart": "成功重啟流程", | ||||
|         "deployFailed": "部署失敗: __message__", | ||||
|         "unusedConfigNodes": "您有一些未使用的配置節點", | ||||
|         "unusedConfigNodesButton":"搜索未使用的配置節點", | ||||
|         "unknownNodesButton":"搜索未知節點", | ||||
|         "invalidNodesButton":"搜索無效節點", | ||||
|         "unusedConfigNodesLink": "點擊此處查看它們", | ||||
|         "errors": { | ||||
|             "noResponse": "伺服器沒有回應" | ||||
|         }, | ||||
| @@ -617,7 +614,14 @@ | ||||
|             "empty": "空的", | ||||
|             "globalConfig": "全局配置節點", | ||||
|             "triggerAction": "觸發動作", | ||||
|             "find": "在工作區中查找" | ||||
|             "find": "在工作區中查找", | ||||
|             "search": { | ||||
|                 "configNodes": "配置節點", | ||||
|                 "unusedConfigNodes": "未使用的配置節點", | ||||
|                 "invalidNodes": "無效的節點", | ||||
|                 "uknownNodes": "未知的節點", | ||||
|                 "unusedSubflows": "未使用的子流程" | ||||
|             } | ||||
|         }, | ||||
|         "help": { | ||||
|             "name": "幫助", | ||||
| @@ -838,14 +842,7 @@ | ||||
|     }, | ||||
|     "search": { | ||||
|         "empty": "找不到匹配", | ||||
|         "addNode": "添加一個節點...", | ||||
|         "options": { | ||||
|             "configNodes": "配置節點", | ||||
|             "unusedConfigNodes": "未使用的配置節點", | ||||
|             "invalidNodes": "無效的節點", | ||||
|             "uknownNodes": "未知的節點", | ||||
|             "unusedSubflows": "未使用的子流程" | ||||
|         } | ||||
|         "addNode": "添加一個節點..." | ||||
|     }, | ||||
|     "expressionEditor": { | ||||
|         "functions": "功能", | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/editor-client", | ||||
|     "version": "3.0.0-beta.1", | ||||
|     "version": "2.2.3", | ||||
|     "license": "Apache-2.0", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|   | ||||
| @@ -98,7 +98,7 @@ oop.inherits(NRJavaScriptWorker, Mirror); | ||||
|         if (options) { | ||||
|             for (var opt in options) { | ||||
|                 if (options.hasOwnProperty(opt)) { | ||||
|                     this.options[opt] = options.opt; | ||||
|                     this.options[opt] = options[opt]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								packages/node_modules/@node-red/editor-client/src/images/grip-horizontal.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 90 B | 
| @@ -1 +0,0 @@ | ||||
| <svg width="50" height="5" viewBox="0, 0, 50, 5" xmlns="http://www.w3.org/2000/svg"><path d="M0 1H50V4H0Z" fill="#CCC"/></svg> | ||||
| Before Width: | Height: | Size: 127 B | 
							
								
								
									
										
											BIN
										
									
								
								packages/node_modules/@node-red/editor-client/src/images/grip.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 192 B | 
| @@ -1 +0,0 @@ | ||||
| <svg width="5" height="50" viewBox="0, 0, 5, 50" xmlns="http://www.w3.org/2000/svg"><path d="M1 0H4V50H1Z" fill="#CCC"/></svg> | ||||
| Before Width: | Height: | Size: 127 B | 
| @@ -13,11 +13,6 @@ | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| /**  | ||||
|  * An API for undo / redo history buffer | ||||
|  * @namespace RED.history | ||||
| */ | ||||
| RED.history = (function() { | ||||
|     var undoHistory = []; | ||||
|     var redoHistory = []; | ||||
| @@ -106,23 +101,6 @@ RED.history = (function() { | ||||
|                         RED.nodes.removeLink(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.junctions) { | ||||
|                     inverseEv.junctions = []; | ||||
|                     for (i=0;i<ev.junctions.length;i++) { | ||||
|                         inverseEv.junctions.push(ev.junctions[i]); | ||||
|                         RED.nodes.removeJunction(ev.junctions[i]); | ||||
|                         if (ev.junctions[i].g) { | ||||
|                             var group = RED.nodes.group(ev.junctions[i].g); | ||||
|                             var index = group.nodes.indexOf(ev.junctions[i]); | ||||
|                             if (index !== -1) { | ||||
|                                 group.nodes.splice(index,1); | ||||
|                                 RED.group.markDirty(group); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.groups) { | ||||
|                     inverseEv.groups = []; | ||||
|                     for (i = ev.groups.length - 1;i>=0;i--) { | ||||
| @@ -289,21 +267,6 @@ RED.history = (function() { | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.junctions) { | ||||
|                     inverseEv.junctions = []; | ||||
|                     for (i=0;i<ev.junctions.length;i++) { | ||||
|                         inverseEv.junctions.push(ev.junctions[i]); | ||||
|                         RED.nodes.addJunction(ev.junctions[i]); | ||||
|                         if (ev.junctions[i].g) { | ||||
|                             group = RED.nodes.group(ev.junctions[i].g); | ||||
|                             if (group.nodes.indexOf(ev.junctions[i]) === -1) { | ||||
|                                 group.nodes.push(ev.junctions[i]); | ||||
|                             } | ||||
|                             RED.group.markDirty(group) | ||||
|                         } | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|   | ||||
| @@ -90,10 +90,6 @@ | ||||
|         "alt-a m": "core:align-selection-to-middle", | ||||
|         "alt-a c": "core:align-selection-to-center", | ||||
|         "alt-a h": "core:distribute-selection-horizontally", | ||||
|         "alt-a v": "core:distribute-selection-vertically", | ||||
|         "shift-f": "core:search-previous", | ||||
|         "f": "core:search-next", | ||||
|         "alt-l l": "core:split-wire-with-link-nodes" | ||||
|  | ||||
|         "alt-a v": "core:distribute-selection-vertically" | ||||
|      } | ||||
| } | ||||
|   | ||||
| @@ -13,11 +13,6 @@ | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| /**  | ||||
|  * An Interface to nodes and utility functions for creating/adding/deleting nodes and links | ||||
|  * @namespace RED.nodes | ||||
| */ | ||||
| RED.nodes = (function() { | ||||
|  | ||||
|     var PORT_TYPE_INPUT = 1; | ||||
| @@ -38,9 +33,6 @@ RED.nodes = (function() { | ||||
|     var groups = {}; | ||||
|     var groupsByZ = {}; | ||||
|  | ||||
|     var junctions = {}; | ||||
|     var junctionsByZ = {}; | ||||
|  | ||||
|     var initialLoad; | ||||
|  | ||||
|     var dirty = false; | ||||
| @@ -822,7 +814,6 @@ RED.nodes = (function() { | ||||
|         var removedNodes = []; | ||||
|         var removedLinks = []; | ||||
|         var removedGroups = []; | ||||
|         var removedJunctions = []; | ||||
|         if (ws) { | ||||
|             delete workspaces[id]; | ||||
|             delete linkTabMap[id]; | ||||
| @@ -831,14 +822,7 @@ RED.nodes = (function() { | ||||
|             var node; | ||||
|  | ||||
|             if (allNodes.hasTab(id)) { | ||||
|                 removedNodes = allNodes.getNodes(id).filter(n => { | ||||
|                     if (n.type === 'junction') { | ||||
|                         removedJunctions.push(n) | ||||
|                         return false | ||||
|                     } else { | ||||
|                         return true | ||||
|                     } | ||||
|                 }) | ||||
|                 removedNodes = allNodes.getNodes(id).slice() | ||||
|             } | ||||
|             for (i in configNodes) { | ||||
|                 if (configNodes.hasOwnProperty(i)) { | ||||
| @@ -853,10 +837,6 @@ RED.nodes = (function() { | ||||
|                 var result = removeNode(removedNodes[i].id); | ||||
|                 removedLinks = removedLinks.concat(result.links); | ||||
|             } | ||||
|             for (i=0;i<removedJunctions.length;i++) { | ||||
|                 var result = removeJunction(removedJunctions[i]) | ||||
|                 removedLinks = removedLinks.concat(result.links) | ||||
|             } | ||||
|  | ||||
|             // Must get 'removedGroups' in the right order. | ||||
|             //  - start with the top-most groups | ||||
| @@ -876,7 +856,7 @@ RED.nodes = (function() { | ||||
|             allNodes.removeTab(id); | ||||
|             RED.events.emit('flows:remove',ws); | ||||
|         } | ||||
|         return {nodes:removedNodes,links:removedLinks, groups: removedGroups, junctions: removedJunctions}; | ||||
|         return {nodes:removedNodes,links:removedLinks, groups: removedGroups}; | ||||
|     } | ||||
|  | ||||
|     function addSubflow(sf, createNewIds) { | ||||
| @@ -1133,7 +1113,7 @@ RED.nodes = (function() { | ||||
|                 delete node.env; | ||||
|             } | ||||
|         } | ||||
|         if (n._def.category != "config" || n.type === 'junction') { | ||||
|         if (n._def.category != "config") { | ||||
|             node.x = n.x; | ||||
|             node.y = n.y; | ||||
|             if (exportDimensions) { | ||||
| @@ -1396,11 +1376,6 @@ RED.nodes = (function() { | ||||
|                 nns.push(convertNode(groups[i], opts)); | ||||
|             } | ||||
|         } | ||||
|         for (i in junctions) { | ||||
|             if (junctions.hasOwnProperty(i)) { | ||||
|                 nns.push(convertNode(junctions[i], opts)); | ||||
|             } | ||||
|         } | ||||
|         for (i in configNodes) { | ||||
|             if (configNodes.hasOwnProperty(i)) { | ||||
|                 nns.push(convertNode(configNodes[i], opts)); | ||||
| @@ -1482,7 +1457,6 @@ RED.nodes = (function() { | ||||
|             tabs: {}, | ||||
|             subflows: {}, | ||||
|             groups: {}, | ||||
|             junctions: {}, | ||||
|             configs: {}, | ||||
|             nodes: {}, | ||||
|             all: [], | ||||
| @@ -1498,8 +1472,6 @@ RED.nodes = (function() { | ||||
|                 imported.subflows[n.id] = n; | ||||
|             } else if (n.type === "group") { | ||||
|                 imported.groups[n.id] = n; | ||||
|             } else if (n.type === "junction") { | ||||
|                 imported.junctions[n.id] = n; | ||||
|             } else if (n.hasOwnProperty("x") && n.hasOwnProperty("y")) { | ||||
|                 imported.nodes[n.id] = n; | ||||
|             } else { | ||||
| @@ -1508,7 +1480,7 @@ RED.nodes = (function() { | ||||
|             var nodeZ = n.z || "__global__"; | ||||
|             imported.zMap[nodeZ] = imported.zMap[nodeZ] || []; | ||||
|             imported.zMap[nodeZ].push(n) | ||||
|             if (allNodes.hasNode(n.id) || configNodes[n.id] || workspaces[n.id] || subflows[n.id] || groups[n.id] || junctions[n.id]) { | ||||
|             if (allNodes.hasNode(n.id) || configNodes[n.id] || workspaces[n.id] || subflows[n.id] || groups[n.id]) { | ||||
|                 imported.conflicted[n.id] = n; | ||||
|             } | ||||
|         }) | ||||
| @@ -1674,7 +1646,7 @@ RED.nodes = (function() { | ||||
|             if (!options.generateIds) { | ||||
|                 if (!options.importMap[id]) { | ||||
|                     // No conflict resolution for this node | ||||
|                     var existing = allNodes.getNode(id) || configNodes[id] || workspaces[id] || subflows[id] || groups[id] || junctions[id]; | ||||
|                     var existing = allNodes.getNode(id) || configNodes[id] || workspaces[id] || subflows[id] || groups[id]; | ||||
|                     if (existing) { | ||||
|                         existingNodes.push({existing:existing, imported:n}); | ||||
|                     } | ||||
| @@ -1728,7 +1700,6 @@ RED.nodes = (function() { | ||||
|                 n.type != "tab" && | ||||
|                 n.type != "subflow" && | ||||
|                 n.type != "group" && | ||||
|                 n.type != 'junction' && | ||||
|                 !registry.getNodeType(n.type) && | ||||
|                 n.type.substring(0,8) != "subflow:" && | ||||
|                 unknownTypes.indexOf(n.type)==-1) { | ||||
| @@ -1801,7 +1772,6 @@ RED.nodes = (function() { | ||||
|         var new_nodes = []; | ||||
|         var new_links = []; | ||||
|         var new_groups = []; | ||||
|         var new_junctions = []; | ||||
|         var new_group_set = new Set(); | ||||
|         var nid; | ||||
|         var def; | ||||
| @@ -1993,15 +1963,12 @@ RED.nodes = (function() { | ||||
|                         changed:false, | ||||
|                         _config:{} | ||||
|                     } | ||||
|                     if (n.type !== "group" && n.type !== 'junction') { | ||||
|                     if (n.type !== "group") { | ||||
|                         node.wires = n.wires||[]; | ||||
|                         node.inputLabels = n.inputLabels; | ||||
|                         node.outputLabels = n.outputLabels; | ||||
|                         node.icon = n.icon; | ||||
|                     } | ||||
|                     if (n.type === 'junction') { | ||||
|                         node.wires = n.wires||[]; | ||||
|                     } | ||||
|                     if (n.hasOwnProperty('l')) { | ||||
|                         node.l = n.l; | ||||
|                     } | ||||
| @@ -2070,15 +2037,6 @@ RED.nodes = (function() { | ||||
|                         node.outputs = subflow.out.length; | ||||
|                         node.inputs = subflow.in.length; | ||||
|                         node.env = n.env; | ||||
|                     } else if (n.type === 'junction') { | ||||
|                          node._def = {defaults:{}} | ||||
|                          node._config.x = node.x | ||||
|                          node._config.y = node.y | ||||
|                          node.inputs = 1 | ||||
|                          node.outputs = 1 | ||||
|                          node.w = 0; | ||||
|                          node.h = 0; | ||||
|  | ||||
|                     } else { | ||||
|                         if (!node._def) { | ||||
|                             if (node.x && node.y) { | ||||
| @@ -2162,9 +2120,7 @@ RED.nodes = (function() { | ||||
|                     node_map[n.id] = node; | ||||
|                     // If an 'unknown' config node, it will not have been caught by the | ||||
|                     // proper config node handling, so needs adding to new_nodes here | ||||
|                     if (node.type === 'junction') { | ||||
|                         new_junctions.push(node) | ||||
|                     } else if (node.type === "unknown" || node._def.category !== "config") { | ||||
|                     if (node.type === "unknown" || node._def.category !== "config") { | ||||
|                         new_nodes.push(node); | ||||
|                     } else if (node.type === "group") { | ||||
|                         new_groups.push(node); | ||||
| @@ -2175,12 +2131,8 @@ RED.nodes = (function() { | ||||
|         } | ||||
|  | ||||
|         // Remap all wires and config node references | ||||
|         for (i=0;i<new_nodes.length+new_junctions.length;i++) { | ||||
|             if (i<new_nodes.length) { | ||||
|                 n = new_nodes[i]; | ||||
|             } else { | ||||
|                 n = new_junctions[i - new_nodes.length] | ||||
|             } | ||||
|         for (i=0;i<new_nodes.length;i++) { | ||||
|             n = new_nodes[i]; | ||||
|             if (n.wires) { | ||||
|                 for (var w1=0;w1<n.wires.length;w1++) { | ||||
|                     var wires = (Array.isArray(n.wires[w1]))?n.wires[w1]:[n.wires[w1]]; | ||||
| @@ -2319,12 +2271,6 @@ RED.nodes = (function() { | ||||
|             addGroup(n); | ||||
|         } | ||||
|  | ||||
|         for (i=0;i<new_junctions.length;i++) { | ||||
|             var junction = new_junctions[i]; | ||||
|             addJunction(junction); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // Now the nodes have been fully updated, add them. | ||||
|         for (i=0;i<new_nodes.length;i++) { | ||||
|             var node = new_nodes[i]; | ||||
| @@ -2355,7 +2301,6 @@ RED.nodes = (function() { | ||||
|             nodes:new_nodes, | ||||
|             links:new_links, | ||||
|             groups:new_groups, | ||||
|             junctions: new_junctions, | ||||
|             workspaces:new_workspaces, | ||||
|             subflows:new_subflows, | ||||
|             missingWorkspace: missingWorkspace, | ||||
| @@ -2462,8 +2407,6 @@ RED.nodes = (function() { | ||||
|         workspacesOrder = []; | ||||
|         groups = {}; | ||||
|         groupsByZ = {}; | ||||
|         junctions = {}; | ||||
|         junctionsByZ = {}; | ||||
|  | ||||
|         var subflowIds = Object.keys(subflows); | ||||
|         subflowIds.forEach(function(id) { | ||||
| @@ -2513,30 +2456,6 @@ RED.nodes = (function() { | ||||
|         RED.events.emit("groups:remove",group); | ||||
|     } | ||||
|  | ||||
|     function addJunction(junction) { | ||||
|         junctionsByZ[junction.z] = junctionsByZ[junction.z] || [] | ||||
|         junctionsByZ[junction.z].push(junction) | ||||
|         junctions[junction.id] = junction; | ||||
|         if (!nodeLinks[junction.id]) { | ||||
|             nodeLinks[junction.id] = {in:[],out:[]}; | ||||
|         } | ||||
|         RED.events.emit("junctions:add", junction) | ||||
|     } | ||||
|     function removeJunction(junction) { | ||||
|         var i = junctionsByZ[junction.z].indexOf(junction) | ||||
|         junctionsByZ[junction.z].splice(i, 1) | ||||
|         if (junctionsByZ[junction.z].length === 0) { | ||||
|             delete junctionsByZ[junction.z] | ||||
|         } | ||||
|         delete junctions[junction.id] | ||||
|         delete nodeLinks[junction.id]; | ||||
|         RED.events.emit("junctions:remove", junction) | ||||
|  | ||||
|         var removedLinks = links.filter(function(l) { return (l.source === junction) || (l.target === junction); }); | ||||
|         removedLinks.forEach(removeLink); | ||||
|         return { links: removedLinks } | ||||
|     } | ||||
|  | ||||
|     function getNodeHelp(type) { | ||||
|         var helpContent = ""; | ||||
|         var helpElement = $("script[data-help-name='"+type+"']"); | ||||
| @@ -2765,6 +2684,7 @@ RED.nodes = (function() { | ||||
|         getType: registry.getNodeType, | ||||
|         getNodeHelp: getNodeHelp, | ||||
|         convertNode: convertNode, | ||||
|  | ||||
|         add: addNode, | ||||
|         remove: removeNode, | ||||
|         clear: clear, | ||||
| @@ -2810,11 +2730,6 @@ RED.nodes = (function() { | ||||
|         group: function(id) { return groups[id] }, | ||||
|         groups: function(z) { return groupsByZ[z]?groupsByZ[z].slice():[] }, | ||||
|  | ||||
|         addJunction: addJunction, | ||||
|         removeJunction: removeJunction, | ||||
|         junction: function(id) { return junctions[id] }, | ||||
|         junctions: function(z) { return junctionsByZ[z]?junctionsByZ[z].slice():[] }, | ||||
|  | ||||
|         eachNode: function(cb) { | ||||
|             allNodes.eachNode(cb); | ||||
|         }, | ||||
|   | ||||
| @@ -358,14 +358,6 @@ var RED = (function() { | ||||
|                         } else { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
|                                     text: RED._("notification.label.unknownNodesButton"), | ||||
|                                     class: "pull-left", | ||||
|                                     click: function() { | ||||
|                                         RED.actions.invoke("core:search", "type:unknown "); | ||||
|                                     } | ||||
|                                 }, | ||||
|                                 { | ||||
|                                     class: "primary", | ||||
|                                     text: RED._("common.label.close"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
| @@ -623,10 +615,7 @@ var RED = (function() { | ||||
|             null, | ||||
|             {id: "menu-item-edit-select-all", label:RED._("keyboard.selectAll"), onselect: "core:select-all-nodes"}, | ||||
|             {id: "menu-item-edit-select-connected", label:RED._("keyboard.selectAllConnected"), onselect: "core:select-connected-nodes"}, | ||||
|             {id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"}, | ||||
|             null, | ||||
|             {id: "menu-item-edit-split-wire-with-links", label:RED._("keyboard.splitWireWithLinks"), onselect: "core:split-wire-with-link-nodes"}, | ||||
|  | ||||
|             {id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"} | ||||
|         ]}); | ||||
|  | ||||
|         menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[ | ||||
| @@ -738,7 +727,6 @@ var RED = (function() { | ||||
|         RED.search.init(); | ||||
|         RED.actionList.init(); | ||||
|         RED.editor.init(); | ||||
|         RED.diagnostics.init(); | ||||
|         RED.diff.init(); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -987,7 +987,6 @@ RED.clipboard = (function() { | ||||
|         try { | ||||
|             RED.view.importNodes(newNodes, importOptions); | ||||
|         } catch(error) { | ||||
|             console.log(error.importConfig) | ||||
|             // Thrown for import_conflict | ||||
|             confirmImport(error.importConfig, newNodes, importOptions); | ||||
|         } | ||||
|   | ||||
| @@ -9,14 +9,12 @@ | ||||
|  * | ||||
|  * options: | ||||
|  * | ||||
|  *  search:    function(value, [done]) | ||||
|  *             A function that is passed the current contents of the input whenever | ||||
|  *             it changes. | ||||
|  *             The function must either return auto-complete options, or pass them | ||||
|  *             to the optional 'done' parameter. | ||||
|  *             If the function signature includes 'done', it must be used | ||||
|  *  minLength: number | ||||
|  *             If `minLength` is 0, pressing down arrow will show the list | ||||
|  *  search : function(value, [done]) | ||||
|  *           A function that is passed the current contents of the input whenever | ||||
|  *           it changes. | ||||
|  *           The function must either return auto-complete options, or pass them | ||||
|  *           to the optional 'done' parameter. | ||||
|  *           If the function signature includes 'done', it must be used | ||||
|  * | ||||
|  * The auto-complete options should be an array of objects in the form: | ||||
|  *  { | ||||
| @@ -28,11 +26,10 @@ | ||||
|  | ||||
|     $.widget( "nodered.autoComplete", { | ||||
|         _create: function() { | ||||
|             const that = this; | ||||
|             var that = this; | ||||
|             this.completionMenuShown = false; | ||||
|             this.options.minLength = parseInteger(this.options.minLength, 1, 0); | ||||
|             this.options.search = this.options.search || function() { return [] }; | ||||
|             this.element.addClass("red-ui-autoComplete"); | ||||
|             this.options.search = this.options.search || function() { return [] } | ||||
|             this.element.addClass("red-ui-autoComplete") | ||||
|             this.element.on("keydown.red-ui-autoComplete", function(evt) { | ||||
|                 if ((evt.keyCode === 13 || evt.keyCode === 9) && that.completionMenuShown) { | ||||
|                     var opts = that.menu.options(); | ||||
| @@ -74,8 +71,8 @@ | ||||
|             this.completionMenuShown = true; | ||||
|         }, | ||||
|         _updateCompletions: function(val) { | ||||
|             const that = this; | ||||
|             if (val.trim().length < this.options.minLength) { | ||||
|             var that = this; | ||||
|             if (val.trim() === "") { | ||||
|                 if (this.completionMenuShown) { | ||||
|                     this.menu.hide(); | ||||
|                 } | ||||
| @@ -99,7 +96,7 @@ | ||||
|                 } | ||||
|             } | ||||
|             if (this.options.search.length === 2) { | ||||
|                 const requestId = 1+Math.floor(Math.random()*10000); | ||||
|                 var requestId = 1+Math.floor(Math.random()*10000); | ||||
|                 this.pendingRequest = requestId; | ||||
|                 this.options.search(val,function(completions) { displayResults(completions,requestId);}) | ||||
|             } else { | ||||
| @@ -115,12 +112,4 @@ | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|     function parseInteger(input, def, min, max) { | ||||
|         if(input == null) { return (def || 0); } | ||||
|         min = min == null ? Number.NEGATIVE_INFINITY : min;  | ||||
|         max = max == null ? Number.POSITIVE_INFINITY : max;  | ||||
|         let n = parseInt(input); | ||||
|         if(isNaN(n) || n < min || n > max) { n = def || 0; } | ||||
|         return n; | ||||
|     } | ||||
| })(jQuery); | ||||
|   | ||||
| @@ -359,7 +359,6 @@ RED.popover = (function() { | ||||
|                 setTimeout(closePopup,delay.hide); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         if (trigger === 'hover') { | ||||
|             target.on('mouseenter',function(e) { | ||||
|                 clearTimeout(timer); | ||||
| @@ -471,11 +470,6 @@ RED.popover = (function() { | ||||
|             popover.setAction = function(newAction) { | ||||
|                 action = newAction; | ||||
|             } | ||||
|             popover.delete = function() { | ||||
|                 popover.close(true) | ||||
|                 target.off("mouseenter"); | ||||
|                 target.off("mouseleave"); | ||||
|             }; | ||||
|             return popover; | ||||
|  | ||||
|         }, | ||||
|   | ||||
| @@ -105,8 +105,8 @@ | ||||
|                     } | ||||
|                 }); | ||||
|                 this.element.on("keydown",function(e) { | ||||
|                     if (!menuShown && e.keyCode === 40 && $(this).val() === '') { | ||||
|                         //DOWN (only show menu if search field is emty) | ||||
|                     if (!menuShown && e.keyCode === 40) { | ||||
|                         //DOWN | ||||
|                         showMenu(); | ||||
|                     } | ||||
|                 }); | ||||
|   | ||||
| @@ -670,7 +670,7 @@ RED.tabs = (function() { | ||||
|                 } | ||||
|                 var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li); | ||||
|                 if (tab.icon) { | ||||
|                     $('<i>',{class:"red-ui-tab-icon", style:"mask-image: url("+tab.icon+"); -webkit-mask-image: url("+tab.icon+");"}).appendTo(link); | ||||
|                     $('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link); | ||||
|                 } else if (tab.iconClass) { | ||||
|                     $('<i>',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link); | ||||
|                 } | ||||
| @@ -828,7 +828,7 @@ RED.tabs = (function() { | ||||
|                 } | ||||
|  | ||||
|                 // link.attr("title",tab.label); | ||||
|                 RED.popover.tooltip(link,function() { return tab.label}) | ||||
|                 RED.popover.tooltip(link,function() { return RED.utils.sanitize(tab.label); }); | ||||
|  | ||||
|                 if (options.onadd) { | ||||
|                     options.onadd(tab); | ||||
|   | ||||
| @@ -55,46 +55,34 @@ | ||||
|     } | ||||
|  | ||||
|     var autoComplete = function(options) { | ||||
|         function getMatch(value, searchValue) { | ||||
|             const idx = value.toLowerCase().indexOf(searchValue.toLowerCase()); | ||||
|             const len = idx > -1 ? searchValue.length : 0; | ||||
|             return { | ||||
|                 index: idx, | ||||
|                 found: idx > -1, | ||||
|                 pre: value.substring(0,idx), | ||||
|                 match: value.substring(idx,idx+len), | ||||
|                 post: value.substring(idx+len), | ||||
|             } | ||||
|         } | ||||
|         function generateSpans(match) { | ||||
|             const els = []; | ||||
|             if(match.pre) { els.push($('<span/>').text(match.pre)); } | ||||
|             if(match.match) { els.push($('<span/>',{style:"font-weight: bold; color: var(--red-ui-text-color-link);"}).text(match.match)); } | ||||
|             if(match.post) { els.push($('<span/>').text(match.post)); } | ||||
|             return els; | ||||
|         } | ||||
|         return function(val) { | ||||
|             var matches = []; | ||||
|             options.forEach(opt => { | ||||
|                 const optVal = opt.value; | ||||
|                 const optSrc = (opt.source||[]).join(","); | ||||
|                 const valMatch = getMatch(optVal, val); | ||||
|                 const srcMatch = getMatch(optSrc, val); | ||||
|                 if (valMatch.found || srcMatch.found) { | ||||
|                     const element = $('<div>',{style: "display: flex"}); | ||||
|                     const valEl = $('<div/>',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"}); | ||||
|                     valEl.append(generateSpans(valMatch)); | ||||
|                     valEl.appendTo(element); | ||||
|                     if (optSrc) { | ||||
|                         const optEl = $('<div>').css({ "font-size": "0.8em" }); | ||||
|                         optEl.append(generateSpans(srcMatch)); | ||||
|                         optEl.appendTo(element); | ||||
|                 let v = opt.value; | ||||
|                 var i = v.toLowerCase().indexOf(val.toLowerCase()); | ||||
|                 if (i > -1) { | ||||
|                     var pre = v.substring(0,i); | ||||
|                     var matchedVal = v.substring(i,i+val.length); | ||||
|                     var post = v.substring(i+val.length) | ||||
|  | ||||
|                     var el = $('<div/>',{style:"white-space:nowrap; overflow: hidden; flex-grow:1"}); | ||||
|                     $('<span/>').text(pre).appendTo(el); | ||||
|                     $('<span/>',{style:"font-weight: bold"}).text(matchedVal).appendTo(el); | ||||
|                     $('<span/>').text(post).appendTo(el); | ||||
|  | ||||
|                     var element = $('<div>',{style: "display: flex"}); | ||||
|                     el.appendTo(element); | ||||
|                     if (opt.source) { | ||||
|                         $('<div>').css({ | ||||
|                             "font-size": "0.8em" | ||||
|                         }).text(opt.source.join(",")).appendTo(element); | ||||
|                     } | ||||
|                     matches.push({  | ||||
|                         value: optVal,  | ||||
|                         label: element,  | ||||
|                         i: (valMatch.found ? valMatch.index : srcMatch.index)  | ||||
|                     }); | ||||
|  | ||||
|                     matches.push({ | ||||
|                         value: v, | ||||
|                         label: element, | ||||
|                         i:i | ||||
|                     }) | ||||
|                 } | ||||
|             }) | ||||
|             matches.sort(function(A,B){return A.i-B.i}) | ||||
| @@ -105,36 +93,6 @@ | ||||
|     // This is a hand-generated list of completions for the core nodes (based on the node help html). | ||||
|     var msgCompletions = [ | ||||
|         { value: "payload" }, | ||||
|         { value: "topic", source: ["mqtt","inject","rbe"] }, | ||||
|         { value: "action", source: ["mqtt"] }, | ||||
|         { value: "complete", source: ["join"] }, | ||||
|         { value: "contentType", source: ["mqtt"] }, | ||||
|         { value: "cookies", source: ["http request","http response"] }, | ||||
|         { value: "correlationData", source: ["mqtt"] }, | ||||
|         { value: "delay", source: ["delay","trigger"] }, | ||||
|         { value: "encoding", source: ["file"] }, | ||||
|         { value: "error", source: ["catch"] }, | ||||
|         { value: "error.message", source: ["catch"] }, | ||||
|         { value: "error.source", source: ["catch"] }, | ||||
|         { value: "error.source.id", source: ["catch"] }, | ||||
|         { value: "error.source.type", source: ["catch"] }, | ||||
|         { value: "error.source.name", source: ["catch"] }, | ||||
|         { value: "filename", source: ["file","file in"] }, | ||||
|         { value: "flush", source: ["delay"] }, | ||||
|         { value: "followRedirects", source: ["http request"] }, | ||||
|         { value: "headers", source: ["http response","http request"] }, | ||||
|         { value: "host", source: ["tcp request","http request"] }, | ||||
|         { value: "ip", source: ["udp out"] }, | ||||
|         { value: "kill", source: ["exec"] }, | ||||
|         { value: "messageExpiryInterval", source: ["mqtt"] }, | ||||
|         { value: "method", source: ["http request"] }, | ||||
|         { value: "options", source: ["xml"] }, | ||||
|         { value: "parts", source: ["split","join","batch","sort"] }, | ||||
|         { value: "pid", source: ["exec"] }, | ||||
|         { value: "port", source: ["tcp request"," udp out"] }, | ||||
|         { value: "qos", source: ["mqtt"] }, | ||||
|         { value: "rate", source: ["delay"] }, | ||||
|         { value: "rejectUnauthorized", source: ["http request"] }, | ||||
|         { value: "req", source: ["http in"]}, | ||||
|         { value: "req.body", source: ["http in"]}, | ||||
|         { value: "req.headers", source: ["http in"]}, | ||||
| @@ -142,28 +100,38 @@ | ||||
|         { value: "req.params", source: ["http in"]}, | ||||
|         { value: "req.cookies", source: ["http in"]}, | ||||
|         { value: "req.files", source: ["http in"]}, | ||||
|         { value: "complete", source: ["join"] }, | ||||
|         { value: "contentType", source: ["mqtt"] }, | ||||
|         { value: "cookies", source: ["http in","http request"] }, | ||||
|         { value: "correlationData", source: ["mqtt"] }, | ||||
|         { value: "delay", source: ["delay","trigger"] }, | ||||
|         { value: "encoding", source: ["file"] }, | ||||
|         { value: "error", source: ["catch"] }, | ||||
|         { value: "filename", source: ["file","file in"] }, | ||||
|         { value: "flush", source: ["delay"] }, | ||||
|         { value: "followRedirects", source: ["http request"] }, | ||||
|         { value: "headers", source: ["http in"," http request"] }, | ||||
|         { value: "kill", source: ["exec"] }, | ||||
|         { value: "messageExpiryInterval", source: ["mqtt"] }, | ||||
|         { value: "method", source: ["http-request"] }, | ||||
|         { value: "options", source: ["xml"] }, | ||||
|         { value: "parts", source: ["split","join"] }, | ||||
|         { value: "pid", source: ["exec"] }, | ||||
|         { value: "qos", source: ["mqtt"] }, | ||||
|         { value: "rate", source: ["delay"] }, | ||||
|         { value: "rejectUnauthorized", source: ["http request"] }, | ||||
|         { value: "requestTimeout", source: ["http request"] }, | ||||
|         { value: "reset", source: ["delay","trigger","join","rbe"] }, | ||||
|         { value: "responseCookies", source: ["http request"] }, | ||||
|         { value: "responseTopic", source: ["mqtt"] }, | ||||
|         { value: "responseURL", source: ["http request"] }, | ||||
|         { value: "restartTimeout", source: ["join"] }, | ||||
|         { value: "retain", source: ["mqtt"] }, | ||||
|         { value: "schema", source: ["json"] }, | ||||
|         { value: "select", source: ["html"] }, | ||||
|         { value: "statusCode", source: ["http response","http request"] }, | ||||
|         { value: "status", source: ["status"] }, | ||||
|         { value: "status.text", source: ["status"] }, | ||||
|         { value: "status.source", source: ["status"] }, | ||||
|         { value: "status.source.type", source: ["status"] }, | ||||
|         { value: "status.source.id", source: ["status"] }, | ||||
|         { value: "status.source.name", source: ["status"] }, | ||||
|         { value: "target", source: ["link call"] }, | ||||
|         { value: "statusCode", source: ["http in"] }, | ||||
|         { value: "template", source: ["template"] }, | ||||
|         { value: "toFront", source: ["delay"] }, | ||||
|         { value: "topic", source: ["inject","mqtt","rbe"] }, | ||||
|         { value: "url", source: ["http request"] }, | ||||
|         { value: "userProperties", source: ["mqtt"] }, | ||||
|         { value: "_session", source: ["websocket out","tcp out"] }, | ||||
|         { value: "userProperties", source: ["mqtt"] } | ||||
|     ] | ||||
|     var allOptions = { | ||||
|         msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)}, | ||||
| @@ -198,8 +166,6 @@ | ||||
|                 } | ||||
|                 RED.editor.editJSON({ | ||||
|                     value: value, | ||||
|                     stateId: RED.editor.generateViewStateId("typedInput", that, "json"), | ||||
|                     focus: true, | ||||
|                     complete: function(v) { | ||||
|                         var value = v; | ||||
|                         try { | ||||
| @@ -222,8 +188,6 @@ | ||||
|                 var that = this; | ||||
|                 RED.editor.editExpression({ | ||||
|                     value: this.value().replace(/\t/g,"\n"), | ||||
|                     stateId: RED.editor.generateViewStateId("typedInput", that, "jsonata"), | ||||
|                     focus: true, | ||||
|                     complete: function(v) { | ||||
|                         that.value(v.replace(/\n/g,"\t")); | ||||
|                     } | ||||
| @@ -238,8 +202,6 @@ | ||||
|                 var that = this; | ||||
|                 RED.editor.editBuffer({ | ||||
|                     value: this.value(), | ||||
|                     stateId: RED.editor.generateViewStateId("typedInput", that, "bin"), | ||||
|                     focus: true, | ||||
|                     complete: function(v) { | ||||
|                         that.value(v); | ||||
|                     } | ||||
| @@ -675,7 +637,7 @@ | ||||
|                     if (opt.icon.indexOf("<") === 0) { | ||||
|                         $(opt.icon).prependTo(op); | ||||
|                     } else if (opt.icon.indexOf("/") !== -1) { | ||||
|                         $('<i>',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+");"}).prependTo(op); | ||||
|                         $('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px; height: 18px;"}).prependTo(op); | ||||
|                     } else { | ||||
|                         $('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op); | ||||
|                     } | ||||
| @@ -1026,7 +988,10 @@ | ||||
|                             $(opt.icon).prependTo(this.selectLabel); | ||||
|                         } | ||||
|                         else if (opt.icon.indexOf("/") !== -1) { | ||||
|                             $('<i>',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+"); margin-right: 4px;height: 18px;width:13px"}).prependTo(this.selectLabel); | ||||
|                             image = new Image(); | ||||
|                             image.name = opt.icon; | ||||
|                             image.src = mapDeprecatedIcon(opt.icon); | ||||
|                             $('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel); | ||||
|                         } | ||||
|                         else { | ||||
|                             $('<i>',{class:"red-ui-typedInput-icon "+opt.icon,style:"min-width: 13px; margin-right: 4px;"}).prependTo(this.selectLabel); | ||||
| @@ -1182,8 +1147,7 @@ | ||||
|                             this.elementDiv.show(); | ||||
|                             if (opt.autoComplete) { | ||||
|                                 this.input.autoComplete({ | ||||
|                                     search: opt.autoComplete, | ||||
|                                     minLength: 0 | ||||
|                                     search: opt.autoComplete | ||||
|                                 }) | ||||
|                             } | ||||
|                         } | ||||
|   | ||||
| @@ -383,14 +383,6 @@ RED.deploy = (function() { | ||||
|                     "</p>"; | ||||
|  | ||||
|                 notificationButtons = [ | ||||
|                     { | ||||
|                         text: RED._("deploy.unknownNodesButton"), | ||||
|                         class: "pull-left", | ||||
|                         click: function() { | ||||
|                             notification.close(); | ||||
|                             RED.actions.invoke("core:search","type:unknown "); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         id: "red-ui-deploy-dialog-confirm-deploy-deploy", | ||||
|                         text: RED._("deploy.confirm.button.confirm"), | ||||
| @@ -410,14 +402,6 @@ RED.deploy = (function() { | ||||
|                     RED._('deploy.confirm.confirm') + | ||||
|                     "</p>"; | ||||
|                 notificationButtons = [ | ||||
|                     { | ||||
|                         text: RED._("deploy.invalidNodesButton"), | ||||
|                         class: "pull-left", | ||||
|                         click: function() { | ||||
|                             notification.close(); | ||||
|                             RED.actions.invoke("core:search","is:invalid "); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         id: "red-ui-deploy-dialog-confirm-deploy-deploy", | ||||
|                         text: RED._("deploy.confirm.button.confirm"), | ||||
| @@ -478,33 +462,9 @@ RED.deploy = (function() { | ||||
|             RED.nodes.version(data.rev); | ||||
|             RED.nodes.originalFlow(nns); | ||||
|             if (hasUnusedConfig) { | ||||
|                 let notification; | ||||
|                 const opts = { | ||||
|                     type: "success", | ||||
|                     fixed: false, | ||||
|                     timeout: 6000, | ||||
|                     buttons: [ | ||||
|                         { | ||||
|                             text: RED._("deploy.unusedConfigNodesButton"), | ||||
|                             class: "pull-left", | ||||
|                             click: function() { | ||||
|                                 notification.close(); | ||||
|                                 RED.actions.invoke("core:search","is:config is:unused "); | ||||
|                             } | ||||
|                         }, | ||||
|                         { | ||||
|                             text: RED._("common.label.close"), | ||||
|                             class: "primary", | ||||
|                             click: function () { | ||||
|                                 save(true); | ||||
|                                 notification.close(); | ||||
|                             } | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|                 notification = RED.notify( | ||||
|                 RED.notify( | ||||
|                     '<p>' + RED._("deploy.successfulDeploy") + '</p>' + | ||||
|                     '<p>' + RED._("deploy.unusedConfigNodes") + '</p>', opts); | ||||
|                     '<p>' + RED._("deploy.unusedConfigNodes") + ' <a href="#" onclick="RED.sidebar.config.show(true); return false;">' + RED._("deploy.unusedConfigNodesLink") + '</a></p>', "success", false, 6000); | ||||
|             } else { | ||||
|                 RED.notify('<p>' + RED._("deploy.successfulDeploy") + '</p>', "success"); | ||||
|             } | ||||
|   | ||||
| @@ -1,61 +0,0 @@ | ||||
|  | ||||
| RED.diagnostics = (function () { | ||||
|  | ||||
|     function init() { | ||||
|         if (RED.settings.get('diagnostics.ui', true) === false) { | ||||
|             return; | ||||
|         } | ||||
|         RED.actions.add("core:show-system-info", function () { show(); }); | ||||
|     } | ||||
|  | ||||
|     function show() { | ||||
|         $.ajax({ | ||||
|             headers: { | ||||
|                 "Accept": "application/json" | ||||
|             }, | ||||
|             cache: false, | ||||
|             url: 'diagnostics', | ||||
|             success: function (data) { | ||||
|                 var json = JSON.stringify(data || {}, "", 4); | ||||
|                 if (json === "{}") { | ||||
|                     json = "{\n\n}"; | ||||
|                 } | ||||
|                 RED.editor.editJSON({ | ||||
|                     title: RED._('diagnostics.title'), | ||||
|                     value: json, | ||||
|                     requireValid: true, | ||||
|                     readOnly: true, | ||||
|                     toolbarButtons: [ | ||||
|                         { | ||||
|                             text: RED._('clipboard.export.copy'), | ||||
|                             icon: 'fa fa-copy', | ||||
|                             click: function () { | ||||
|                                 RED.clipboard.copyText(json, $(this), RED._('clipboard.copyMessageValue')) | ||||
|                             } | ||||
|                         }, | ||||
|                         { | ||||
|                             text: RED._('clipboard.download'), | ||||
|                             icon: 'fa fa-download', | ||||
|                             click: function () { | ||||
|                                 var element = document.createElement('a'); | ||||
|                                 element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json)); | ||||
|                                 element.setAttribute('download', "system-info.json"); | ||||
|                                 element.style.display = 'none'; | ||||
|                                 document.body.appendChild(element); | ||||
|                                 element.click(); | ||||
|                                 document.body.removeChild(element); | ||||
|                             } | ||||
|                         }, | ||||
|                     ] | ||||
|                 }); | ||||
|             }, | ||||
|             error: function (jqXHR, textStatus, errorThrown) { | ||||
|                 console.log("Unexpected error loading system info:", jqXHR.status, textStatus, errorThrown); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         init: init, | ||||
|     }; | ||||
| })(); | ||||
| @@ -110,11 +110,7 @@ RED.editor = (function() { | ||||
|         var result = []; | ||||
|         for (var prop in definition) { | ||||
|             if (definition.hasOwnProperty(prop)) { | ||||
|                 var valid = validateNodeProperty(node, definition, prop, properties[prop]); | ||||
|                 if ((typeof valid) === "string") { | ||||
|                     result.push(valid); | ||||
|                 } | ||||
|                 else if(!valid) { | ||||
|                 if (!validateNodeProperty(node, definition, prop, properties[prop])) { | ||||
|                     result.push(prop); | ||||
|                 } | ||||
|             } | ||||
| @@ -128,7 +124,7 @@ RED.editor = (function() { | ||||
|      * @param definition - the node property definitions (either def.defaults or def.creds) | ||||
|      * @param property - the property name being validated | ||||
|      * @param value - the property value being validated | ||||
|      * @returns {boolean|string} whether the node proprty is valid. `true`: valid `false|String`: invalid | ||||
|      * @returns {boolean} whether the node proprty is valid | ||||
|      */ | ||||
|     function validateNodeProperty(node,definition,property,value) { | ||||
|         var valid = true; | ||||
| @@ -140,74 +136,22 @@ RED.editor = (function() { | ||||
|         if (/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/.test(value)) { | ||||
|             return true; | ||||
|         } | ||||
|         var label = null; | ||||
|         if (("label" in definition[property]) && | ||||
|             ((typeof definition[property].label) == "string")) { | ||||
|             label = definition[property].label; | ||||
|         } | ||||
|         if ("required" in definition[property] && definition[property].required) { | ||||
|             valid = value !== ""; | ||||
|             if (!valid && label) { | ||||
|                 return RED._("validator.errors.missing-required-prop", { | ||||
|                     prop: label | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         if (valid && "validate" in definition[property]) { | ||||
|             try { | ||||
|                 var opt = {}; | ||||
|                 if (label) { | ||||
|                     opt.label = label; | ||||
|                 } | ||||
|                 valid = definition[property].validate.call(node,value, opt); | ||||
|                 // If the validator takes two arguments, it is a 3.x validator that | ||||
|                 // can return a String to mean 'invalid' and provide a reason | ||||
|                 if ((definition[property].validate.length === 2) && | ||||
|                     ((typeof valid) === "string")) { | ||||
|                     return valid; | ||||
|                 } else { | ||||
|                     // Otherwise, a 2.x returns a truth-like/false-like value that | ||||
|                     // we should cooerce to a boolean. | ||||
|                     valid = !!valid | ||||
|                 } | ||||
|                 valid = definition[property].validate.call(node,value); | ||||
|             } catch(err) { | ||||
|                 console.log("Validation error:",node.type,node.id,"property: "+property,"value:",value,err); | ||||
|                 return RED._("validator.errors.validation-error", { | ||||
|                     prop: property, | ||||
|                     node: node.type, | ||||
|                     id: node.id, | ||||
|                     error: err.message | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         if (valid && definition[property].type && RED.nodes.getType(definition[property].type) && !("validate" in definition[property])) { | ||||
|             if (!value || value == "_ADD_") { | ||||
|                 valid = definition[property].hasOwnProperty("required") && !definition[property].required; | ||||
|                 if (!valid && label) { | ||||
|                     return RED._("validator.errors.missing-required-prop", { | ||||
|                         prop: label | ||||
|                     }); | ||||
|                 } | ||||
|             } else { | ||||
|                 var configNode = RED.nodes.node(value); | ||||
|                 if (configNode) { | ||||
|                     if ((configNode.valid == null) || configNode.valid) { | ||||
|                         return true; | ||||
|                     } | ||||
|                     if (label) { | ||||
|                         return RED._("validator.errors.invalid-config", { | ||||
|                             prop: label | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 else { | ||||
|                     if (label) { | ||||
|                         return RED._("validator.errors.missing-config", { | ||||
|                             prop: label | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 return false; | ||||
|                 valid = (configNode && (configNode.valid == null || configNode.valid)); | ||||
|             } | ||||
|         } | ||||
|         return valid; | ||||
| @@ -235,26 +179,10 @@ RED.editor = (function() { | ||||
|             if (defaults[property].hasOwnProperty("format") && defaults[property].format !== "" && input[0].nodeName === "DIV") { | ||||
|                 value = input.text(); | ||||
|             } | ||||
|             var valid = validateNodeProperty(node, defaults, property,value); | ||||
|             if (((typeof valid) === "string") || !valid) { | ||||
|             if (!validateNodeProperty(node, defaults, property,value)) { | ||||
|                 input.addClass("input-error"); | ||||
|                 if ((typeof valid) === "string") { | ||||
|                     var tooltip = input.data("tooltip"); | ||||
|                     if (tooltip) { | ||||
|                         tooltip.setContent(valid); | ||||
|                     } | ||||
|                     else { | ||||
|                         tooltip = RED.popover.tooltip(input, valid); | ||||
|                         input.data("tooltip", tooltip); | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 input.removeClass("input-error"); | ||||
|                 var tooltip = input.data("tooltip"); | ||||
|                 if (tooltip) { | ||||
|                     input.data("tooltip", null); | ||||
|                     tooltip.delete(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -421,11 +349,20 @@ RED.editor = (function() { | ||||
|      * @param prefix - the prefix to use in the input element ids (node-input|node-config-input) | ||||
|      */ | ||||
|     function attachPropertyChangeHandler(node,definition,property,prefix) { | ||||
|         $("#"+prefix+"-"+property).on("change keyup paste", function(event) { | ||||
|             if (!$(this).attr("skipValidation")) { | ||||
|                 validateNodeEditor(node,prefix); | ||||
|             } | ||||
|         }); | ||||
|         var input = $("#"+prefix+"-"+property); | ||||
|         if (definition !== undefined && "format" in definition[property] && definition[property].format !== "" && input[0].nodeName === "DIV") { | ||||
|             $("#"+prefix+"-"+property).on('change keyup', function(event) { | ||||
|                 if (!$(this).attr("skipValidation")) { | ||||
|                     validateNodeEditor(node,prefix); | ||||
|                 } | ||||
|             }); | ||||
|         } else { | ||||
|             $("#"+prefix+"-"+property).on("change", function(event) { | ||||
|                 if (!$(this).attr("skipValidation")) { | ||||
|                     validateNodeEditor(node,prefix); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -859,7 +796,6 @@ RED.editor = (function() { | ||||
|         if (buildingEditDialog) { return } | ||||
|         buildingEditDialog = true; | ||||
|         var editing_node = node; | ||||
|         var removeInfoEditorOnClose = false; | ||||
|         var skipInfoRefreshOnClose = false; | ||||
|         var activeEditPanes = []; | ||||
|  | ||||
| @@ -1055,14 +991,6 @@ RED.editor = (function() { | ||||
|                 } | ||||
|                 if (!node._def.defaults || !node._def.defaults.hasOwnProperty('info'))  { | ||||
|                     nodeEditPanes.push('editor-tab-description'); | ||||
|                     removeInfoEditorOnClose = true; | ||||
|                     if(node.infoEditor) { | ||||
|                         //As 'editor-tab-description' adds `node.infoEditor` store original & set a | ||||
|                         //flag to NOT remove this property | ||||
|                         node.infoEditor__orig = node.infoEditor; | ||||
|                         delete node.infoEditor; | ||||
|                         removeInfoEditorOnClose = false; | ||||
|                     } | ||||
|                 } | ||||
|                 nodeEditPanes.push("editor-tab-appearance"); | ||||
|  | ||||
| @@ -1078,17 +1006,8 @@ RED.editor = (function() { | ||||
|                 if (RED.view.state() != RED.state.IMPORT_DRAGGING) { | ||||
|                     RED.view.state(RED.state.DEFAULT); | ||||
|                 } | ||||
|                 if (editing_node) { | ||||
|                     if (editing_node.infoEditor__orig) { | ||||
|                         editing_node.infoEditor = editing_node.infoEditor__orig; | ||||
|                         delete editing_node.infoEditor__orig; | ||||
|                     } | ||||
|                     if (removeInfoEditorOnClose) { | ||||
|                         delete editing_node.infoEditor; | ||||
|                     } | ||||
|                     if (!skipInfoRefreshOnClose) { | ||||
|                         RED.sidebar.info.refresh(editing_node); | ||||
|                     } | ||||
|                 if (editing_node && !skipInfoRefreshOnClose) { | ||||
|                     RED.sidebar.info.refresh(editing_node); | ||||
|                 } | ||||
|                 RED.workspaces.refresh(); | ||||
|  | ||||
| @@ -1948,48 +1867,6 @@ RED.editor = (function() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** Genrate a consistent but unique ID for saving and restoring the code editors view state */ | ||||
|     function generateViewStateId(source, thing, suffix) { | ||||
|         try { | ||||
|             thing = thing || {}; | ||||
|             const thingOptions = typeof thing.options === "object" ? thing.options : {}; | ||||
|             let stateId; | ||||
|             if (thing.hasOwnProperty("stateId")) { | ||||
|                 stateId = thing.stateId | ||||
|             } else if (thingOptions.hasOwnProperty("stateId")) { | ||||
|                 stateId = thing.stateId | ||||
|             } | ||||
|             if (stateId === false) { return false; } | ||||
|             if (!stateId) { | ||||
|                 let id; | ||||
|                 const selection = RED.view.selection(); | ||||
|                 if (source === "node" && thing.id) { | ||||
|                     id = thing.id; | ||||
|                 } else if (selection.nodes && selection.nodes.length) { | ||||
|                     id = selection.nodes[0].id; | ||||
|                 } else { | ||||
|                     return false; //cant obtain Id. | ||||
|                 } | ||||
|                 //Use a string builder to build an ID | ||||
|                 const sb = [id]; | ||||
|                 //get the index of the el - there may be more than one editor. | ||||
|                 const el = $(thing.element || thingOptions.element); | ||||
|                 if(el.length) { | ||||
|                     sb.push(el.closest(".form-row").index()); | ||||
|                     sb.push(el.index()); | ||||
|                 } | ||||
|                 if (source == "typedInput") { | ||||
|                     sb.push(el.closest("li").index());//for when embeded in editable list | ||||
|                     if (!suffix && thing.propertyType) { suffix = thing.propertyType } | ||||
|                 } | ||||
|                 stateId = sb.join("/"); | ||||
|             } | ||||
|             if (stateId && suffix) { stateId += "/" + suffix; } | ||||
|             return stateId; | ||||
|         } catch (error) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     return { | ||||
|         init: function() { | ||||
|             if(window.ace) { window.ace.config.set('basePath', 'vendor/ace'); } | ||||
| @@ -2006,7 +1883,6 @@ RED.editor = (function() { | ||||
|             }); | ||||
|             RED.editor.codeEditor.init(); | ||||
|         }, | ||||
|         generateViewStateId: generateViewStateId, | ||||
|         edit: showEditDialog, | ||||
|         editConfig: showEditConfigNodeDialog, | ||||
|         editFlow: showEditFlowDialog, | ||||
|   | ||||
| @@ -47,7 +47,6 @@ | ||||
|     var definition = { | ||||
|         show: function(options) { | ||||
|             var value = options.value; | ||||
|             var onCancel = options.cancel; | ||||
|             var onComplete = options.complete; | ||||
|             var type = "_buffer" | ||||
|             if ($("script[data-template-name='"+type+"']").length === 0) { | ||||
| @@ -61,14 +60,12 @@ | ||||
|  | ||||
|             var trayOptions = { | ||||
|                 title: options.title, | ||||
|                 focusElement: options.focusElement, | ||||
|                 width: "inherit", | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "node-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             if (onCancel) { onCancel(); } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     }, | ||||
| @@ -77,8 +74,7 @@ | ||||
|                         text: RED._("common.label.done"), | ||||
|                         class: "primary", | ||||
|                         click: function() { | ||||
|                             bufferStringEditor.saveView(); | ||||
|                             if (onComplete) { onComplete(JSON.stringify(bufferBinValue),null,bufferStringEditor); } | ||||
|                             onComplete(JSON.stringify(bufferBinValue)); | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     } | ||||
| @@ -90,20 +86,19 @@ | ||||
|                     } | ||||
|                 }, | ||||
|                 open: function(tray) { | ||||
|                     var trayBody = tray.find('.red-ui-tray-body'); | ||||
|                     var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); | ||||
|  | ||||
|                     bufferStringEditor = RED.editor.createEditor({ | ||||
|                         id: 'red-ui-editor-type-buffer-str', | ||||
|                         value: value||"", | ||||
|                         stateId: RED.editor.generateViewStateId("buffer", options, ""), | ||||
|                         focus: true, | ||||
|                         value: "", | ||||
|                         mode:"ace/mode/text" | ||||
|                     }); | ||||
|                     bufferStringEditor.getSession().setValue(value||"",-1); | ||||
|  | ||||
|                     bufferBinEditor = RED.editor.createEditor({ | ||||
|                         id: 'red-ui-editor-type-buffer-bin', | ||||
|                         value: "", | ||||
|                         stateId: false, | ||||
|                         focus: false, | ||||
|                         mode:"ace/mode/text", | ||||
|                         readOnly: true | ||||
|                     }); | ||||
|   | ||||
| @@ -80,9 +80,6 @@ RED.editor.codeEditor.ace = (function() { | ||||
|                 } | ||||
|             },100); | ||||
|         } | ||||
|         if (!options.stateId && options.stateId !== false) { | ||||
|             options.stateId = RED.editor.generateViewStateId("ace", options, (options.mode || options.title).split("/").pop()); | ||||
|         } | ||||
|         if (options.mode === 'ace/mode/markdown') { | ||||
|             $(el).addClass("red-ui-editor-text-container-toolbar"); | ||||
|             editor.toolbar = RED.editor.customEditTypes['_markdown'].buildToolbar(toolbarRow,editor); | ||||
| @@ -95,15 +92,11 @@ RED.editor.codeEditor.ace = (function() { | ||||
|                     RED.editor.editMarkdown({ | ||||
|                         value: value, | ||||
|                         width: "Infinity", | ||||
|                         stateId: options.stateId, | ||||
|                         focus: true, | ||||
|                         cancel: function () { | ||||
|                             editor.focus(); | ||||
|                         }, | ||||
|                         cursor: editor.getCursorPosition(), | ||||
|                         complete: function(v,cursor) { | ||||
|                             editor.setValue(v, -1); | ||||
|                             editor.gotoLine(cursor.row+1,cursor.column,false); | ||||
|                             setTimeout(function() { | ||||
|                                 editor.restoreView(); | ||||
|                                 editor.focus(); | ||||
|                             },300); | ||||
|                         } | ||||
| @@ -124,56 +117,11 @@ RED.editor.codeEditor.ace = (function() { | ||||
|         editor._destroy = editor.destroy; | ||||
|         editor.destroy = function() { | ||||
|             try { | ||||
|                 editor.saveView(); | ||||
|                 editor._initState = null; | ||||
|                 this._destroy(); | ||||
|             } catch (e) { } | ||||
|             $(el).remove(); | ||||
|             $(toolbarRow).remove(); | ||||
|         } | ||||
|         editor.on("blur", function () { | ||||
|             editor.focusMemory = false; | ||||
|             editor.saveView(); | ||||
|         }) | ||||
|         editor.on("focus", function () { | ||||
|             if (editor._initState) { | ||||
|                 editor.restoreView(editor._initState); | ||||
|                 editor._initState = null; | ||||
|             } | ||||
|         }) | ||||
|         editor.getView = function () { | ||||
|             var session = editor.getSession(); | ||||
|             return { | ||||
|                 selection: session.selection.toJSON(), | ||||
|                 scrollTop: session.getScrollTop(), | ||||
|                 scrollLeft: session.getScrollLeft(), | ||||
|                 options: session.getOptions() | ||||
|             } | ||||
|         } | ||||
|         editor.saveView = function () { | ||||
|             if (!options.stateId) { return; } //only possible if created with a unique stateId | ||||
|             window._editorStateAce = window._editorStateAce || {}; | ||||
|             var state = editor.getView(); | ||||
|             window._editorStateAce[options.stateId] = state; | ||||
|             return state; | ||||
|         } | ||||
|         editor.restoreView = function (state) { | ||||
|             if (!options.stateId) { return; } //only possible if created with a unique stateId | ||||
|             window._editorStateAce = window._editorStateAce || {}; | ||||
|             var _state = state || window._editorStateAce[options.stateId]; | ||||
|             if (!_state) { return; } //no view state available | ||||
|             try { | ||||
|                 var session = editor.getSession(); | ||||
|                 session.setOptions(_state.options); | ||||
|                 session.selection.fromJSON(_state.selection); | ||||
|                 session.setScrollTop(_state.scrollTop); | ||||
|                 session.setScrollLeft(_state.scrollLeft); | ||||
|                 editor._initState = _state; | ||||
|             } catch (error) { | ||||
|                 delete window._editorStateMonaco[options.stateId]; | ||||
|             } | ||||
|         }; | ||||
|         editor.restoreView(); | ||||
|         editor.type = type; | ||||
|         return editor; | ||||
|     } | ||||
|   | ||||
| @@ -171,7 +171,7 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|  | ||||
|         options = options || {}; | ||||
|         window.MonacoEnvironment = window.MonacoEnvironment || {}; | ||||
|         window.MonacoEnvironment.getWorkerUrl = window.MonacoEnvironment.getWorkerUrl || function (moduleId, label) { | ||||
|         window.MonacoEnvironment.getWorkerUrl = function (moduleId, label) { | ||||
|             if (label === 'json') { return './vendor/monaco/dist/json.worker.js'; } | ||||
|             if (label === 'css' || label === 'scss') { return './vendor/monaco/dist/css.worker.js'; } | ||||
|             if (label === 'html' || label === 'handlebars') { return './vendor/monaco/dist/html.worker.js'; } | ||||
| @@ -747,25 +747,13 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|                     mode = "html"; | ||||
|                     break; | ||||
|                 case "appcache": | ||||
|                 case "sh": | ||||
|                 case "bash": | ||||
|                     mode = "shell"; | ||||
|                     break; | ||||
|                 case "batchfile": | ||||
|                     mode = "bat"; | ||||
|                     break; | ||||
|                 case "protobuf": | ||||
|                     mode = "proto"; | ||||
|                     break; | ||||
|                 //TODO: add other compatability types. | ||||
|             } | ||||
|             return mode; | ||||
|         } | ||||
|  | ||||
|          | ||||
|         if(!options.stateId && options.stateId !== false) { | ||||
|             options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title).split("/").pop()); | ||||
|         } | ||||
|         var el = options.element || $("#"+options.id)[0]; | ||||
|         var toolbarRow = $("<div>").appendTo(el); | ||||
|         el = $("<div>").appendTo(el).addClass("red-ui-editor-text-container")[0]; | ||||
| @@ -1110,7 +1098,6 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|             try { | ||||
|                 var m = this.getModel(); | ||||
|                 if(m && !m.isDisposed()) { | ||||
|                     ed._initState = null; | ||||
|                     m.dispose(); | ||||
|                 } | ||||
|                 this.setModel(null); | ||||
| @@ -1164,7 +1151,7 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|             try { | ||||
|                 var _model = ed.getModel(); | ||||
|                 if (_model !== null) { | ||||
|                     var id = _model._languageId; // e.g. javascript | ||||
|                     var id = _model.getModeId(); // e.g. javascript | ||||
|                     var ra = _model._associatedResource.authority;  //e.g.  model | ||||
|                     var rp = _model._associatedResource.path;   //e.g.      /18 | ||||
|                     var rs = _model._associatedResource.scheme; //e.g.      inmemory | ||||
| @@ -1256,7 +1243,14 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|         //#endregion "ACE compatability" | ||||
|  | ||||
|         //final setup | ||||
|         ed.focusMemory = options.focus; | ||||
|         if (options.cursor) { | ||||
|             var row = options.cursor.row || options.cursor.lineNumber; | ||||
|             var col = options.cursor.column || options.cursor.col; | ||||
|             ed.gotoLine(row, col); | ||||
|         } | ||||
|         if (options.focus) { | ||||
|             ed.focus(); | ||||
|         } | ||||
|         ed._mode = editorOptions.language; | ||||
|  | ||||
|         //as models are signleton, consts and let are avialable to other javascript instances | ||||
| @@ -1268,12 +1262,11 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|         } | ||||
|  | ||||
|         ed.onDidBlurEditorWidget(function() { | ||||
|             ed.focusMemory = false; | ||||
|             ed.saveView(); | ||||
|             if(isVisible(el) == false) { | ||||
|                 onVisibilityChange(false, 0, el); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         ed.onDidFocusEditorWidget(function() { | ||||
|             onVisibilityChange(true, 10, el); | ||||
|         }); | ||||
| @@ -1307,33 +1300,17 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|         } | ||||
|  | ||||
|         function onVisibilityChange(visible, delay, element) { | ||||
|             delay = delay || 50; | ||||
|             if (visible) { | ||||
|                 if (ed.focusMemory) { | ||||
|                     setTimeout(function () { | ||||
|                         if (element.parentElement) { //ensure el is still in DOM | ||||
|                             ed.focus(); | ||||
|                         } | ||||
|                     }, 300) | ||||
|                 } | ||||
|                 if (ed._initState) { | ||||
|                     setTimeout(function () { | ||||
|                         if (element.parentElement) { //ensure el is still in DOM | ||||
|                             ed.restoreViewState(ed._initState); | ||||
|                             ed._initState = null; | ||||
|                         } | ||||
|                     }, delay); | ||||
|                 } | ||||
|                 if (ed._mode == "javascript" && ed._tempMode == "text") { | ||||
|             if(visible) { | ||||
|                 if(ed._mode == "javascript" && ed._tempMode == "text") { | ||||
|                     ed._tempMode = ""; | ||||
|                     setTimeout(function () { | ||||
|                         if (element.parentElement) { //ensure el is still in DOM | ||||
|                     setTimeout(function() { | ||||
|                         if(element.parentElement) { //ensure el is still in DOM | ||||
|                             ed.setMode('javascript', undefined, false); | ||||
|                         } | ||||
|                     }, delay); | ||||
|                     }, delay || 50); | ||||
|                 } | ||||
|             } else if (ed._mode == "javascript" && ed._tempMode != "text") { | ||||
|                 if (element.parentElement) { //ensure el is still in DOM | ||||
|             } else if(ed._mode == "javascript" && ed._tempMode != "text") { | ||||
|                 if(element.parentElement) { //ensure el is still in DOM | ||||
|                     ed.setMode('text', undefined, false); | ||||
|                     ed._tempMode = "text"; | ||||
|                 } | ||||
| @@ -1352,19 +1329,15 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|                 expandButton.on("click", function (e) { | ||||
|                     e.preventDefault(); | ||||
|                     var value = ed.getValue(); | ||||
|                     ed.saveView(); | ||||
|                     RED.editor.editMarkdown({ | ||||
|                         value: value, | ||||
|                         width: "Infinity", | ||||
|                         stateId: options.stateId, | ||||
|                         cancel: function () { | ||||
|                             ed.focus(); | ||||
|                         }, | ||||
|                         cursor: ed.getCursorPosition(), | ||||
|                         complete: function (v, cursor) { | ||||
|                             ed.setValue(v, -1); | ||||
|                             ed.gotoLine(cursor.row + 1, cursor.column, false); | ||||
|                             setTimeout(function () { | ||||
|                                 ed.focus(); | ||||
|                                 ed.restoreView(); | ||||
|                             }, 300); | ||||
|                         } | ||||
|                     }) | ||||
| @@ -1380,37 +1353,7 @@ RED.editor.codeEditor.monaco = (function() { | ||||
|                 autoClose: 50 | ||||
|             }); | ||||
|         } | ||||
|         ed.getView = function () { | ||||
|             return ed.saveViewState(); | ||||
|         } | ||||
|         ed.saveView = function (debuginfo) { | ||||
|             if (!options.stateId) { return; } //only possible if created with a unique stateId | ||||
|             window._editorStateMonaco = window._editorStateMonaco || {}; | ||||
|             var state = ed.getView(); | ||||
|             window._editorStateMonaco[options.stateId] = state; | ||||
|             return state; | ||||
|         } | ||||
|         ed.restoreView = function (state) { | ||||
|             if (!options.stateId) { return; } //only possible if created with a unique stateId | ||||
|             window._editorStateMonaco = window._editorStateMonaco || {}; | ||||
|             var _state = state || window._editorStateMonaco[options.stateId]; | ||||
|             if (!_state) { return; } //no view state available | ||||
|             try { | ||||
|                 if (ed.type) { //is editor already initialised? | ||||
|                     ed.restoreViewState(_state); | ||||
|                 } else { | ||||
|                     ed._initState = _state; | ||||
|                 } | ||||
|             } catch (error) { | ||||
|                 delete window._editorStateMonaco[options.stateId]; | ||||
|             } | ||||
|         }; | ||||
|         ed.restoreView(); | ||||
|         if (options.cursor && !ed._initState) { | ||||
|             var row = options.cursor.row || options.cursor.lineNumber; | ||||
|             var col = options.cursor.column || options.cursor.col; | ||||
|             ed.gotoLine(row, col); | ||||
|         } | ||||
|  | ||||
|         ed.type = type; | ||||
|         return ed; | ||||
|     } | ||||
|   | ||||
| @@ -41,8 +41,12 @@ RED.editor.envVarList = (function() { | ||||
|                         style: "width:100%", | ||||
|                         class: "node-input-env-value", | ||||
|                         type: "text", | ||||
|                     }).attr("autocomplete","disable").appendTo(envRow) | ||||
|                     valueField.typedInput({default:'str',types:isTemplateNode?DEFAULT_ENV_TYPE_LIST:DEFAULT_ENV_TYPE_LIST_INC_CRED}); | ||||
|                     }).attr("autocomplete","disable").appendTo(envRow); | ||||
|                     var types = (opt.ui && opt.ui.opts && opt.ui.opts.types); | ||||
|                     if (!types) { | ||||
|                         types = isTemplateNode ? DEFAULT_ENV_TYPE_LIST : DEFAULT_ENV_TYPE_LIST_INC_CRED; | ||||
|                     } | ||||
|                     valueField.typedInput({default:'str',types:types}); | ||||
|                     valueField.typedInput('type', opt.type); | ||||
|                     if (opt.type === "cred") { | ||||
|                         if (opt.value) { | ||||
| @@ -94,6 +98,11 @@ RED.editor.envVarList = (function() { | ||||
|                         } | ||||
|                         opt.ui.label = opt.ui.label || {}; | ||||
|                         opt.ui.type = opt.ui.type || "input"; | ||||
|                         if ((opt.ui.type === "cred") && | ||||
|                             opt.ui.opts && | ||||
|                             opt.ui.opts.types) { | ||||
|                             opt.ui.type = "input"; | ||||
|                         } | ||||
|  | ||||
|                         var uiRow = $('<div/>').appendTo(container).hide(); | ||||
|                         // save current info for reverting on cancel | ||||
|   | ||||
| @@ -50,7 +50,6 @@ | ||||
|         show: function(options) { | ||||
|             var expressionTestCacheId = options.parent||"_"; | ||||
|             var value = options.value; | ||||
|             var onCancel = options.cancel; | ||||
|             var onComplete = options.complete; | ||||
|             var type = "_expression" | ||||
|             if ($("script[data-template-name='"+type+"']").length === 0) { | ||||
| @@ -64,14 +63,12 @@ | ||||
|  | ||||
|             var trayOptions = { | ||||
|                 title: options.title, | ||||
|                 focusElement: options.focusElement, | ||||
|                 width: "inherit", | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "node-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             if(onCancel) { onCancel(); } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     }, | ||||
| @@ -81,8 +78,7 @@ | ||||
|                         class: "primary", | ||||
|                         click: function() { | ||||
|                             $("#red-ui-editor-type-expression-help").text(""); | ||||
|                             expressionEditor.saveView(); | ||||
|                             if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(),expressionEditor); } | ||||
|                             onComplete(expressionEditor.getValue()); | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     } | ||||
| @@ -114,8 +110,6 @@ | ||||
|                         id: 'red-ui-editor-type-expression', | ||||
|                         value: "", | ||||
|                         mode:"ace/mode/jsonata", | ||||
|                         stateId: options.stateId, | ||||
|                         focus: true, | ||||
|                         options: { | ||||
|                             enableBasicAutocompletion:true, | ||||
|                             enableSnippets:true, | ||||
| @@ -239,8 +233,6 @@ | ||||
|                     testDataEditor = RED.editor.createEditor({ | ||||
|                         id: 'red-ui-editor-type-expression-test-data', | ||||
|                         value: expressionTestCache[expressionTestCacheId] || '{\n    "payload": "hello world"\n}', | ||||
|                         stateId: false, | ||||
|                         focus: false, | ||||
|                         mode:"ace/mode/json", | ||||
|                         lineNumbers: false | ||||
|                     }); | ||||
| @@ -310,8 +302,6 @@ | ||||
|                     testResultEditor = RED.editor.createEditor({ | ||||
|                         id: 'red-ui-editor-type-expression-test-result', | ||||
|                         value: "", | ||||
|                         stateId: false, | ||||
|                         focus: false, | ||||
|                         mode:"ace/mode/json", | ||||
|                         lineNumbers: false, | ||||
|                         readOnly: true | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
|     var definition = { | ||||
|         show: function(options) { | ||||
|             var value = options.value; | ||||
|             var onCancel = options.cancel; | ||||
|             var onComplete = options.complete; | ||||
|             var type = "_js" | ||||
|             if ($("script[data-template-name='"+type+"']").length === 0) { | ||||
| @@ -29,16 +28,16 @@ | ||||
|             } | ||||
|             RED.view.state(RED.state.EDITING); | ||||
|             var expressionEditor; | ||||
|             var changeTimer; | ||||
|  | ||||
|             var trayOptions = { | ||||
|                 title: options.title, | ||||
|                 focusElement: options.focusElement, | ||||
|                 width: options.width||"inherit", | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "node-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             if (onCancel) { onCancel(); } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     }, | ||||
| @@ -47,8 +46,7 @@ | ||||
|                         text: RED._("common.label.done"), | ||||
|                         class: "primary", | ||||
|                         click: function() { | ||||
|                             expressionEditor.saveView(); | ||||
|                             if (onComplete) { onComplete(expressionEditor.getValue(), expressionEditor.getCursorPosition(), expressionEditor); } | ||||
|                             onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition()); | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     } | ||||
| @@ -64,12 +62,11 @@ | ||||
|                     expressionEditor.resize(); | ||||
|                 }, | ||||
|                 open: function(tray) { | ||||
|                     var trayBody = tray.find('.red-ui-tray-body'); | ||||
|                     var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); | ||||
|                     expressionEditor = RED.editor.createEditor({ | ||||
|                         id: 'node-input-js', | ||||
|                         mode: options.mode || 'ace/mode/javascript', | ||||
|                         stateId: options.stateId, | ||||
|                         focus: true, | ||||
|                         value: value, | ||||
|                         globals: { | ||||
|                             msg:true, | ||||
| @@ -87,16 +84,19 @@ | ||||
|                         }, | ||||
|                         extraLibs: options.extraLibs | ||||
|                     }); | ||||
|                     if (options.cursor && !expressionEditor._initState) { | ||||
|                     if (options.cursor) { | ||||
|                         expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); | ||||
|                     } | ||||
|                     dialogForm.i18n(); | ||||
|                     setTimeout(function() { | ||||
|                         expressionEditor.focus(); | ||||
|                     },300); | ||||
|                 }, | ||||
|                 close: function() { | ||||
|                     expressionEditor.destroy(); | ||||
|                     if (options.onclose) { | ||||
|                         options.onclose(); | ||||
|                     } | ||||
|                     expressionEditor.destroy(); | ||||
|                 }, | ||||
|                 show: function() {} | ||||
|             } | ||||
|   | ||||
| @@ -21,9 +21,7 @@ | ||||
|         '<ul id="red-ui-editor-type-json-tabs"></ul>'+ | ||||
|         '<div id="red-ui-editor-type-json-tab-raw" class="red-ui-editor-type-json-tab-content hide">'+ | ||||
|             '<div class="form-row" style="margin-bottom: 3px; text-align: right;">'+ | ||||
|                 '<span class="button-group">'+ | ||||
|                     '<button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button>'+ | ||||
|                 '<span class="button-group">'+ | ||||
|                 '<button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button>'+ | ||||
|             '</div>'+ | ||||
|             '<div class="form-row node-text-editor-row">'+ | ||||
|                 '<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>'+ | ||||
| @@ -36,7 +34,7 @@ | ||||
|  | ||||
|     var activeTab; | ||||
|  | ||||
|     function insertNewItem(parent,index,copyIndex,readOnly) { | ||||
|     function insertNewItem(parent,index,copyIndex) { | ||||
|         var newValue = ""; | ||||
|  | ||||
|         if (parent.children.length > 0) { | ||||
| @@ -62,26 +60,26 @@ | ||||
|                 newKey = keyRoot+"-"+(keySuffix++); | ||||
|             } | ||||
|         } | ||||
|         var newItem = handleItem(newKey,newValue,parent.depth+1,parent,readOnly); | ||||
|         var newItem = handleItem(newKey,newValue,parent.depth+1,parent); | ||||
|         parent.treeList.insertChildAt(newItem, index, true); | ||||
|         parent.treeList.expand(); | ||||
|     } | ||||
|     function showObjectMenu(button,item,readOnly) { | ||||
|     function showObjectMenu(button,item) { | ||||
|         var elementPos = button.offset(); | ||||
|         var options = []; | ||||
|         if (item.parent) { | ||||
|             options.push({id:"red-ui-editor-type-json-menu-insert-above", icon:"fa fa-toggle-up", label:RED._('jsonEditor.insertAbove'),onselect:function(){ | ||||
|                 var index = item.parent.children.indexOf(item); | ||||
|                 insertNewItem(item.parent,index,index,readOnly); | ||||
|                 insertNewItem(item.parent,index,index); | ||||
|             }}); | ||||
|             options.push({id:"red-ui-editor-type-json-menu-insert-below", icon:"fa fa-toggle-down", label:RED._('jsonEditor.insertBelow'),onselect:function(){ | ||||
|                 var index = item.parent.children.indexOf(item)+1; | ||||
|                 insertNewItem(item.parent,index,index-1,readOnly); | ||||
|                 insertNewItem(item.parent,index,index-1); | ||||
|             }}); | ||||
|         } | ||||
|         if (item.type === 'array' || item.type === 'object') { | ||||
|             options.push({id:"red-ui-editor-type-json-menu-add-child", icon:"fa fa-plus", label:RED._('jsonEditor.addItem'),onselect:function(){ | ||||
|                 insertNewItem(item,item.children.length,item.children.length-1,readOnly); | ||||
|                 insertNewItem(item,item.children.length,item.children.length-1); | ||||
|             }}); | ||||
|         } | ||||
|         if (item.parent) { | ||||
| @@ -123,7 +121,7 @@ | ||||
|                         newKey = keyRoot+"-"+(keySuffix++); | ||||
|                     } | ||||
|                 } | ||||
|                 var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent,readOnly); | ||||
|                 var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent); | ||||
|                 var index = item.parent.children.indexOf(item)+1; | ||||
|  | ||||
|                 item.parent.treeList.insertChildAt(newItem, index, true); | ||||
| @@ -173,24 +171,24 @@ | ||||
|         menuOptionMenu.show(); | ||||
|     } | ||||
|  | ||||
|     function parseObject(obj,depth,parent,readOnly) { | ||||
|     function parseObject(obj,depth,parent) { | ||||
|         var result = []; | ||||
|         for (var prop in obj) { | ||||
|             if (obj.hasOwnProperty(prop)) { | ||||
|                 result.push(handleItem(prop,obj[prop],depth,parent,readOnly)); | ||||
|                 result.push(handleItem(prop,obj[prop],depth,parent)); | ||||
|             } | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|     function parseArray(obj,depth,parent,readOnly) { | ||||
|     function parseArray(obj,depth,parent) { | ||||
|         var result = []; | ||||
|         var l = obj.length; | ||||
|         for (var i=0;i<l;i++) { | ||||
|             result.push(handleItem(i,obj[i],depth,parent,readOnly)); | ||||
|             result.push(handleItem(i,obj[i],depth,parent)); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|     function handleItem(key,val,depth,parent,readOnly) { | ||||
|     function handleItem(key,val,depth,parent) { | ||||
|         var item = {depth:depth, type: typeof val}; | ||||
|         var container = $('<span class="red-ui-editor-type-json-editor-label">'); | ||||
|         if (key != null) { | ||||
| @@ -206,14 +204,11 @@ | ||||
|             if (parent && parent.type === "array") { | ||||
|                 keyLabel.addClass("red-ui-editor-type-json-editor-label-array-key") | ||||
|             } | ||||
|             if(readOnly) { | ||||
|                 keyLabel.addClass("readonly") | ||||
|             } | ||||
|  | ||||
|             keyLabel.on("click", function(evt) { | ||||
|                 if (item.parent.type === 'array') { | ||||
|                     return; | ||||
|                 } | ||||
|                 if (readOnly) { return; } | ||||
|                 evt.preventDefault(); | ||||
|                 evt.stopPropagation(); | ||||
|                 var w = Math.max(150,keyLabel.width()); | ||||
| @@ -258,10 +253,10 @@ | ||||
|             item.expanded = depth < 2; | ||||
|             item.type = "array"; | ||||
|             item.deferBuild = depth >= 2; | ||||
|             item.children = parseArray(val,depth+1,item,readOnly); | ||||
|             item.children = parseArray(val,depth+1,item); | ||||
|         } else if (val !== null && item.type === "object") { | ||||
|             item.expanded = depth < 2; | ||||
|             item.children = parseObject(val,depth+1,item,readOnly); | ||||
|             item.children = parseObject(val,depth+1,item); | ||||
|             item.deferBuild = depth >= 2; | ||||
|         } else { | ||||
|             item.value = val; | ||||
| @@ -292,11 +287,7 @@ | ||||
|         // | ||||
|         var orphanedChildren; | ||||
|         var valueLabel = $('<span class="red-ui-editor-type-json-editor-label-value">').addClass(valClass).text(valValue).appendTo(container); | ||||
|         if (readOnly) { | ||||
|             valueLabel.addClass("readonly") | ||||
|         } | ||||
|         valueLabel.on("click", function(evt) { | ||||
|             if (readOnly) { return; } | ||||
|             evt.preventDefault(); | ||||
|             evt.stopPropagation(); | ||||
|             if (valType === 'str') { | ||||
| @@ -311,8 +302,8 @@ | ||||
|                 types:[ | ||||
|                     'str','num','bool', | ||||
|                     {value:"null",label:RED._("common.type.null"),hasValue:false}, | ||||
|                     {value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.svg"}, | ||||
|                     {value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.svg"} | ||||
|                     {value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.png"}, | ||||
|                     {value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.png"} | ||||
|                 ], | ||||
|                 default: valType | ||||
|             }); | ||||
| @@ -404,19 +395,17 @@ | ||||
|             valueLabel.hide(); | ||||
|         }) | ||||
|         item.gutter = $('<span class="red-ui-editor-type-json-editor-item-gutter"></span>'); | ||||
|         if(!readOnly) { | ||||
|             if (parent) { | ||||
|                 $('<span class="red-ui-editor-type-json-editor-item-handle"><i class="fa fa-bars"></span>').appendTo(item.gutter); | ||||
|             } else { | ||||
|                 $('<span></span>').appendTo(item.gutter); | ||||
|             } | ||||
|             $('<button type="button" class="editor-button editor-button-small"><i class="fa fa-caret-down"></button>').appendTo(item.gutter).on("click", function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 evt.stopPropagation(); | ||||
|                 showObjectMenu($(this), item, readOnly); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         if (parent) {//red-ui-editor-type-json-editor-item-handle | ||||
|             $('<span class="red-ui-editor-type-json-editor-item-handle"><i class="fa fa-bars"></span>').appendTo(item.gutter); | ||||
|         } else { | ||||
|             $('<span></span>').appendTo(item.gutter); | ||||
|         } | ||||
|         $('<button type="button" class="editor-button editor-button-small"><i class="fa fa-caret-down"></button>').appendTo(item.gutter).on("click", function(evt) { | ||||
|             evt.preventDefault(); | ||||
|             evt.stopPropagation(); | ||||
|             showObjectMenu($(this), item); | ||||
|         }); | ||||
|         item.element = container; | ||||
|         return item; | ||||
|     } | ||||
| @@ -445,7 +434,6 @@ | ||||
|     var definition = { | ||||
|         show: function(options) { | ||||
|             var value = options.value; | ||||
|             var onCancel = options.cancel; | ||||
|             var onComplete = options.complete; | ||||
|             var type = "_json" | ||||
|             if ($("script[data-template-name='"+type+"']").length === 0) { | ||||
| @@ -467,16 +455,15 @@ | ||||
|                 } | ||||
|             } | ||||
|             var rootNode; | ||||
|  | ||||
|             var trayOptions = { | ||||
|                 title: options.title, | ||||
|                 focusElement: options.focusElement, | ||||
|                 width: options.width||700, | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "node-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             if (onCancel) { onCancel(); } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     }, | ||||
| @@ -498,8 +485,7 @@ | ||||
|                             } else if (activeTab === "json-raw") { | ||||
|                                 result = expressionEditor.getValue(); | ||||
|                             } | ||||
|                             expressionEditor.saveView(); | ||||
|                             if (onComplete) { onComplete(result,null,expressionEditor) } | ||||
|                             if (onComplete) { onComplete(result) } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     } | ||||
| @@ -512,25 +498,7 @@ | ||||
|                 open: function(tray) { | ||||
|                     var trayBody = tray.find('.red-ui-tray-body'); | ||||
|                     var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); | ||||
|                     var toolbarButtons = options.toolbarButtons || []; | ||||
|                     if (toolbarButtons.length) { | ||||
|                         toolbarButtons.forEach(function (button) { | ||||
|                             var element = $('<button type="button" class="red-ui-button red-ui-button-small"> </button>') | ||||
|                                 .insertBefore("#node-input-json-reformat") | ||||
|                                 .on("click", function (evt) { | ||||
|                                     evt.preventDefault(); | ||||
|                                     if (button.click !== undefined) { | ||||
|                                         button.click.call(element, evt); | ||||
|                                     } | ||||
|                                 }); | ||||
|                             if (button.id) { element.attr("id", button.id); } | ||||
|                             if (button.title) { element.attr("title", button.title); } | ||||
|                             if (button.icon) { element.append($("<i></i>").attr("class", button.icon)); } | ||||
|                             if (button.label || button.text) { | ||||
|                                 element.append($("<span></span>").text(" " + (button.label || button.text))); | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|  | ||||
|                     var container = $("#red-ui-editor-type-json-tab-ui-container").css({"height":"100%"}); | ||||
|                     var filterDepth = Infinity; | ||||
|                     var list = $('<div class="red-ui-debug-msg-payload red-ui-editor-type-json-editor">').appendTo(container).treeList({ | ||||
| @@ -560,15 +528,13 @@ | ||||
|                         }) | ||||
|                     }); | ||||
|  | ||||
|  | ||||
|                     expressionEditor = RED.editor.createEditor({ | ||||
|                         id: 'node-input-json', | ||||
|                         value: value||"", | ||||
|                         mode:"ace/mode/json", | ||||
|                         readOnly: !!options.readOnly, | ||||
|                         stateId: options.stateId, | ||||
|                         focus: true | ||||
|                         value: "", | ||||
|                         mode:"ace/mode/json" | ||||
|                     }); | ||||
|  | ||||
|                     expressionEditor.getSession().setValue(value||"",-1); | ||||
|                     if (options.requireValid) { | ||||
|                         expressionEditor.getSession().on('change', function() { | ||||
|                             clearTimeout(changeTimer); | ||||
| @@ -605,7 +571,7 @@ | ||||
|                                     var raw = expressionEditor.getValue().trim() ||"{}"; | ||||
|                                     try { | ||||
|                                         var parsed = JSON.parse(raw); | ||||
|                                         rootNode = handleItem(null,parsed,0,null,options.readOnly); | ||||
|                                         rootNode = handleItem(null,parsed,0,null); | ||||
|                                         rootNode.class = "red-ui-editor-type-json-root-node" | ||||
|                                         list.treeList('data',[rootNode]); | ||||
|                                     } catch(err) { | ||||
| @@ -623,15 +589,17 @@ | ||||
|  | ||||
|                     tabs.addTab({ | ||||
|                         id: 'json-raw', | ||||
|                         label: options.readOnly ? RED._('jsonEditor.rawMode-readonly') : RED._('jsonEditor.rawMode'), | ||||
|                         label: RED._('jsonEditor.rawMode'), | ||||
|                         content: $("#red-ui-editor-type-json-tab-raw") | ||||
|                     }); | ||||
|                     tabs.addTab({ | ||||
|                         id: 'json-ui', | ||||
|                         label: options.readOnly ? RED._('jsonEditor.uiMode-readonly') : RED._('jsonEditor.uiMode'), | ||||
|                         label: RED._('jsonEditor.uiMode'), | ||||
|                         content: $("#red-ui-editor-type-json-tab-ui") | ||||
|                     }); | ||||
|                     finishedBuild = true; | ||||
|  | ||||
|  | ||||
|                 }, | ||||
|                 close: function() { | ||||
|                     if (options.onclose) { | ||||
|   | ||||
| @@ -54,26 +54,24 @@ | ||||
|     var definition = { | ||||
|         show: function(options) { | ||||
|             var value = options.value; | ||||
|             var onCancel = options.cancel; | ||||
|             var onComplete = options.complete; | ||||
|             var type = "_markdown" | ||||
|             if ($("script[data-template-name='"+type+"']").length === 0) { | ||||
|                 $(template).appendTo("#red-ui-editor-node-configs"); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             RED.view.state(RED.state.EDITING); | ||||
|             var expressionEditor; | ||||
|  | ||||
|             var trayOptions = { | ||||
|                 title: options.title, | ||||
|                 focusElement: options.focusElement, | ||||
|                 width: options.width||Infinity, | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "node-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             if (onCancel) { onCancel(); } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     }, | ||||
| @@ -82,8 +80,7 @@ | ||||
|                         text: RED._("common.label.done"), | ||||
|                         class: "primary", | ||||
|                         click: function() { | ||||
|                             expressionEditor.saveView(); | ||||
|                             if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(), expressionEditor); } | ||||
|                             onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition()); | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     } | ||||
| @@ -102,8 +99,6 @@ | ||||
|                     expressionEditor = RED.editor.createEditor({ | ||||
|                         id: 'red-ui-editor-type-markdown', | ||||
|                         value: value, | ||||
|                         stateId: options.stateId, | ||||
|                         focus: true, | ||||
|                         mode:"ace/mode/markdown", | ||||
|                         expandable: false | ||||
|                     }); | ||||
| @@ -148,17 +143,17 @@ | ||||
|                     }); | ||||
|                     RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview")); | ||||
|  | ||||
|                     if (options.cursor && !expressionEditor._initState) { | ||||
|                     if (options.cursor) { | ||||
|                         expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); | ||||
|                     } | ||||
|  | ||||
|                     dialogForm.i18n(); | ||||
|                 }, | ||||
|                 close: function() { | ||||
|                     expressionEditor.destroy(); | ||||
|                     if (options.onclose) { | ||||
|                         options.onclose(); | ||||
|                     } | ||||
|                     expressionEditor.destroy(); | ||||
|                 }, | ||||
|                 show: function() {} | ||||
|             } | ||||
|   | ||||
| @@ -37,8 +37,7 @@ | ||||
|                 if (!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) { | ||||
|                     var icon = $("#red-ui-editor-node-icon").val()||""; | ||||
|                     if (!this.isDefaultIcon) { | ||||
|                         if ((icon !== node.icon) && | ||||
|                             (icon !== "")) { | ||||
|                         if ((node.icon && icon !== node.icon) || (!node.icon && icon !== "")) { | ||||
|                             editState.changes.icon = node.icon; | ||||
|                             node.icon = icon; | ||||
|                             editState.changed = true; | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
|  | ||||
|             create: function(container) { | ||||
|                 this.editor = buildDescriptionForm(container,node); | ||||
|                 RED.e = this.editor; | ||||
|             }, | ||||
|             resize: function(size) { | ||||
|                 this.editor.resize(); | ||||
| @@ -57,9 +58,11 @@ | ||||
|         var nodeInfoEditor = RED.editor.createEditor({ | ||||
|             id: editorId, | ||||
|             mode: 'ace/mode/markdown', | ||||
|             stateId: RED.editor.generateViewStateId("node", node, "nodeinfo"), | ||||
|             value: node.info || "" | ||||
|             value: "" | ||||
|         }); | ||||
|         if (node.info) { | ||||
|             nodeInfoEditor.getSession().setValue(node.info, -1); | ||||
|         } | ||||
|         node.infoEditor = nodeInfoEditor; | ||||
|         return nodeInfoEditor; | ||||
|     } | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
|     var definition = { | ||||
|         show: function(options) { | ||||
|             var value = options.value; | ||||
|             var onCancel = options.cancel; | ||||
|             var onComplete = options.complete; | ||||
|             var type = "_text" | ||||
|             if ($("script[data-template-name='"+type+"']").length === 0) { | ||||
| @@ -29,16 +28,16 @@ | ||||
|             } | ||||
|             RED.view.state(RED.state.EDITING); | ||||
|             var expressionEditor; | ||||
|             var changeTimer; | ||||
|  | ||||
|             var trayOptions = { | ||||
|                 title: options.title, | ||||
|                 focusElement: options.focusElement, | ||||
|                 width: options.width||"inherit", | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "node-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             if(onCancel) { onCancel(); } | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     }, | ||||
| @@ -47,8 +46,7 @@ | ||||
|                         text: RED._("common.label.done"), | ||||
|                         class: "primary", | ||||
|                         click: function() { | ||||
|                             expressionEditor.saveView(); | ||||
|                             if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(),expressionEditor);} | ||||
|                             onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition()); | ||||
|                             RED.tray.close(); | ||||
|                         } | ||||
|                     } | ||||
| @@ -57,27 +55,31 @@ | ||||
|                     var rows = $("#dialog-form>div:not(.node-text-editor-row)"); | ||||
|                     var editorRow = $("#dialog-form>div.node-text-editor-row"); | ||||
|                     var height = $("#dialog-form").height(); | ||||
|                     // for (var i=0;i<rows.size();i++) { | ||||
|                     //     height -= $(rows[i]).outerHeight(true); | ||||
|                     // } | ||||
|                     // height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom"))); | ||||
|                     $(".node-text-editor").css("height",height+"px"); | ||||
|                     expressionEditor.resize(); | ||||
|                 }, | ||||
|                 open: function(tray) { | ||||
|                     var trayBody = tray.find('.red-ui-tray-body'); | ||||
|                     var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); | ||||
|                     expressionEditor = RED.editor.createEditor({ | ||||
|                         id: 'node-input-text', | ||||
|                         value: value||"", | ||||
|                         stateId: options.stateId, | ||||
|                         mode:"ace/mode/"+(options.mode||"text"), | ||||
|                         focus: true, | ||||
|                         value: "", | ||||
|                         mode:"ace/mode/"+(options.mode||"text") | ||||
|                     }); | ||||
|                     if (options.cursor && !expressionEditor._initState) { | ||||
|                     expressionEditor.getSession().setValue(value||"",-1); | ||||
|                     if (options.cursor) { | ||||
|                         expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); | ||||
|                     } | ||||
|                 }, | ||||
|                 close: function() { | ||||
|                     expressionEditor.destroy(); | ||||
|                     if (options.onclose) { | ||||
|                         options.onclose(); | ||||
|                     } | ||||
|                     expressionEditor.destroy(); | ||||
|                 }, | ||||
|                 show: function() {} | ||||
|             } | ||||
|   | ||||
| @@ -349,10 +349,8 @@ RED.group = (function() { | ||||
|             } | ||||
|             if (n.type === 'group') { | ||||
|                 RED.events.emit("groups:change",n) | ||||
|             } else if (n.type !== 'junction') { | ||||
|                 RED.events.emit("nodes:change",n) | ||||
|             } else { | ||||
|                 RED.events.emit("junctions:change",n) | ||||
|                 RED.events.emit("nodes:change",n) | ||||
|             } | ||||
|         }) | ||||
|         RED.nodes.removeGroup(g); | ||||
| @@ -546,10 +544,8 @@ RED.group = (function() { | ||||
|                 group.h = Math.max(group.h,n.y+n.h/2+25-group.y); | ||||
|                 if (n.type === 'group') { | ||||
|                     RED.events.emit("groups:change",n) | ||||
|                 } else if (n.type !== 'junction') { | ||||
|                     RED.events.emit("nodes:change",n) | ||||
|                 } else { | ||||
|                     RED.events.emit("junctions:change",n) | ||||
|                     RED.events.emit("nodes:change",n) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -584,10 +580,8 @@ RED.group = (function() { | ||||
|             } | ||||
|             if (n.type === 'group') { | ||||
|                 RED.events.emit("groups:change",n) | ||||
|             } else if (n.type !== 'junction') { | ||||
|                 RED.events.emit("nodes:change",n) | ||||
|             } else { | ||||
|                 RED.events.emit("junctions:change",n) | ||||
|                 RED.events.emit("nodes:change",n) | ||||
|             } | ||||
|         } | ||||
|         markDirty(group); | ||||
|   | ||||
| @@ -363,106 +363,112 @@ RED.library = (function() { | ||||
|                     options.onconfirm(item); | ||||
|                 } | ||||
|             }); | ||||
|         var itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"}); | ||||
|         var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>') | ||||
|             .on("click", function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 evt.stopPropagation(); | ||||
|                 var elementPos = menuButton.offset(); | ||||
|  | ||||
|                 var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu", | ||||
|                     options: [ | ||||
|                         {id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() { | ||||
|                             var defaultFolderName = "new-folder"; | ||||
|                             var defaultFolderNameMatches = {}; | ||||
|  | ||||
|                             var selected = dirList.treeList('selected'); | ||||
|                             if (!selected.children) { | ||||
|                                 selected = selected.parent; | ||||
|                             } | ||||
|                             var complete = function() { | ||||
|                                 selected.children.forEach(function(c) { | ||||
|                                     if (/^new-folder/.test(c.label)) { | ||||
|                                         defaultFolderNameMatches[c.label] = true | ||||
|                                     } | ||||
|                                 }); | ||||
|                                 var folderIndex = 2; | ||||
|                                 while(defaultFolderNameMatches[defaultFolderName]) { | ||||
|                                     defaultFolderName = "new-folder-"+(folderIndex++) | ||||
|                                 } | ||||
|  | ||||
|                                 selected.treeList.expand(); | ||||
|                                 var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName); | ||||
|                                 var newItem = { | ||||
|                                     icon: "fa fa-folder-o", | ||||
|                                     children:[], | ||||
|                                     path: selected.path, | ||||
|                                     element: input | ||||
|                                 } | ||||
|                                 var confirmAdd = function() { | ||||
|                                     var val = input.val().trim(); | ||||
|                                     if (val === "") { | ||||
|                                         cancelAdd(); | ||||
|                                         return; | ||||
|                                     } else { | ||||
|                                         for (var i=0;i<selected.children.length;i++) { | ||||
|                                             if (selected.children[i].label === val) { | ||||
|                                                 cancelAdd(); | ||||
|                                                 return; | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                     newItem.treeList.remove(); | ||||
|                                     var finalItem = { | ||||
|                                         library: selected.library, | ||||
|                                         type: selected.type, | ||||
|                                         icon: "fa fa-folder", | ||||
|                                         children:[], | ||||
|                                         label: val, | ||||
|                                         path: newItem.path+val+"/" | ||||
|                                     } | ||||
|                                     selected.treeList.addChild(finalItem,true); | ||||
|                                 } | ||||
|                                 var cancelAdd = function() { | ||||
|                                     newItem.treeList.remove(); | ||||
|                                 } | ||||
|                                 input.on('keydown', function(evt) { | ||||
|                                     evt.stopPropagation(); | ||||
|                                     if (evt.keyCode === 13) { | ||||
|                                         confirmAdd(); | ||||
|                                     } else if (evt.keyCode === 27) { | ||||
|                                         cancelAdd(); | ||||
|                                     } | ||||
|                                 }) | ||||
|                                 input.on("blur", function() { | ||||
|                                     confirmAdd(); | ||||
|                                 }) | ||||
|                                 selected.treeList.addChild(newItem); | ||||
|                                 setTimeout(function() { | ||||
|                                     input.trigger("focus"); | ||||
|                                     input.select(); | ||||
|                                 },400); | ||||
|                             } | ||||
|                             selected.treeList.expand(complete); | ||||
|  | ||||
|                         } }, | ||||
|                         // null, | ||||
|                         // {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} }, | ||||
|                         // {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} } | ||||
|                     ] | ||||
|                 }).on('mouseleave', function(){ $(this).remove(); dirList.focus() }) | ||||
|                   .on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)}) | ||||
|                   .appendTo("body"); | ||||
|                 menuOptionMenu.css({ | ||||
|                     position: "absolute", | ||||
|                     top: elementPos.top+"px", | ||||
|                     left: (elementPos.left - menuOptionMenu.width() + 20)+"px" | ||||
|                 }).show(); | ||||
|  | ||||
|             }).appendTo(itemTools); | ||||
|         var itemTools = null; | ||||
|         if (options.folderTools) { | ||||
|             dirList.on('treelistselect', function(event, item) { | ||||
|                 if (item.writable !== false && item.treeList) { | ||||
|                     if (itemTools) { | ||||
|                         itemTools.remove(); | ||||
|                     } | ||||
|                     itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"}); | ||||
|                     var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>') | ||||
|                         .on("click", function(evt) { | ||||
|                             evt.preventDefault(); | ||||
|                             evt.stopPropagation(); | ||||
|                             var elementPos = menuButton.offset(); | ||||
|  | ||||
|                             var menuOptionMenu | ||||
|                                 = RED.menu.init({id:"red-ui-library-browser-menu", | ||||
|                                       options: [ | ||||
|                                           {id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() { | ||||
|                                               var defaultFolderName = "new-folder"; | ||||
|                                               var defaultFolderNameMatches = {}; | ||||
|  | ||||
|                                               var selected = dirList.treeList('selected'); | ||||
|                                               if (!selected.children) { | ||||
|                                                   selected = selected.parent; | ||||
|                                               } | ||||
|                                               var complete = function() { | ||||
|                                                   selected.children.forEach(function(c) { | ||||
|                                                       if (/^new-folder/.test(c.label)) { | ||||
|                                                           defaultFolderNameMatches[c.label] = true | ||||
|                                                       } | ||||
|                                                   }); | ||||
|                                                   var folderIndex = 2; | ||||
|                                                   while(defaultFolderNameMatches[defaultFolderName]) { | ||||
|                                                       defaultFolderName = "new-folder-"+(folderIndex++) | ||||
|                                                   } | ||||
|  | ||||
|                                                   selected.treeList.expand(); | ||||
|                                                   var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName); | ||||
|                                                   var newItem = { | ||||
|                                                       icon: "fa fa-folder-o", | ||||
|                                                       children:[], | ||||
|                                                       path: selected.path, | ||||
|                                                       element: input | ||||
|                                                   } | ||||
|                                                   var confirmAdd = function() { | ||||
|                                                       var val = input.val().trim(); | ||||
|                                                       if (val === "") { | ||||
|                                                           cancelAdd(); | ||||
|                                                           return; | ||||
|                                                       } else { | ||||
|                                                           for (var i=0;i<selected.children.length;i++) { | ||||
|                                                               if (selected.children[i].label === val) { | ||||
|                                                                   cancelAdd(); | ||||
|                                                                   return; | ||||
|                                                               } | ||||
|                                                           } | ||||
|                                                       } | ||||
|                                                       newItem.treeList.remove(); | ||||
|                                                       var finalItem = { | ||||
|                                                           library: selected.library, | ||||
|                                                           type: selected.type, | ||||
|                                                           icon: "fa fa-folder", | ||||
|                                                           children:[], | ||||
|                                                           label: val, | ||||
|                                                           path: newItem.path+val+"/" | ||||
|                                                       } | ||||
|                                                       selected.treeList.addChild(finalItem,true); | ||||
|                                                   } | ||||
|                                                   var cancelAdd = function() { | ||||
|                                                       newItem.treeList.remove(); | ||||
|                                                   } | ||||
|                                                   input.on('keydown', function(evt) { | ||||
|                                                       evt.stopPropagation(); | ||||
|                                                       if (evt.keyCode === 13) { | ||||
|                                                           confirmAdd(); | ||||
|                                                       } else if (evt.keyCode === 27) { | ||||
|                                                           cancelAdd(); | ||||
|                                                       } | ||||
|                                                   }) | ||||
|                                                   input.on("blur", function() { | ||||
|                                                       confirmAdd(); | ||||
|                                                   }) | ||||
|                                                   selected.treeList.addChild(newItem); | ||||
|                                                   setTimeout(function() { | ||||
|                                                       input.trigger("focus"); | ||||
|                                                       input.select(); | ||||
|                                                   },400); | ||||
|                                               } | ||||
|                                               selected.treeList.expand(complete); | ||||
|  | ||||
|                                           } }, | ||||
|                                           // null, | ||||
|                                           // {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} }, | ||||
|                                           // {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} } | ||||
|                                       ] | ||||
|                                                 }).on('mouseleave', function(){ $(this).remove(); dirList.focus() }) | ||||
|                                 .on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)}) | ||||
|                                 .appendTo("body"); | ||||
|                             menuOptionMenu.css({ | ||||
|                                 position: "absolute", | ||||
|                                 top: elementPos.top+"px", | ||||
|                                 left: (elementPos.left - menuOptionMenu.width() + 20)+"px" | ||||
|                             }).show(); | ||||
|  | ||||
|                         }).appendTo(itemTools); | ||||
|                      | ||||
|                     itemTools.appendTo(item.treeList.label); | ||||
|                 } | ||||
|             }); | ||||
|   | ||||
| @@ -208,7 +208,7 @@ RED.palette = (function() { | ||||
|     } | ||||
|  | ||||
|     function escapeCategory(category) { | ||||
|         return category.replace(/[ /.]/g,"_"); | ||||
|         return category.replace(/[\x00-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/g,"_"); | ||||
|     } | ||||
|     function addNodeType(nt,def) { | ||||
|         if (getPaletteNode(nt).length) { | ||||
| @@ -224,7 +224,14 @@ RED.palette = (function() { | ||||
|  | ||||
|             var d = $('<div>',{class:"red-ui-palette-node"}).attr("data-palette-type",nt).data('category',rootCategory); | ||||
|  | ||||
|             var label = RED.utils.getPaletteLabel(nt, def);///^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; | ||||
|             var label = nt;///^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; | ||||
|             if (typeof def.paletteLabel !== "undefined") { | ||||
|                 try { | ||||
|                     label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||""; | ||||
|                 } catch(err) { | ||||
|                     console.log("Definition error: "+nt+".paletteLabel",err); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             $('<div/>', { | ||||
|                 class: "red-ui-palette-label"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "") | ||||
|   | ||||
| @@ -120,7 +120,6 @@ RED.projects.settings = (function() { | ||||
|             title: RED._('sidebar.project.editDescription'), | ||||
|             header: $('<span><i class="fa fa-book"></i> README.md</span>'), | ||||
|             value: activeProject.description, | ||||
|             stateId: "sidebar.project.editDescription", | ||||
|             complete: function(v) { | ||||
|                 container.empty(); | ||||
|                 var spinner = utils.addSpinnerOverlay(container); | ||||
|   | ||||
| @@ -25,8 +25,6 @@ RED.search = (function() { | ||||
|     var searchHistory = []; | ||||
|     var index = {}; | ||||
|     var currentResults = []; | ||||
|     var activeResults = []; | ||||
|     var currentIndex = 0; | ||||
|     var previousActiveElement; | ||||
|  | ||||
|     function indexProperty(node,label,property) { | ||||
| @@ -121,7 +119,6 @@ RED.search = (function() { | ||||
|         val = extractFlag(val,"config",flags); | ||||
|         val = extractFlag(val,"subflow",flags); | ||||
|         val = extractFlag(val,"hidden",flags); | ||||
|         val = extractFlag(val,"modified",flags); | ||||
|         // uses:<node-id> | ||||
|         val = extractValue(val,"uses",flags); | ||||
|  | ||||
| @@ -167,11 +164,6 @@ RED.search = (function() { | ||||
|                                 continue; | ||||
|                             } | ||||
|                         } | ||||
|                         if (flags.hasOwnProperty("modified")) { | ||||
|                             if (!node.node.changed && !node.node.moved) { | ||||
|                                 continue; | ||||
|                             } | ||||
|                         } | ||||
|                         if (flags.hasOwnProperty("hidden")) { | ||||
|                             // Only tabs can be hidden | ||||
|                             if (node.node.type !== 'tab') { | ||||
| @@ -269,8 +261,9 @@ RED.search = (function() { | ||||
|                 } else { | ||||
|                     searchResults.editableList('addItem',{}); | ||||
|                 } | ||||
|             }, | ||||
|             options: getSearchOptions() | ||||
|  | ||||
|  | ||||
|             } | ||||
|         }); | ||||
|         var copySearchContainer = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-caret-right"></button>').appendTo(searchDiv).on('click', function(evt) { | ||||
|             evt.preventDefault(); | ||||
| @@ -331,8 +324,7 @@ RED.search = (function() { | ||||
|                         } | ||||
|                     } else if (!$(children[selected]).hasClass("red-ui-search-historyHeader")) { | ||||
|                         if (currentResults.length > 0) { | ||||
|                             currentIndex = Math.max(0,selected); | ||||
|                             reveal(currentResults[currentIndex].node); | ||||
|                             reveal(currentResults[Math.max(0,selected)].node); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @@ -416,7 +408,6 @@ RED.search = (function() { | ||||
|  | ||||
|                     div.on("click", function(evt) { | ||||
|                         evt.preventDefault(); | ||||
|                         currentIndex = i; | ||||
|                         reveal(node); | ||||
|                     }); | ||||
|                 } | ||||
| @@ -432,59 +423,13 @@ RED.search = (function() { | ||||
|         if (existingIndex > -1) { | ||||
|             searchHistory.splice(existingIndex,1); | ||||
|         } | ||||
|         searchHistory.unshift(searchVal); | ||||
|         $("#red-ui-view-searchtools-search").data("term", searchVal); | ||||
|         activeResults = Object.assign([], currentResults); | ||||
|         hide(null, activeResults.length > 0); | ||||
|         searchHistory.unshift(searchInput.val()); | ||||
|         hide(); | ||||
|         RED.view.reveal(node.id); | ||||
|     } | ||||
|  | ||||
|     function revealPrev() { | ||||
|         if (disabled) { | ||||
|             updateSearchToolbar(); | ||||
|             return; | ||||
|         } | ||||
|         if (!searchResults || !activeResults.length) { | ||||
|             show(); | ||||
|             return; | ||||
|         } | ||||
|         if (currentIndex > 0) { | ||||
|             currentIndex--; | ||||
|         } else { | ||||
|             currentIndex = activeResults.length - 1; | ||||
|         } | ||||
|         const n = activeResults[currentIndex]; | ||||
|         if (n && n.node && n.node.id) { | ||||
|             RED.view.reveal(n.node.id); | ||||
|             $("#red-ui-view-searchtools-prev").trigger("focus"); | ||||
|         } | ||||
|         updateSearchToolbar(); | ||||
|     } | ||||
|     function revealNext() { | ||||
|         if (disabled) { | ||||
|             updateSearchToolbar(); | ||||
|             return; | ||||
|         } | ||||
|         if (!searchResults || !activeResults.length) { | ||||
|             show(); | ||||
|             return; | ||||
|         } | ||||
|         if (currentIndex < activeResults.length - 1) { | ||||
|             currentIndex++ | ||||
|         } else { | ||||
|             currentIndex = 0; | ||||
|         } | ||||
|         const n = activeResults[currentIndex]; | ||||
|         if (n && n.node && n.node.id) { | ||||
|             RED.view.reveal(n.node.id); | ||||
|             $("#red-ui-view-searchtools-next").trigger("focus"); | ||||
|         } | ||||
|         updateSearchToolbar(); | ||||
|     } | ||||
|  | ||||
|     function show(v) { | ||||
|         if (disabled) { | ||||
|             updateSearchToolbar(); | ||||
|             return; | ||||
|         } | ||||
|         if (!visible) { | ||||
| @@ -511,7 +456,7 @@ RED.search = (function() { | ||||
|         searchInput.trigger("focus"); | ||||
|     } | ||||
|  | ||||
|     function hide(el, keepSearchToolbar) { | ||||
|     function hide() { | ||||
|         if (visible) { | ||||
|             visible = false; | ||||
|             $("#red-ui-header-shade").hide(); | ||||
| @@ -525,37 +470,13 @@ RED.search = (function() { | ||||
|                 }); | ||||
|             } | ||||
|             RED.events.emit("search:close"); | ||||
|             if (previousActiveElement && (!keepSearchToolbar || !activeResults.length)) { | ||||
|             if (previousActiveElement) { | ||||
|                 $(previousActiveElement).trigger("focus"); | ||||
|                 previousActiveElement = null; | ||||
|             } | ||||
|             previousActiveElement = null; | ||||
|         }  | ||||
|         if(!keepSearchToolbar) { | ||||
|             clearActiveSearch(); | ||||
|         } | ||||
|         updateSearchToolbar(); | ||||
|         if(keepSearchToolbar && activeResults.length) { | ||||
|             $("#red-ui-view-searchtools-next").trigger("focus"); | ||||
|         } | ||||
|     } | ||||
|     function updateSearchToolbar() { | ||||
|         if (!disabled && currentIndex >= 0 && activeResults && activeResults.length) { | ||||
|             let term = $("#red-ui-view-searchtools-search").data("term") || ""; | ||||
|             if (term.length > 16) { | ||||
|                 term = term.substring(0, 12) + "..." | ||||
|             } | ||||
|             const i18nSearchCounterData = { | ||||
|                 term: term, | ||||
|                 result: (currentIndex + 1), | ||||
|                 count: activeResults.length | ||||
|             } | ||||
|             $("#red-ui-view-searchtools-counter").text(RED._('actions.search-counter', i18nSearchCounterData)); | ||||
|             $("#view-search-tools > :not(:first-child)").show(); //show other tools | ||||
|         } else { | ||||
|             clearActiveSearch(); | ||||
|             $("#view-search-tools > :not(:first-child)").hide(); //hide all but search button | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function clearIndex() { | ||||
|         index = {}; | ||||
|     } | ||||
| @@ -577,29 +498,9 @@ RED.search = (function() { | ||||
|         addItemToIndex(item); | ||||
|     } | ||||
|  | ||||
|     function clearActiveSearch() { | ||||
|         activeResults = []; | ||||
|         currentIndex = 0; | ||||
|         $("#red-ui-view-searchtools-search").data("term", ""); | ||||
|     } | ||||
|  | ||||
|     function getSearchOptions() { | ||||
|         return [ | ||||
|             {label:RED._("search.options.configNodes"), value:"is:config"}, | ||||
|             {label:RED._("search.options.unusedConfigNodes"), value:"is:config is:unused"}, | ||||
|             {label:RED._("search.options.modifiedNodes"), value:"is:modified"}, | ||||
|             {label:RED._("search.options.invalidNodes"), value: "is:invalid"}, | ||||
|             {label:RED._("search.options.uknownNodes"), value: "type:unknown"}, | ||||
|             {label:RED._("search.options.unusedSubflows"), value:"is:subflow is:unused"}, | ||||
|             {label:RED._("search.options.hiddenFlows"), value:"is:hidden"}, | ||||
|         ] | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function init() { | ||||
|         RED.actions.add("core:search",show); | ||||
|         RED.actions.add("core:search-previous",revealPrev); | ||||
|         RED.actions.add("core:search-next",revealNext); | ||||
|  | ||||
|         RED.events.on("editor:open",function() { disabled = true; }); | ||||
|         RED.events.on("editor:close",function() { disabled = false; }); | ||||
| @@ -610,21 +511,11 @@ RED.search = (function() { | ||||
|  | ||||
|         RED.keyboard.add("red-ui-search","escape",hide); | ||||
|  | ||||
|         RED.keyboard.add("view-search-tools","escape",function() { | ||||
|             clearActiveSearch(); | ||||
|             updateSearchToolbar(); | ||||
|         }); | ||||
|  | ||||
|         $("#red-ui-header-shade").on('mousedown',hide); | ||||
|         $("#red-ui-editor-shade").on('mousedown',hide); | ||||
|         $("#red-ui-palette-shade").on('mousedown',hide); | ||||
|         $("#red-ui-sidebar-shade").on('mousedown',hide); | ||||
|  | ||||
|         $("#red-ui-view-searchtools-close").on("click", function close() { | ||||
|             clearActiveSearch();             | ||||
|             updateSearchToolbar(); | ||||
|         }); | ||||
|         $("#red-ui-view-searchtools-close").trigger("click"); | ||||
|  | ||||
|         RED.events.on("workspace:clear", clearIndex); | ||||
|  | ||||
| @@ -650,8 +541,7 @@ RED.search = (function() { | ||||
|         init: init, | ||||
|         show: show, | ||||
|         hide: hide, | ||||
|         search: search, | ||||
|         getSearchOptions: getSearchOptions | ||||
|         search: search | ||||
|     }; | ||||
|  | ||||
| })(); | ||||
|   | ||||
| @@ -29,6 +29,5 @@ RED.state = { | ||||
|     GROUP_DRAGGING: 12, | ||||
|     GROUP_RESIZE: 13, | ||||
|     DETACHED_DRAGGING: 14, | ||||
|     SLICING: 15, | ||||
|     SLICING_JUNCTION: 16 | ||||
|     SLICING: 15 | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,6 @@ RED.statusBar = (function() { | ||||
|     function addWidget(options) { | ||||
|         widgets[options.id] = options; | ||||
|         var el = $('<span class="red-ui-statusbar-widget"></span>'); | ||||
|         el.prop('id', options.id); | ||||
|         options.element.appendTo(el); | ||||
|         if (options.align === 'left') { | ||||
|             leftBucket.append(el); | ||||
|   | ||||
| @@ -983,6 +983,17 @@ RED.subflow = (function() { | ||||
|                         default: inputType | ||||
|                     }) | ||||
|                     input.typedInput('value',val.value) | ||||
|                     if (inputType === 'cred') { | ||||
|                         if (node.credentials) { | ||||
|                             if (node.credentials[tenv.name]) { | ||||
|                                 input.typedInput('value', node.credentials[tenv.name]); | ||||
|                             } else if (node.credentials['has_'+tenv.name]) { | ||||
|                                 input.typedInput('value', "__PWRD__") | ||||
|                             } else { | ||||
|                                 input.typedInput('value', ""); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } else { | ||||
|                     input.val(val.value) | ||||
|                 } | ||||
|   | ||||
| @@ -15,8 +15,6 @@ | ||||
|  **/ | ||||
| RED.sidebar.config = (function() { | ||||
|  | ||||
|     let flashingConfigNode; | ||||
|     let flashingConfigNodeTimer; | ||||
|  | ||||
|     var content = document.createElement("div"); | ||||
|     content.className = "red-ui-sidebar-node-config"; | ||||
| @@ -147,7 +145,6 @@ RED.sidebar.config = (function() { | ||||
|                 var entry = $('<li class="red-ui-palette-node_id_'+node.id.replace(/\./g,"-")+'"></li>').appendTo(list); | ||||
|                 var nodeDiv = $('<div class="red-ui-palette-node-config red-ui-palette-node"></div>').appendTo(entry); | ||||
|                 entry.data('node',node.id); | ||||
|                 nodeDiv.data('node',node.id); | ||||
|                 var label = $('<div class="red-ui-palette-label"></div>').text(label).appendTo(nodeDiv); | ||||
|                 if (node.d) { | ||||
|                     nodeDiv.addClass("red-ui-palette-node-config-disabled"); | ||||
| @@ -353,32 +350,6 @@ RED.sidebar.config = (function() { | ||||
|         RED.popover.tooltip($('#red-ui-sidebar-config-filter-unused'), RED._("sidebar.config.showAllUnusedConfigNodes")); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function flashConfigNode(el) { | ||||
|         if(flashingConfigNode && flashingConfigNode.length) { | ||||
|             //cancel current flashing node before flashing new node | ||||
|             clearInterval(flashingConfigNodeTimer); | ||||
|             flashingConfigNodeTimer = null; | ||||
|             flashingConfigNode.children("div").removeClass('highlighted'); | ||||
|             flashingConfigNode = null; | ||||
|         } | ||||
|         if(!el || !el.children("div").length) { return; } | ||||
|  | ||||
|         flashingConfigNodeTimer = setInterval(function(flashEndTime) { | ||||
|             if (flashEndTime >= Date.now()) { | ||||
|                 const highlighted = el.children("div").hasClass("highlighted"); | ||||
|                 el.children("div").toggleClass('highlighted', !highlighted) | ||||
|             } else { | ||||
|                 clearInterval(flashingConfigNodeTimer); | ||||
|                 flashingConfigNodeTimer = null; | ||||
|                 flashingConfigNode = null; | ||||
|                 el.children("div").removeClass('highlighted'); | ||||
|             } | ||||
|         }, 100, Date.now() + 2200); | ||||
|         flashingConfigNode = el; | ||||
|         el.children("div").addClass('highlighted'); | ||||
|     } | ||||
|  | ||||
|     function show(id) { | ||||
|         if (typeof id === 'boolean') { | ||||
|             if (id) { | ||||
| @@ -403,7 +374,19 @@ RED.sidebar.config = (function() { | ||||
|                 } else if (y<0) { | ||||
|                     scrollWindow.animate({scrollTop: '+='+(y-10)},150); | ||||
|                 } | ||||
|                 flashConfigNode(node, id); | ||||
|                 var flash = 21; | ||||
|                 var flashFunc = function() { | ||||
|                     if ((flash%2)===0) { | ||||
|                         node.removeClass('node_highlighted'); | ||||
|                     } else { | ||||
|                         node.addClass('node_highlighted'); | ||||
|                     } | ||||
|                     flash--; | ||||
|                     if (flash >= 0) { | ||||
|                         setTimeout(flashFunc,100); | ||||
|                     } | ||||
|                 } | ||||
|                 flashFunc(); | ||||
|             },100); | ||||
|         } | ||||
|         RED.sidebar.show("config"); | ||||
|   | ||||
| @@ -370,7 +370,7 @@ RED.sidebar.help = (function() { | ||||
|                 var node = selection.nodes[0]; | ||||
|                 if (node.type === "subflow" && node.direction) { | ||||
|                     // ignore subflow virtual ports | ||||
|                 } else if (node.type !== 'group' && node.type !== 'junction'){ | ||||
|                 } else if (node.type !== 'group'){ | ||||
|                     showNodeTypeHelp(node.type); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -268,7 +268,14 @@ RED.sidebar.info.outliner = (function() { | ||||
|  | ||||
|                 } | ||||
|             }, | ||||
|             options: RED.search.getSearchOptions() | ||||
|             options: [ | ||||
|                 {label:RED._("sidebar.info.search.configNodes"), value:"is:config"}, | ||||
|                 {label:RED._("sidebar.info.search.unusedConfigNodes"), value:"is:config is:unused"}, | ||||
|                 {label:RED._("sidebar.info.search.invalidNodes"), value: "is:invalid"}, | ||||
|                 {label:RED._("sidebar.info.search.uknownNodes"), value: "type:unknown"}, | ||||
|                 {label:RED._("sidebar.info.search.unusedSubflows"), value:"is:subflow is:unused"}, | ||||
|                 {label:RED._("sidebar.info.search.hiddenFlows"), value:"is:hidden"}, | ||||
|             ] | ||||
|         }); | ||||
|  | ||||
|         projectInfo = $('<div class="red-ui-treeList-label red-ui-info-outline-project"><span class="red-ui-treeList-icon"><i class="fa fa-archive"></i></span></div>').hide().appendTo(container) | ||||
| @@ -280,18 +287,15 @@ RED.sidebar.info.outliner = (function() { | ||||
|             data:getFlowData() | ||||
|         }) | ||||
|         treeList.on('treelistselect', function(e,item) { | ||||
|             var node = RED.nodes.node(item.id) || RED.nodes.group(item.id) || RED.nodes.workspace(item.id) || RED.nodes.subflow(item.id); | ||||
|             var node = RED.nodes.node(item.id) || RED.nodes.group(item.id); | ||||
|             if (node) { | ||||
|                 RED.sidebar.info.refresh(node); | ||||
|                 // if (node.type === 'group' || node._def.category !== "config") { | ||||
|                 //     // RED.view.select({nodes:[node]}) | ||||
|                 // } else if (node._def.category === "config") { | ||||
|                 //     RED.sidebar.info.refresh(node); | ||||
|                 // } else { | ||||
|                 //     // RED.view.select({nodes:[]}) | ||||
|                 // } | ||||
|             } else { | ||||
|                 RED.sidebar.info.refresh(null); | ||||
|                 if (node.type === 'group' || node._def.category !== "config") { | ||||
|                     // RED.view.select({nodes:[node]}) | ||||
|                 } else if (node._def.category === "config") { | ||||
|                     RED.sidebar.info.refresh(node); | ||||
|                 } else { | ||||
|                     // RED.view.select({nodes:[]}) | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         treeList.on('treelistconfirm', function(e,item) { | ||||
|   | ||||
| @@ -163,7 +163,6 @@ RED.sidebar.info = (function() { | ||||
|         }); | ||||
|         return el; | ||||
|     } | ||||
|  | ||||
|     function refresh(node) { | ||||
|         if (node === undefined) { | ||||
|             refreshSelection(); | ||||
| @@ -272,7 +271,7 @@ RED.sidebar.info = (function() { | ||||
|                 objectType = "group"; | ||||
|             } | ||||
|             $(propRow.children()[0]).text(RED._("sidebar.info."+objectType)) | ||||
|             RED.utils.createObjectElement(node.id,{sourceId: node.id}).appendTo(propRow.children()[1]); | ||||
|             RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); | ||||
|  | ||||
|             if (node.type === "tab" || node.type === "subflow") { | ||||
|                 // If nothing is selected, but we're on a flow or subflow tab. | ||||
| @@ -302,8 +301,8 @@ RED.sidebar.info = (function() { | ||||
|                 if (typeCounts.groups > 0) { | ||||
|                     $('<div>').text(RED._("clipboard.group",{count:typeCounts.groups})).appendTo(counts); | ||||
|                 } | ||||
|             } else if (node.type === 'junction') { | ||||
|                 propertiesPanelHeaderHelp.hide(); | ||||
|  | ||||
|  | ||||
|             } else { | ||||
|                 propertiesPanelHeaderHelp.show(); | ||||
|  | ||||
| @@ -366,7 +365,7 @@ RED.sidebar.info = (function() { | ||||
|  | ||||
|                                     } | ||||
|                                 } else { | ||||
|                                     RED.utils.createObjectElement(val,{sourceId: node.id}).appendTo(propRow.children()[1]); | ||||
|                                     RED.utils.createObjectElement(val).appendTo(propRow.children()[1]); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
| @@ -432,7 +431,6 @@ RED.sidebar.info = (function() { | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function setInfoText(infoText,target) { | ||||
|         var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target); | ||||
|         info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" ); | ||||
| @@ -449,7 +447,6 @@ RED.sidebar.info = (function() { | ||||
|                 $(this).toggleClass('expanded',!isExpanded); | ||||
|             }) | ||||
|     } | ||||
|  | ||||
|     var tips = (function() { | ||||
|         var enabled = true; | ||||
|         var startDelay = 1000; | ||||
|   | ||||
| @@ -169,13 +169,7 @@ | ||||
|                         raiseTrayZ(); | ||||
|                         handleWindowResize();//cause call to monaco layout | ||||
|                     },200); | ||||
|                     if(!options.hasOwnProperty("focusElement")) { | ||||
|                         //focusElement is not inside options - default to focusing 1st | ||||
|                         body.find(":focusable:first").trigger("focus"); | ||||
|                     } else if(options.focusElement !== false) { | ||||
|                         //focusElement IS specified, focus that instead (if not false) | ||||
|                         $(options.focusElement).trigger("focus"); | ||||
|                     }  | ||||
|                     body.find(":focusable:first").trigger("focus"); | ||||
|  | ||||
|                 },150); | ||||
|                 el.css({right:0}); | ||||
|   | ||||
| @@ -171,21 +171,17 @@ RED.typeSearch = (function() { | ||||
|                 var div = $('<div>',{class:"red-ui-search-result"}).appendTo(container); | ||||
|  | ||||
|                 var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div); | ||||
|                 if (object.type === "junction") { | ||||
|                     nodeDiv.addClass("red-ui-palette-icon-junction"); | ||||
|                 } else { | ||||
|                     var colour = RED.utils.getNodeColor(object.type,def); | ||||
|                     nodeDiv.css('backgroundColor',colour); | ||||
|                 } | ||||
|                 var colour = RED.utils.getNodeColor(object.type,def); | ||||
|                 var icon_url = RED.utils.getNodeIcon(def); | ||||
|                 nodeDiv.css('backgroundColor',colour); | ||||
|  | ||||
|                 var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); | ||||
|                 RED.utils.createIconElement(icon_url, iconContainer, false); | ||||
|  | ||||
|                 if (object.type !== "junction" && def.inputs > 0) { | ||||
|                 if (def.inputs > 0) { | ||||
|                     $('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv); | ||||
|                 } | ||||
|                 if (object.type !== "junction" && def.outputs > 0) { | ||||
|                 if (def.outputs > 0) { | ||||
|                     $('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv); | ||||
|                 } | ||||
|  | ||||
| @@ -317,8 +313,8 @@ RED.typeSearch = (function() { | ||||
|         return !filter || | ||||
|             ( | ||||
|                 (!filter.type || type === filter.type) && | ||||
|                 (!filter.input || type === 'junction' || def.inputs > 0) && | ||||
|                 (!filter.output || type === 'junction' || def.outputs > 0) | ||||
|                 (!filter.input || def.inputs > 0) && | ||||
|                 (!filter.output || def.outputs > 0) | ||||
|             ) | ||||
|     } | ||||
|     function refreshTypeList(opts) { | ||||
| @@ -327,7 +323,7 @@ RED.typeSearch = (function() { | ||||
|         searchInput.searchBox('value','').focus(); | ||||
|         selected = -1; | ||||
|         var common = [ | ||||
|             'inject','debug','function','change','switch','junction' | ||||
|             'inject','debug','function','change','switch' | ||||
|         ].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); }); | ||||
|  | ||||
|         var recentlyUsed = Object.keys(typesUsed); | ||||
| @@ -352,9 +348,6 @@ RED.typeSearch = (function() { | ||||
|         var index = 0; | ||||
|         for(i=0;i<common.length;i++) { | ||||
|             var itemDef = RED.nodes.getType(common[i]); | ||||
|             if (common[i] === 'junction') { | ||||
|                 itemDef = { inputs:1, outputs: 1, label: 'junction', type: 'junction'} | ||||
|             } | ||||
|             if (itemDef) { | ||||
|                 item = { | ||||
|                     type: common[i], | ||||
|   | ||||
| @@ -365,16 +365,7 @@ RED.utils = (function() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a DOM element representation of obj - as used by Debug sidebar etc | ||||
|      * | ||||
|      * @params obj - the data to display | ||||
|      * @params options - a bag of options | ||||
|      * | ||||
|      * - If you want the Copy Value button, then set `sourceId` | ||||
|      * - If you want the Copy Path button, also set `path` to the value to be copied | ||||
|      */ | ||||
|     function createObjectElement(obj,options) { | ||||
|     function buildMessageElement(obj,options) { | ||||
|         options = options || {}; | ||||
|         var key = options.key; | ||||
|         var typeHint = options.typeHint; | ||||
| @@ -564,7 +555,7 @@ RED.utils = (function() { | ||||
|                     if (fullLength <= 10) { | ||||
|                         for (i=0;i<fullLength;i++) { | ||||
|                             row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(arrayRows); | ||||
|                             subElements[path+"["+i+"]"] = createObjectElement( | ||||
|                             subElements[path+"["+i+"]"] = buildMessageElement( | ||||
|                                 data[i], | ||||
|                                 { | ||||
|                                     key: ""+i, | ||||
| @@ -594,7 +585,7 @@ RED.utils = (function() { | ||||
|                                 return function() { | ||||
|                                     for (var i=min;i<=max;i++) { | ||||
|                                         var row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(parent); | ||||
|                                         subElements[path+"["+i+"]"] = createObjectElement( | ||||
|                                         subElements[path+"["+i+"]"] = buildMessageElement( | ||||
|                                             data[i], | ||||
|                                             { | ||||
|                                                 key: ""+i, | ||||
| @@ -650,7 +641,7 @@ RED.utils = (function() { | ||||
|                                 newPath += "[\""+keys[i].replace(/"/,"\\\"")+"\"]" | ||||
|                             } | ||||
|                         } | ||||
|                         subElements[newPath] = createObjectElement( | ||||
|                         subElements[newPath] = buildMessageElement( | ||||
|                             data[keys[i]], | ||||
|                             { | ||||
|                                 key: keys[i], | ||||
| @@ -1028,8 +1019,6 @@ RED.utils = (function() { | ||||
|             return "font-awesome/fa-object-ungroup"; | ||||
|         } else if (node && node.type === 'group') { | ||||
|             return "font-awesome/fa-object-group" | ||||
|         } else if ((node && node.type === 'junction') || (def.type === "junction") ) { | ||||
|             return "font-awesome/fa-circle-o" | ||||
|         } else if (def.category === 'config') { | ||||
|             return RED.settings.apiRootUrl+"icons/node-red/cog.svg" | ||||
|         } else if (node && node.type === 'tab') { | ||||
| @@ -1095,8 +1084,6 @@ RED.utils = (function() { | ||||
|             l = node.label || defaultLabel | ||||
|         } else if (node.type === 'group') { | ||||
|             l = node.name || defaultLabel | ||||
|         } else if (node.type === 'junction') { | ||||
|             l = 'junction' | ||||
|         } else { | ||||
|             l = node._def.label; | ||||
|             try { | ||||
| @@ -1109,18 +1096,6 @@ RED.utils = (function() { | ||||
|         return RED.text.bidi.enforceTextDirectionWithUCC(l); | ||||
|     } | ||||
|  | ||||
|     function getPaletteLabel(nodeType, def) { | ||||
|         var label = nodeType; | ||||
|         if (typeof def.paletteLabel !== "undefined") { | ||||
|             try { | ||||
|                 label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||""; | ||||
|             } catch(err) { | ||||
|                 console.log("Definition error: "+nodeType+".paletteLabel",err); | ||||
|             } | ||||
|         } | ||||
|         return label | ||||
|     } | ||||
|  | ||||
|     var nodeColorCache = {}; | ||||
|     function clearNodeColorCache() { | ||||
|         nodeColorCache = {}; | ||||
| @@ -1263,8 +1238,6 @@ RED.utils = (function() { | ||||
|             nodeDiv.addClass("red-ui-palette-icon-selection"); | ||||
|         } else if (node.type === "group") { | ||||
|             nodeDiv.addClass("red-ui-palette-icon-group"); | ||||
|         } else if (node.type === "junction") { | ||||
|             nodeDiv.addClass("red-ui-palette-icon-junction"); | ||||
|         } else if (node.type === 'tab') { | ||||
|             nodeDiv.addClass("red-ui-palette-icon-flow"); | ||||
|         } else { | ||||
| @@ -1396,7 +1369,7 @@ RED.utils = (function() { | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         createObjectElement: createObjectElement, | ||||
|         createObjectElement: buildMessageElement, | ||||
|         getMessageProperty: getMessageProperty, | ||||
|         setMessageProperty: setMessageProperty, | ||||
|         normalisePropertyExpression: normalisePropertyExpression, | ||||
| @@ -1406,7 +1379,6 @@ RED.utils = (function() { | ||||
|         getNodeIcon: getNodeIcon, | ||||
|         getNodeLabel: getNodeLabel, | ||||
|         getNodeColor: getNodeColor, | ||||
|         getPaletteLabel: getPaletteLabel, | ||||
|         clearNodeColorCache: clearNodeColorCache, | ||||
|         addSpinnerOverlay: addSpinnerOverlay, | ||||
|         decodeObject: decodeObject, | ||||
|   | ||||
| @@ -809,244 +809,6 @@ RED.view.tools = (function() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Splits selected wires and re-joins them with link-out+link-in | ||||
|      * @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes. | ||||
|      */ | ||||
|     function splitWiresWithLinkNodes(wires) { | ||||
|         let wiresToSplit = wires || RED.view.selection().links; | ||||
|         if (!Array.isArray(wiresToSplit)) { | ||||
|             wiresToSplit = [wiresToSplit]; | ||||
|         } | ||||
|         if (wiresToSplit.length < 1) { | ||||
|             return; //nothing selected | ||||
|         } | ||||
|  | ||||
|         const history = { | ||||
|             t: 'multi', | ||||
|             events: [], | ||||
|             dirty: RED.nodes.dirty() | ||||
|         } | ||||
|         const nodeSrcMap = {}; | ||||
|         const nodeTrgMap = {}; | ||||
|         const _gridSize = RED.view.gridSize(); | ||||
|  | ||||
|         for (let wireIdx = 0; wireIdx < wiresToSplit.length; wireIdx++) { | ||||
|             const wire = wiresToSplit[wireIdx]; | ||||
|  | ||||
|             //get source and target nodes of this wire link | ||||
|             const nSrc = wire.source; | ||||
|             const nTrg = wire.target; | ||||
|  | ||||
|             var updateNewNodePosXY = function (origNode, newNode, alignLeft, snap, yOffset) { | ||||
|                 const nnSize = RED.view.calculateNodeDimensions(newNode); | ||||
|                 newNode.w = nnSize[0]; | ||||
|                 newNode.h = nnSize[1]; | ||||
|                 const coords = { x: origNode.x || 0, y: origNode.y || 0, w: origNode.w || RED.view.node_width, h: origNode.h || RED.view.node_height }; | ||||
|                 const x = coords.x - (coords.w/2.0); | ||||
|                 if (alignLeft) { | ||||
|                     coords.x = x - _gridSize - (newNode.w/2.0); | ||||
|                 } else { | ||||
|                     coords.x = x + coords.w + _gridSize + (newNode.w/2.0); | ||||
|                 } | ||||
|                 newNode.x = coords.x; | ||||
|                 newNode.y = coords.y; | ||||
|                 if (snap !== false) { | ||||
|                     const offsets = RED.view.tools.calculateGridSnapOffsets(newNode); | ||||
|                     newNode.x -= offsets.x; | ||||
|                     newNode.y -= offsets.y; | ||||
|                 } | ||||
|                 newNode.y += (yOffset || 0); | ||||
|             } | ||||
|             const srcPort = (wire.sourcePort || 0); | ||||
|             let linkOutMapId = nSrc.id + ':' + srcPort; | ||||
|             let nnLinkOut = nodeSrcMap[linkOutMapId]; | ||||
|             //Create a Link Out if one is not already present | ||||
|             if(!nnLinkOut) { | ||||
|                 const nLinkOut = RED.view.createNode("link out"); //create link node | ||||
|                 nnLinkOut = nLinkOut.node; | ||||
|                 nodeSrcMap[linkOutMapId] = nnLinkOut; | ||||
|                 let yOffset = 0; | ||||
|                 if(nSrc.outputs > 1) { | ||||
|  | ||||
|                     const CENTER_PORT = (((nSrc.outputs-1) / 2) + 1); | ||||
|                     const offsetCount = Math.abs(CENTER_PORT - (srcPort + 1)); | ||||
|                     yOffset = (_gridSize * 2 * offsetCount); | ||||
|                     if((srcPort + 1) < CENTER_PORT) { | ||||
|                         yOffset = -yOffset; | ||||
|                     } | ||||
|                     updateNewNodePosXY(nSrc, nnLinkOut, false, false, yOffset); | ||||
|                 } else { | ||||
|                     updateNewNodePosXY(nSrc, nnLinkOut, false, RED.view.snapGrid, yOffset); | ||||
|                 } | ||||
|                 //add created node | ||||
|                 RED.nodes.add(nnLinkOut); | ||||
|                 RED.editor.validateNode(nnLinkOut); | ||||
|                 history.events.push(nLinkOut.historyEvent); | ||||
|                 //connect node to link node | ||||
|                 const link = { | ||||
|                     source: nSrc, | ||||
|                     sourcePort: wire.sourcePort || 0, | ||||
|                     target: nnLinkOut | ||||
|                 }; | ||||
|                 RED.nodes.addLink(link); | ||||
|                 history.events.push({ | ||||
|                     t: 'add', | ||||
|                     links: [link], | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             let nnLinkIn = nodeTrgMap[nTrg.id]; | ||||
|             //Create a Link In if one is not already present | ||||
|             if(!nnLinkIn) { | ||||
|                 const nLinkIn = RED.view.createNode("link in"); //create link node | ||||
|                 nnLinkIn = nLinkIn.node; | ||||
|                 nodeTrgMap[nTrg.id] = nnLinkIn; | ||||
|                 updateNewNodePosXY(nTrg, nnLinkIn, true, RED.view.snapGrid, 0); | ||||
|                 //add created node | ||||
|                 RED.nodes.add(nnLinkIn); | ||||
|                 RED.editor.validateNode(nnLinkIn); | ||||
|                 history.events.push(nLinkIn.historyEvent); | ||||
|                 //connect node to link node | ||||
|                 const link = { | ||||
|                     source: nnLinkIn, | ||||
|                     sourcePort: 0, | ||||
|                     target: nTrg | ||||
|                 }; | ||||
|                 RED.nodes.addLink(link); | ||||
|                 history.events.push({ | ||||
|                     t: 'add', | ||||
|                     links: [link], | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             //connect the link out/link in virtual wires | ||||
|             if(nnLinkIn.links.indexOf(nnLinkOut.id) == -1) { | ||||
|                 nnLinkIn.links.push(nnLinkOut.id); | ||||
|             } | ||||
|             if(nnLinkOut.links.indexOf(nnLinkIn.id) == -1) { | ||||
|                 nnLinkOut.links.push(nnLinkIn.id); | ||||
|             } | ||||
|  | ||||
|             //delete the original wire | ||||
|             RED.nodes.removeLink(wire); | ||||
|             history.events.push({ | ||||
|                 t: "delete", | ||||
|                 links: [wire] | ||||
|             }); | ||||
|         } | ||||
|         //add all history events to stack | ||||
|         RED.history.push(history); | ||||
|  | ||||
|         //select all downstream of new link-in nodes so user can drag to new location | ||||
|         RED.view.clearSelection(); | ||||
|         RED.view.select({nodes: Object.values(nodeTrgMap) }); | ||||
|         selectConnected("down"); | ||||
|  | ||||
|         //update the view | ||||
|         RED.nodes.dirty(true); | ||||
|         RED.view.redraw(true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Calculate the required offsets to snap a node | ||||
|      * @param {Object} node The node to calculate grid snap offsets for | ||||
|      * @param {Object} [options] Options: `align` can be "nearest", "left" or "right" | ||||
|      * @returns `{x:number, y:number}`  as the offsets to deduct from `x` and `y` | ||||
|      */ | ||||
|     function calculateGridSnapOffsets(node, options) { | ||||
|         options = options || { align: "nearest" }; | ||||
|         const gridOffset = { x: 0, y: 0 }; | ||||
|         const gridSize = RED.view.gridSize(); | ||||
|         const offsetLeft = node.x - (gridSize * Math.round((node.x - node.w / 2) / gridSize) + node.w / 2); | ||||
|         const offsetRight = node.x - (gridSize * Math.round((node.x + node.w / 2) / gridSize) - node.w / 2); | ||||
|         gridOffset.x = offsetRight; | ||||
|         if (options.align === "right") { | ||||
|             //skip - already set to right | ||||
|         } else if (options.align === "left" || Math.abs(offsetLeft) < Math.abs(offsetRight)) { | ||||
|             gridOffset.x = offsetLeft; | ||||
|         } | ||||
|         gridOffset.y = node.y - (gridSize * Math.round(node.y / gridSize)); | ||||
|         return gridOffset; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Generate names for the select nodes. | ||||
|      *  - it only sets the name if it is currently blank | ||||
|      *  - it uses `<paletteLabel> <N>` - where N is the next available integer that | ||||
|      *    doesn't clash with any existing nodes of that type | ||||
|      * @param {Object} node The node to set the name of - if not provided, uses current selection | ||||
|      */ | ||||
|     function generateNodeNames(node, options) { | ||||
|         options = options || { | ||||
|             renameBlank: true, | ||||
|             renameClash: true, | ||||
|             generateHistory: true | ||||
|         } | ||||
|         let nodes = node; | ||||
|         if (node) { | ||||
|             if (!Array.isArray(node)) { | ||||
|                 nodes = [ node ] | ||||
|             } | ||||
|         } else { | ||||
|             nodes = RED.view.selection().nodes; | ||||
|         } | ||||
|         if (nodes && nodes.length > 0) { | ||||
|             // Generate history event if using the workspace selection, | ||||
|             // or if the provided node already exists | ||||
|             const generateHistory = options.generateHistory && (!node || !!RED.nodes.node(node.id)) | ||||
|             const historyEvents = [] | ||||
|             const typeIndex = {} | ||||
|             let changed = false; | ||||
|             nodes.forEach(n => { | ||||
|                 const nodeDef = n._def || RED.nodes.getType(n.type) | ||||
|                 if (nodeDef && nodeDef.defaults && nodeDef.defaults.name) { | ||||
|                     const paletteLabel = RED.utils.getPaletteLabel(n.type, nodeDef) | ||||
|                     const defaultNodeNameRE = new RegExp('^'+paletteLabel+' (\\d+)$') | ||||
|                     if (!typeIndex.hasOwnProperty(n.type)) { | ||||
|                         const existingNodes = RED.nodes.filterNodes({type: n.type}) | ||||
|                         let maxNameNumber = 0; | ||||
|                         existingNodes.forEach(n => { | ||||
|                             let match = defaultNodeNameRE.exec(n.name) | ||||
|                             if (match) { | ||||
|                                 let nodeNumber = parseInt(match[1]) | ||||
|                                 if (nodeNumber > maxNameNumber) { | ||||
|                                     maxNameNumber = nodeNumber | ||||
|                                 } | ||||
|                             } | ||||
|                         }) | ||||
|                         typeIndex[n.type] = maxNameNumber + 1 | ||||
|                     } | ||||
|                     if ((options.renameBlank && n.name === '') || (options.renameClash && defaultNodeNameRE.test(n.name))) { | ||||
|                         if (generateHistory) { | ||||
|                             historyEvents.push({ | ||||
|                                 t:'edit', | ||||
|                                 node: n, | ||||
|                                 changes: { name: n.name }, | ||||
|                                 dirty: RED.nodes.dirty(), | ||||
|                                 changed: n.changed | ||||
|                             }) | ||||
|                         } | ||||
|                         n.name = paletteLabel+" "+typeIndex[n.type] | ||||
|                         n.dirty = true | ||||
|                         typeIndex[n.type]++ | ||||
|                         changed = true | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|             if (changed) { | ||||
|                 if (historyEvents.length > 0) { | ||||
|                     RED.history.push({ | ||||
|                         t: 'multi', | ||||
|                         events: historyEvents | ||||
|                     }) | ||||
|                 } | ||||
|                 RED.nodes.dirty(true) | ||||
|                 RED.view.redraw() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         init: function() { | ||||
|             RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); }) | ||||
| @@ -1108,10 +870,6 @@ RED.view.tools = (function() { | ||||
|             RED.actions.add("core:wire-series-of-nodes", function() { wireSeriesOfNodes() }) | ||||
|             RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() }) | ||||
|  | ||||
|             RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() }); | ||||
|  | ||||
|             RED.actions.add("core:generate-node-names", generateNodeNames ) | ||||
|  | ||||
|             // RED.actions.add("core:add-node", function() { addNode() }) | ||||
|         }, | ||||
|         /** | ||||
| @@ -1123,8 +881,7 @@ RED.view.tools = (function() { | ||||
|          * @param  {Number} dx | ||||
|          * @param  {Number} dy | ||||
|          */ | ||||
|         moveSelection: moveSelection, | ||||
|         calculateGridSnapOffsets: calculateGridSnapOffsets | ||||
|         moveSelection: moveSelection | ||||
|     } | ||||
|  | ||||
| })(); | ||||
|   | ||||
| @@ -24,9 +24,6 @@ RED.workspaces = (function() { | ||||
|     var hideStack = []; | ||||
|     var viewStackPos = 0; | ||||
|  | ||||
|     let flashingTab; | ||||
|     let flashingTabTimer; | ||||
|  | ||||
|     function addToViewStack(id) { | ||||
|         if (viewStackPos !== viewStack.length) { | ||||
|             viewStack.splice(viewStackPos); | ||||
| @@ -284,9 +281,22 @@ RED.workspaces = (function() { | ||||
|                         onselect: "core:show-last-hidden-flow" | ||||
|                     } | ||||
|                 ] | ||||
|                 if (hideStack.length > 0) { | ||||
|                 let hiddenFlows = new Set() | ||||
|                 for (let i = 0; i < hideStack.length; i++) { | ||||
|                     let ids = hideStack[i] | ||||
|                     if (!Array.isArray(ids)) { | ||||
|                         ids = [ids] | ||||
|                     } | ||||
|                     ids.forEach(id => { | ||||
|                         if (RED.nodes.workspace(id)) { | ||||
|                             hiddenFlows.add(id) | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
|                 const flowCount = hiddenFlows.size; | ||||
|                 if (flowCount > 0) { | ||||
|                     menuItems.unshift({ | ||||
|                         label: RED._("workspace.hiddenFlows",{count: hideStack.length}), | ||||
|                         label: RED._("workspace.hiddenFlows",{count: flowCount}), | ||||
|                         onselect: "core:list-hidden-flows" | ||||
|                     }) | ||||
|                 } | ||||
| @@ -431,9 +441,6 @@ RED.workspaces = (function() { | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         RED.actions.add("core:list-modified-nodes",function() { | ||||
|             RED.actions.invoke("core:search","is:modified "); | ||||
|         }) | ||||
|         RED.actions.add("core:list-hidden-flows",function() { | ||||
|             RED.actions.invoke("core:search","is:hidden "); | ||||
|         }) | ||||
| @@ -534,31 +541,6 @@ RED.workspaces = (function() { | ||||
|         workspace_tabs.order(order); | ||||
|     } | ||||
|  | ||||
|     function flashTab(tabId) { | ||||
|         if(flashingTab && flashingTab.length) { | ||||
|             //cancel current flashing node before flashing new node | ||||
|             clearInterval(flashingTabTimer); | ||||
|             flashingTabTimer = null; | ||||
|             flashingTab.removeClass('highlighted'); | ||||
|             flashingTab = null; | ||||
|         } | ||||
|         let tab = $("#red-ui-tab-" + tabId); | ||||
|         if(!tab || !tab.length) { return; } | ||||
|  | ||||
|         flashingTabTimer = setInterval(function(flashEndTime) { | ||||
|             if (flashEndTime >= Date.now()) { | ||||
|                 const highlighted = tab.hasClass("highlighted"); | ||||
|                 tab.toggleClass('highlighted', !highlighted) | ||||
|             } else { | ||||
|                 clearInterval(flashingTabTimer); | ||||
|                 flashingTabTimer = null; | ||||
|                 flashingTab = null; | ||||
|                 tab.removeClass('highlighted'); | ||||
|             } | ||||
|         }, 100, Date.now() + 2200); | ||||
|         flashingTab = tab; | ||||
|         tab.addClass('highlighted'); | ||||
|     } | ||||
|     return { | ||||
|         init: init, | ||||
|         add: addWorkspace, | ||||
| @@ -591,7 +573,7 @@ RED.workspaces = (function() { | ||||
|         isHidden: function(id) { | ||||
|             return hideStack.includes(id) | ||||
|         }, | ||||
|         show: function(id,skipStack,unhideOnly,flash) { | ||||
|         show: function(id,skipStack,unhideOnly) { | ||||
|             if (!workspace_tabs.contains(id)) { | ||||
|                 var sf = RED.nodes.subflow(id); | ||||
|                 if (sf) { | ||||
| @@ -613,9 +595,6 @@ RED.workspaces = (function() { | ||||
|                 } | ||||
|                 workspace_tabs.activateTab(id); | ||||
|             } | ||||
|             if(flash) { | ||||
|                 flashTab(id.replace(".","-")) | ||||
|             } | ||||
|         }, | ||||
|         refresh: function() { | ||||
|             RED.nodes.eachWorkspace(function(ws) { | ||||
|   | ||||
| @@ -118,26 +118,20 @@ RED.user = (function() { | ||||
|                     }); | ||||
|  | ||||
|                 } else if (data.type == "strategy") { | ||||
|                     var sessionMessage = /[?&]session_message=(.*?)(?:$|&)/.exec(window.location.search); | ||||
|                     RED.sessionMessages = RED.sessionMessages || []; | ||||
|                     if (sessionMessage) { | ||||
|                         RED.sessionMessages.push(decodeURIComponent(sessionMessage[1])); | ||||
|                         if (history.pushState) { | ||||
|                             var newurl = window.location.protocol+"//"+window.location.host+window.location.pathname | ||||
|                             window.history.replaceState({ path: newurl }, "", newurl); | ||||
|                         } else { | ||||
|                             window.location.search = ""; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (RED.sessionMessages.length === 0 && data.autoLogin) { | ||||
|                         document.location = data.loginRedirect | ||||
|                         return | ||||
|                     } | ||||
|  | ||||
|                     i = 0; | ||||
|                     for (;i<data.prompts.length;i++) { | ||||
|                         var field = data.prompts[i]; | ||||
|                         var sessionMessage = /[?&]session_message=(.*?)(?:$|&)/.exec(window.location.search); | ||||
|                         if (sessionMessage) { | ||||
|                             RED.sessionMessages = RED.sessionMessages || []; | ||||
|                             RED.sessionMessages.push(sessionMessage[1]); | ||||
|                             if (history.pushState) { | ||||
|                                 var newurl = window.location.protocol+"//"+window.location.host+window.location.pathname | ||||
|                                 window.history.replaceState({ path: newurl }, "", newurl); | ||||
|                             } else { | ||||
|                                 window.location.search = ""; | ||||
|                             } | ||||
|                         } | ||||
|                         if (RED.sessionMessages) { | ||||
|                             var sessionMessages = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields"); | ||||
|                             RED.sessionMessages.forEach(function (msg) { | ||||
|   | ||||
| @@ -14,72 +14,22 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
| RED.validators = { | ||||
|     number: function(blankAllowed,mopt){ | ||||
|         return function(v, opt) { | ||||
|             if ((blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v))) { | ||||
|     number: function(blankAllowed){return function(v) { return (blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v));}}, | ||||
|     regex: function(re){return function(v) { return re.test(v);}}, | ||||
|     typedInput: function(ptypeName,isConfig) { return function(v) { | ||||
|         var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName]; | ||||
|         if (ptype === 'json') { | ||||
|             try { | ||||
|                 JSON.parse(v); | ||||
|                 return true; | ||||
|             } catch(err) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (opt && opt.label) { | ||||
|                 return RED._("validator.errors.invalid-num-prop", { | ||||
|                     prop: opt.label | ||||
|                 }); | ||||
|             } | ||||
|             return opt ? RED._("validator.errors.invalid-num") : false; | ||||
|         }; | ||||
|     }, | ||||
|     regex: function(re, mopt) { | ||||
|         return function(v, opt) { | ||||
|             if (re.test(v)) { | ||||
|                 return true; | ||||
|             } | ||||
|             if (opt && opt.label) { | ||||
|                 return RED._("validator.errors.invalid-regex-prop", { | ||||
|                     prop: opt.label | ||||
|                 }); | ||||
|             } | ||||
|             return opt ? RED._("validator.errors.invalid-regexp") : false; | ||||
|         }; | ||||
|     }, | ||||
|     typedInput: function(ptypeName,isConfig,mopt) { | ||||
|         return function(v, opt) { | ||||
|             var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName]; | ||||
|             if (ptype === 'json') { | ||||
|                 try { | ||||
|                     JSON.parse(v); | ||||
|                     return true; | ||||
|                 } catch(err) { | ||||
|                     if (opt && opt.label) { | ||||
|                         return RED._("validator.errors.invalid-json-prop", { | ||||
|                             error: err.message, | ||||
|                             prop: opt.label, | ||||
|                         }); | ||||
|                     } | ||||
|                     return opt ? RED._("validator.errors.invalid-json", { | ||||
|                         error: err.message | ||||
|                     }) : false; | ||||
|                 } | ||||
|             } else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) { | ||||
|                 if (RED.utils.validatePropertyExpression(v)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (opt && opt.label) { | ||||
|                     return RED._("validator.errors.invalid-prop-prop", { | ||||
|                         prop: opt.label | ||||
|                     }); | ||||
|                 } | ||||
|                 return opt ? RED._("validator.errors.invalid-prop") : false; | ||||
|             } else if (ptype === 'num') { | ||||
|                 if (/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (opt && opt.label) { | ||||
|                     return RED._("validator.errors.invalid-num-prop", { | ||||
|                         prop: opt.label | ||||
|                     }); | ||||
|                 } | ||||
|                 return opt ? RED._("validator.errors.invalid-num") : false; | ||||
|             } | ||||
|             return true; | ||||
|         }; | ||||
|     } | ||||
|         } else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) { | ||||
|             return RED.utils.validatePropertyExpression(v); | ||||
|         } else if (ptype === 'num') { | ||||
|             return /^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v); | ||||
|         } | ||||
|         return true; | ||||
|     }} | ||||
| }; | ||||
|   | ||||
| @@ -142,16 +142,9 @@ body { | ||||
|         line-height: 14px; | ||||
|         vertical-align: text-top; | ||||
|         margin-top: 0px; | ||||
|         -webkit-mask-image: url(images/spin.svg); | ||||
|         mask-image: url(images/spin.svg); | ||||
|         -webkit-mask-size: contain; | ||||
|         mask-size: contain; | ||||
|         -webkit-mask-position: 50% 50%; | ||||
|         mask-position: 50% 50%; | ||||
|         -webkit-mask-repeat: no-repeat; | ||||
|         mask-repeat: no-repeat; | ||||
|         background-color: $spinner-color; | ||||
|         } | ||||
|         background: url(images/spin.svg) no-repeat 50% 50%; | ||||
|         background-size: contain | ||||
|     } | ||||
|  | ||||
|     .red-ui-font-code { | ||||
|         font-family: $monospace-font; | ||||
|   | ||||
| @@ -300,14 +300,6 @@ $group-default-label-color: #a4a4a4; | ||||
| $tourGuide-border: #c56c6c; | ||||
| $tourGuide-heading-color: #c56c6c; | ||||
|  | ||||
| $grip-color: #ccc; | ||||
|  | ||||
| $icons-flow-color: #808080; | ||||
|  | ||||
| $spinner-color: #999; | ||||
|  | ||||
| $tab-icon-color: #dedede; | ||||
|  | ||||
| // Deprecated | ||||
| $text-color-green: $text-color-success; | ||||
| $info-text-code-color: $text-color-code; | ||||
|   | ||||
| @@ -123,20 +123,17 @@ | ||||
|     background: $debug-message-background; | ||||
|     font-size: 11px; | ||||
|     color: $secondary-text-color-inactive; | ||||
|     overflow-wrap: anywhere; | ||||
| } | ||||
| .red-ui-debug-msg-date { | ||||
|     padding: 1px 10px 1px 0px; | ||||
|     white-space: nowrap; | ||||
|     padding: 1px 5px 1px 1px; | ||||
| } | ||||
| .red-ui-debug-msg-topic { | ||||
|     display: block; | ||||
|     color: $debug-message-text-color-meta; | ||||
| } | ||||
| .red-ui-debug-msg-name { | ||||
|     padding: 1px 0px; | ||||
|     padding: 1px 5px; | ||||
|     color: $secondary-text-color-inactive; | ||||
|     white-space: nowrap; | ||||
| } | ||||
| .red-ui-debug-msg-tools { | ||||
|     position: absolute; | ||||
|   | ||||
| @@ -149,27 +149,11 @@ | ||||
|     bottom: 0px; | ||||
|     width: 7px; | ||||
|     left: -9px; | ||||
|     background-color: $primary-background; | ||||
|     background: $primary-background url(images/grip.png) no-repeat 50% 50%; | ||||
|     cursor: col-resize; | ||||
|     border-left: 1px solid $primary-border-color; | ||||
|     box-shadow: -1px 0 6px $shadow; | ||||
|  | ||||
|     &:before { | ||||
|         content: ''; | ||||
|         display: block; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         -webkit-mask-image: url(images/grip.svg); | ||||
|         mask-image: url(images/grip.svg); | ||||
|         -webkit-mask-size: auto; | ||||
|         mask-size: auto; | ||||
|         -webkit-mask-position: 50% 50%; | ||||
|         mask-position: 50% 50%; | ||||
|         -webkit-mask-repeat: no-repeat; | ||||
|         mask-repeat: no-repeat; | ||||
|         background-color: $grip-color; | ||||
|     } | ||||
|      | ||||
|     &.red-ui-tray-resize-maximised { | ||||
|         background: $primary-background; | ||||
|         cursor: default; | ||||
| @@ -701,10 +685,6 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle { | ||||
|         border-color: $list-item-background-hover; | ||||
|         border-style: dashed; | ||||
|     } | ||||
|     &.readonly { | ||||
|         cursor: pointer; | ||||
|         pointer-events: none; | ||||
|     } | ||||
| } | ||||
| .red-ui-editor-type-json-editor-item-gutter { | ||||
|     width: 48px; | ||||
| @@ -724,10 +704,6 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle { | ||||
|     > span, > button { | ||||
|         display: none; | ||||
|     } | ||||
|     &.readonly { | ||||
|         cursor: pointer; | ||||
|         pointer-events: none; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -379,17 +379,3 @@ g.red-ui-flow-link-unknown path.red-ui-flow-link-line { | ||||
|     white-space: pre; | ||||
|     @include disable-selection; | ||||
| } | ||||
| .red-ui-flow-junction-background { | ||||
|     stroke: $node-border; | ||||
|     stroke-width: 1; | ||||
|     fill: $node-port-background; | ||||
|     cursor: crosshair; | ||||
| } | ||||
| .red-ui-flow-junction-hovered { | ||||
|     stroke: $port-selected-color; | ||||
|     fill:  $port-selected-color; | ||||
| } | ||||
| .red-ui-flow-junction.selected .red-ui-flow-junction-background { | ||||
|     stroke: $port-selected-color; | ||||
|     // fill:  $port-selected-color; | ||||
| } | ||||
|   | ||||
| @@ -27,10 +27,10 @@ | ||||
| } | ||||
|  | ||||
| .ui-widget.ui-widget-content { | ||||
| 	border: 1px solid $tertiary-border-color; | ||||
|     border: 1px solid $tertiary-border-color; | ||||
| } | ||||
| .ui-widget-content { | ||||
| 	border: 1px solid $secondary-border-color; | ||||
|     border: 1px solid $secondary-border-color; | ||||
| } | ||||
|  | ||||
| .ui-widget-header { | ||||
|   | ||||
| @@ -189,7 +189,6 @@ | ||||
| .red-ui-search-result-node { | ||||
|     &.red-ui-palette-icon-flow, | ||||
|     &.red-ui-palette-icon-group, | ||||
|     &.red-ui-palette-icon-junction, | ||||
|     &.red-ui-palette-icon-selection { | ||||
|         background: none; | ||||
|         border-color: transparent; | ||||
| @@ -269,7 +268,6 @@ | ||||
|  | ||||
|     &.red-ui-palette-icon-flow, | ||||
|     &.red-ui-palette-icon-group, | ||||
|     &.red-ui-palette-icon-junction, | ||||
|     &.red-ui-palette-icon-selection { | ||||
|         background: none; | ||||
|         border-color: transparent; | ||||
| @@ -305,7 +303,6 @@ | ||||
|         &.red-ui-palette-icon-flow { | ||||
|             margin-top: -2px; | ||||
|         } | ||||
|         &.red-ui-palette-icon-junction .red-ui-palette-icon-fa, | ||||
|         &.red-ui-palette-icon-group .red-ui-palette-icon-fa { | ||||
|             font-size: 14px; | ||||
|         } | ||||
|   | ||||
| @@ -40,23 +40,7 @@ | ||||
|     height: 7px; | ||||
|     box-sizing: border-box; | ||||
|     cursor: ns-resize; | ||||
|     background-color: $primary-background; | ||||
|  | ||||
|     &:before { | ||||
|         content: ''; | ||||
|         display: block; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         -webkit-mask-image: url(images/grip-horizontal.svg); | ||||
|         mask-image: url(images/grip-horizontal.svg); | ||||
|         -webkit-mask-size: contain; | ||||
|         mask-size: contain; | ||||
|         -webkit-mask-position: center; | ||||
|         mask-position: center; | ||||
|         -webkit-mask-repeat: no-repeat; | ||||
|         mask-repeat: no-repeat; | ||||
|         background-color: $grip-color; | ||||
|     } | ||||
|     background: $primary-background url(images/grip-horizontal.png) no-repeat 50% 50%; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -86,22 +70,6 @@ | ||||
|         width: 7px; | ||||
|         display: inline-block; | ||||
|         cursor: ew-resize; | ||||
|         background-color: $primary-background; | ||||
|         background: $primary-background url(images/grip.png) no-repeat 50% 50%; | ||||
|     } | ||||
|  | ||||
|         &:before { | ||||
|             content: ''; | ||||
|             display: block; | ||||
|             width: 100%; | ||||
|             height: 100%; | ||||
|             -webkit-mask-image: url(images/grip.svg); | ||||
|             mask-image: url(images/grip.svg); | ||||
|             -webkit-mask-size: contain; | ||||
|             mask-size: contain; | ||||
|             -webkit-mask-position: 50% 50%; | ||||
|             mask-position: 50% 50%; | ||||
|             -webkit-mask-repeat: no-repeat; | ||||
|             mask-repeat: no-repeat; | ||||
|             background-color: $grip-color; | ||||
|         } | ||||
| } | ||||
|   | ||||
| @@ -152,20 +152,7 @@ | ||||
|     border-radius:3px; | ||||
|     padding: 1px 2px; | ||||
| } | ||||
| .red-ui-popover { | ||||
|     a { | ||||
|         text-decoration: none; | ||||
|         color: var(--red-ui-popover-color) !important; | ||||
|     } | ||||
|     a:hover, | ||||
|     a:focus { | ||||
|         text-decoration: none; | ||||
|         color: var(--red-ui-popover-color) !important; | ||||
|     } | ||||
|     a:focus { | ||||
|         outline: 1px solid $form-input-focus-color; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .red-ui-popover a.red-ui-button, | ||||
| .red-ui-popover button.red-ui-button { | ||||
|     &:not(.primary) { | ||||
|   | ||||
| @@ -66,9 +66,8 @@ | ||||
|         border-left-width: 3px; | ||||
|         border-right-width: 3px; | ||||
|         .red-ui-palette-icon-fa { | ||||
|             font-size: 11px; | ||||
|             position: relative; | ||||
|             top: -3px; | ||||
|             top: -2.5px; | ||||
|             left: 0px; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -47,24 +47,8 @@ | ||||
|     bottom:10px; | ||||
|     width: 7px; | ||||
|     // z-index: 11; | ||||
|     background-color: $primary-background; | ||||
|     background: $primary-background url(images/grip.png) no-repeat 50% 50%; | ||||
|     cursor: col-resize; | ||||
|  | ||||
|     &:before { | ||||
|         content: ''; | ||||
|         display: block; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         -webkit-mask-image: url(images/grip.svg); | ||||
|         mask-image: url(images/grip.svg); | ||||
|         -webkit-mask-size: auto; | ||||
|         mask-size: auto; | ||||
|         -webkit-mask-position: 50% 50%; | ||||
|         mask-position: 50% 50%; | ||||
|         -webkit-mask-repeat: no-repeat; | ||||
|         mask-repeat: no-repeat; | ||||
|         background-color: $grip-color; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .red-ui-sidebar-closed > #red-ui-sidebar { display: none; } | ||||
|   | ||||
| @@ -42,10 +42,6 @@ ul.red-ui-sidebar-node-config-list { | ||||
|             border-color: transparent; | ||||
|             box-shadow: 0 0 0 2px $node-selected-color; | ||||
|         } | ||||
|         &.highlighted { | ||||
|             border-color: transparent; | ||||
|             outline: dashed $node-selected-color 4px; | ||||
|         } | ||||
|     } | ||||
|     .red-ui-palette-label { | ||||
|         margin-left: 8px; | ||||
|   | ||||
| @@ -530,16 +530,10 @@ div.red-ui-info-table { | ||||
| } | ||||
|  | ||||
| .red-ui-icons-flow { | ||||
|     mask-image: url(images/subflow_tab.svg); | ||||
|     -webkit-mask-image: url(images/subflow_tab.svg); | ||||
|     mask-position: center; | ||||
|     -webkit-mask-position: center; | ||||
|     mask-size: contain; | ||||
|     -webkit-mask-size: contain; | ||||
|     mask-repeat: no-repeat; | ||||
|     -webkit-mask-repeat: no-repeat; | ||||
|     background-color: $icons-flow-color; | ||||
|     // filter: brightness(2.5); | ||||
|     background-image: url('images/subflow_tab.svg'); | ||||
|     background-repeat: no-repeat; | ||||
|     background-size: contain; | ||||
|     filter: brightness(2.5); | ||||
| } | ||||
|  | ||||
| .red-ui-info-toolbar { | ||||
|   | ||||
| @@ -85,10 +85,6 @@ | ||||
|             &:not(.active) a:hover+a.red-ui-tab-close { | ||||
|                 background: $tab-background-hover; | ||||
|             } | ||||
|             &.highlighted { | ||||
|                 box-shadow: 0px 0px 4px 2px $node-selected-color; | ||||
|                 border: dashed 1px $node-selected-color; | ||||
|             } | ||||
|             &.active { | ||||
|                 background: $tab-background-active; | ||||
|                 font-weight: bold; | ||||
| @@ -346,28 +342,21 @@ | ||||
| } | ||||
|  | ||||
|  | ||||
| img.red-ui-tab-icon { | ||||
|     margin-left: -8px; | ||||
|     margin-right: 3px; | ||||
|     margin-top: -2px; | ||||
|     opacity: 0.1; | ||||
|     width: 20px; | ||||
|     height: 20px; | ||||
|     vertical-align: middle; | ||||
| } | ||||
| i.red-ui-tab-icon { | ||||
|     opacity: 0.7; | ||||
|     width: 18px; | ||||
|     height: 20px; | ||||
|     &:not(.fa) { | ||||
|         display: inline-block; | ||||
|         margin-left: -8px; | ||||
|         margin-right: 3px; | ||||
|         margin-top: -2px; | ||||
|         opacity: 1; | ||||
|         width: 20px; | ||||
|         height: 20px; | ||||
|         vertical-align: middle; | ||||
|         -webkit-mask-size: contain; | ||||
|         mask-size: contain; | ||||
|         -webkit-mask-position: center; | ||||
|         mask-position: center; | ||||
|         -webkit-mask-repeat: no-repeat; | ||||
|         mask-repeat: no-repeat; | ||||
|         background-color: $tab-icon-color; | ||||
|     } | ||||
| } | ||||
|  | ||||
| .red-ui-tabs-badges { | ||||
|     position: absolute; | ||||
|     top:0px; | ||||
|   | ||||
| @@ -135,13 +135,6 @@ | ||||
| } | ||||
| .red-ui-treeList-spinner { | ||||
|     height: 32px; | ||||
|     -webkit-mask-image: url(images/spin.svg); | ||||
|     mask-image: url(images/spin.svg); | ||||
|     -webkit-mask-size: auto 20px; | ||||
|     mask-size: auto 20px; | ||||
|     -webkit-mask-position: 50% 50%; | ||||
|     mask-position: 50% 50%; | ||||
|     -webkit-mask-repeat: no-repeat; | ||||
|     mask-repeat: no-repeat; | ||||
|     background-color: $spinner-color; | ||||
|     background: url(images/spin.svg) 50% 50% no-repeat; | ||||
|     background-size: auto 20px; | ||||
| } | ||||
|   | ||||
| @@ -104,17 +104,6 @@ | ||||
|     } | ||||
|     .red-ui-typedInput-icon { | ||||
|         margin-right: 6px; | ||||
|         &:not(.fa) { | ||||
|             -webkit-mask-size: cover; | ||||
|             mask-size: cover; | ||||
|             -webkit-mask-position: center; | ||||
|             mask-position: center; | ||||
|             -webkit-mask-repeat: no-repeat; | ||||
|             mask-repeat: no-repeat; | ||||
|             background-color: $primary-text-color; | ||||
|             height: 14px; | ||||
|             width: 12px; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| button.red-ui-typedInput-type-select, | ||||
| @@ -153,16 +142,6 @@ button.red-ui-typedInput-option-trigger | ||||
|         img { | ||||
|             max-width: none; | ||||
|         } | ||||
|         .red-ui-typedInput-icon:not(.fa) { | ||||
|             display: inline-block; | ||||
|             -webkit-mask-size: cover; | ||||
|             mask-size: cover; | ||||
|             -webkit-mask-position: center; | ||||
|             mask-position: center; | ||||
|             -webkit-mask-repeat: no-repeat; | ||||
|             mask-repeat: no-repeat; | ||||
|             background-color: $primary-text-color; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     &:not(.disabled):hover { | ||||
|   | ||||
| @@ -134,13 +134,6 @@ | ||||
|             margin-top: -1px; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     .search-counter { | ||||
|         display: inline-block; | ||||
|         font-size: smaller; | ||||
|         font-weight: 600; | ||||
|         white-space: nowrap; | ||||
|     } | ||||
| } | ||||
|  | ||||
| a.red-ui-footer-button, | ||||
|   | ||||
| Before Width: | Height: | Size: 7.3 KiB | 
| Before Width: | Height: | Size: 36 KiB | 
							
								
								
									
										
											BIN
										
									
								
								packages/node_modules/@node-red/editor-client/src/tours/images/delete-repair.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										
											BIN
										
									
								
								packages/node_modules/@node-red/editor-client/src/tours/images/detach-repair.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
| Before Width: | Height: | Size: 46 KiB | 
| Before Width: | Height: | Size: 22 KiB | 
							
								
								
									
										
											BIN
										
									
								
								packages/node_modules/@node-red/editor-client/src/tours/images/slice.gif
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 81 KiB | 
| Before Width: | Height: | Size: 21 KiB | 
							
								
								
									
										
											BIN
										
									
								
								packages/node_modules/@node-red/editor-client/src/tours/images/subflow-labels.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 29 KiB | 
| @@ -1,76 +1,52 @@ | ||||
| export default { | ||||
|     version: "3.0.0-beta.1", | ||||
|     version: "2.2.0", | ||||
|     steps: [ | ||||
|         { | ||||
|             titleIcon: "fa fa-map-o", | ||||
|             title: { | ||||
|                 "en-US": "Welcome to Node-RED 3.0 Beta 1!", | ||||
|                 "ja": "Node-RED 3.0 ベータ1へようこそ!" | ||||
|                 "en-US": "Welcome to Node-RED 2.2!", | ||||
|                 "ja": "Node-RED 2.2へようこそ!" | ||||
|             }, | ||||
|             description: { | ||||
|                 "en-US": "<p>This is the first Beta release of Node-RED 3.0. It contains just about everything we have planned for the final release.</p><p>Let's take a moment to discover the new features in this release.</p>", | ||||
|                 "ja": "<p>これはNode-RED 3.0の最初のベータリリースです。これには、最終リリースで計画しているほぼ全ての機能が含まれています。</p><p>本リリースの新機能を見つけてみましょう。</p>" | ||||
|                 "en-US": "Let's take a moment to discover the new features in this release.", | ||||
|                 "ja": "本リリースの新機能を見つけてみましょう。" | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Wire Junctions", | ||||
|                 "ja": "分岐点をワイヤーに追加" | ||||
|                 "en-US": "Search history", | ||||
|                 "ja": "検索履歴" | ||||
|             }, | ||||
|             image: 'images/junction-slice.gif', | ||||
|             description: { | ||||
|                 "en-US": `<p>To make it easier to route wires around your flows, it is now possible to | ||||
|                              add junction nodes that give you more control.</p> | ||||
|                           <p>Junctions can be added to wires by holding the Shift key, then click and drag with | ||||
|                           the right-hand mouse button across the wires.</p>`, | ||||
|                 "ja": `<p>フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。</p> | ||||
|                        <p>シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。</p>` | ||||
|                 "en-US": "<p>The Search dialog now keeps a history of your searches, making it easier to go back to a previous search.</p>", | ||||
|                 "ja": "<p>検索ダイアログが検索履歴を保持するようになりました。これによって、過去の検索に戻りやすくなりました。</p>" | ||||
|             }, | ||||
|             element: "#red-ui-search .red-ui-searchBox-form", | ||||
|             prepare(done) { | ||||
|                 RED.search.show(); | ||||
|                 setTimeout(done,400); | ||||
|             }, | ||||
|             complete() { | ||||
|                 RED.search.hide(); | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Wire Junctions", | ||||
|                 "ja": "分岐点をワイヤーに追加" | ||||
|                 "en-US": "Remembering Zoom & Position", | ||||
|                 "ja": "拡大/縮小のレベルや位置を記憶" | ||||
|             }, | ||||
|             image: 'images/junction-quick-add.png', | ||||
|             description: { | ||||
|                 "en-US": `<p>Junctions can also be added using the quick-add dialog.</p> | ||||
|                           <p>The dialog is opened by holding the Ctrl (or Cmd) key when | ||||
|                              clicking in the workspace.</p>`, | ||||
|                 "ja": `<p>クイック追加ダイアログを用いて、分岐点を追加することもできます。</p> | ||||
|                        <p>本ダイアログを開くには、Ctrl(またはCmd)キーを押しながら、ワークスペース上でクリックします。</p>` | ||||
|                 "en-US": "<p>The editor has new options to restore the zoom level and scroll position when reloading the editor.</p>", | ||||
|                 "ja": "<p>エディタを再読み込みした時に、拡大/縮小のレベルやスクロール位置を復元するための新しいオプションを利用できます。</p>" | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Debug Path Tooltip", | ||||
|                 "ja": "デバッグパスのツールチップ" | ||||
|             element: function() { return $("#user-settings-view-store-position").parent()}, | ||||
|             prepare(done) { | ||||
|                 RED.actions.invoke("core:show-user-settings") | ||||
|                 setTimeout(done,400); | ||||
|             }, | ||||
|             image: 'images/debug-path-tooltip.png', | ||||
|             description: { | ||||
|                 "en-US": `<p>When hovering over a node name in the Debug sidebar, a | ||||
|                              new tooltip shows the full location of the node.</p> | ||||
|                           <p>This is useful when working with subflows, making it | ||||
|                              much easier to identify exactly which node generated | ||||
|                              the message.</p> | ||||
|                           <p>Clicking on any item in the list will reveal it in | ||||
|                              the workspace.</p>`, | ||||
|                 "ja": `<p>デバックサイドバー内のノード名の上にマウスカーソルを乗せると、新たにツールチップが表示され、ノードの場所が分かるようになっています。</p> | ||||
|                        <p>これは、サブフローを用いる時に役立つ機能であり、メッセージがどのノードから出力されたかを正確に特定することが遥かに簡単になります。</p> | ||||
|                        <p>本リスト内の要素をクリックすると、ワークスペース内にその要素が表示されます。</p>` | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Continuous Search", | ||||
|                 "ja": "連続した検索" | ||||
|             }, | ||||
|             image: 'images/continuous-search.png', | ||||
|             description: { | ||||
|                 "en-US": `<p>When searching for things in the editor, a new toolbar in | ||||
|                              the workspace provides options to quickly jump between | ||||
|                              the search results.</p>`, | ||||
|                 "ja": `<p>ワークスペース内の新しいツールバーにあるオプションによって、エディタ内を検索する際に、検索結果の間を素早く移動できます。</p>` | ||||
|             complete(done) { | ||||
|                 $("#node-dialog-ok").trigger("click"); | ||||
|                 setTimeout(done,400); | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
| @@ -78,44 +54,85 @@ export default { | ||||
|                 "en-US": "New wiring actions", | ||||
|                 "ja": "新しいワイヤー操作" | ||||
|             }, | ||||
|             image: "images/split-wire-with-links.gif", | ||||
|             // image: "images/", | ||||
|             description: { | ||||
|                 "en-US": `<p>A new action has been added that will replace a wire with a pair of connected Link nodes:</p> | ||||
|                 "en-US": `<p>A pair of new actions have been added to help with wiring nodes together:</p> | ||||
|                           <ul> | ||||
|                           <li><b><code>Split Wire With Link Nodes</code></b></li> | ||||
|                           <li><b><code>Wire Series Of Nodes</code></b> - adds a wire (if necessary) between each pair of nodes in the order they were selected.</li> | ||||
|                           <li><b><code>Wire Node To Multiple</code></b> - wires the first node selected to all of the other selected nodes.</li> | ||||
|                           </ul> | ||||
|                           <p>Actions can be accessed from the Action List in the main menu.</p>`, | ||||
|                 "ja": `<p>ワイヤーを、接続されたLinkノードのペアに置き換える動作が新たに追加されました:</p> | ||||
|                 "ja": `<p>ノード接続を支援する2つの新しい操作が追加されました:</p> | ||||
|                        <ul> | ||||
|                        <li><b><code>ワイヤーをlinkノードで分割</code></b></li> | ||||
|                        <li><b><code>Wire Series Of Nodes</code></b> - ノードを選択した順序で、各ノードのペアの間にワイヤーを(必要に応じて)追加します。</li> | ||||
|                        <li><b><code>Wire Node To Multiple</code></b> - 最初に選択したノードから、他の選択した全てのノードに対して、ワイヤーを追加します。</li> | ||||
|                        </ul> | ||||
|                        <p>本アクションは、メインメニュー内の動作一覧から呼び出せます。</p>`, | ||||
|                        <p>メインメニュー内の動作一覧から、これらの操作を利用できます。</p>` | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Default node names", | ||||
|                 "ja": "標準ノードの名前" | ||||
|                 "en-US": "Deleting nodes and reconnecting wires", | ||||
|                 "ja": "ノードの削除とワイヤーの再接続" | ||||
|             }, | ||||
|             // image: "images/", | ||||
|             image: "images/delete-repair.gif", | ||||
|             description: { | ||||
|                 "en-US": `<p>Some nodes have been updated to generate a unique name when | ||||
|                              new instances are added to the workspace. This applies to | ||||
|                              <code>Debug</code>, <code>Function</code> and <code>Link</code> nodes.</p> | ||||
|                           <p>A new action has also been added to generate default names for the selected | ||||
|                              nodes:</p> | ||||
|                              <ul> | ||||
|                              <li><b><code>Generate Node Names</code></b></li> | ||||
|                              </ul><p>Actions can be accessed from the Action List in the main menu.</p> | ||||
|                             `, | ||||
|                 "ja": `<p>一部のノードは、ワークスペース上に新インスタンスとして追加した際に、一意の名前を付けるよう変更されました。この変更は、<code>Debug</code>、<code>Function</code>、<code>Link</code>ノードに適用されています。</p> | ||||
|                        <p>選択したノードに対して、標準の名前を生成する動作も新たに追加されました:</p> | ||||
|                           <ul> | ||||
|                           <li><b><code>ノード名を生成</code></b></li> | ||||
|                           </ul><p>本アクションは、メインメニュー内の動作一覧から呼び出せます。</p> | ||||
|                          ` | ||||
|                 "en-US": `<p>It is now possible to delete a selection of nodes and automatically repair the wiring behind them.</p> | ||||
|                           <p>This is really useful if you want to remove a node from the middle of the flow.</p> | ||||
|                           <p>Hold the Ctrl (or Cmd) key when you press Delete and the nodes will be gone and the wires repaired.</p> | ||||
|                           `, | ||||
|                 "ja": `<p>選択したノードを削除した後、その背後にあるワイヤーを自動的に修復できるようになりました。</p> | ||||
|                        <p>これは、フローの中からノードを削除する時に、とても便利に使えます。</p> | ||||
|                        <p>Ctrl (またはCmd)キーを押しながらDeleteキーを押すと、ノードがなくなり、ワイヤーが修復されます。</p> | ||||
|                        ` | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Detaching nodes from a flow", | ||||
|                 "ja": "フローからノードの切り離し" | ||||
|             }, | ||||
|             image: "images/detach-repair.gif", | ||||
|             description: { | ||||
|                 "en-US": `<p>If you want to remove a node from a flow without deleting it, | ||||
|                           you can use the <b><code>Detach Selected Nodes</code></b> action.</p> | ||||
|                           <p>The nodes will be removed from their flow, the wiring repaired behind them, and then attached to the mouse | ||||
|                           so you can drop them wherever you want in the workspace.</p> | ||||
|                           <p>There isn't a default keyboard shortcut assigned for this new action, but | ||||
|                           you can add your own via the Keyboard pane of the main Settings dialog.</p>`, | ||||
|                 "ja": `<p>ノードを削除することなく、フローからノードを除きたい場合は、<b><code>Detach Selected Nodes</code></b>操作を利用できます。</p> | ||||
|                        <p>フローからノードが除かれた後、背後のワイヤーが修復され、ノードはマウスポインタにつながります。そのため、ワークスペースの好きな所にノードを配置できます。</p> | ||||
|                        <p>この新しい操作に対して、デフォルトのキーボードショートカットは登録されていませんが、メイン設定ダイアログのキーボード設定から追加できます。</p>` | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "More wiring tricks", | ||||
|                 "ja": "その他のワイヤー操作" | ||||
|             }, | ||||
|             image: "images/slice.gif", | ||||
|             description: { | ||||
|                 "en-US": `<p>A couple more wiring tricks to share.</p> | ||||
|                           <p>You can now select multiple wires by holding the Ctrl (or Cmd) key | ||||
|                           when clicking on a wire. This makes it easier to delete multiple wires in one go.</p> | ||||
|                           <p>If you hold the Ctrl (or Cmd) key, then click and drag with the right-hand mouse button, | ||||
|                           you can slice through wires to remove them.</p>`, | ||||
|                 "ja": `<p>その他のいくつかのワイヤー操作</p> | ||||
|                        <p>Ctrl (またはCmd)キーを押しながらワイヤーをクリックすることで、複数のワイヤーを選択できるようになりました。これによって、複数のワイヤーを一度に削除することが簡単になりました。</p> | ||||
|                        <p>Ctrl (またはCmd)キーを押しながら、マウスの右ボタンを用いてドラッグすると、ワイヤーを切って削除できます。</p>` | ||||
|             } | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Subflow Output Labels", | ||||
|                 "ja": "サブフローの出力ラベル" | ||||
|             }, | ||||
|             image: "images/subflow-labels.png", | ||||
|             description: { | ||||
|                 "en-US": "<p>If a subflow has labels set for its outputs, they now get shown on the ports within the subflow template view.</p>", | ||||
|                 "ja": "<p>サブフローの出力にラベルが設定されている場合、サブフローテンプレート画面内のポートにラベルが表示されるようになりました。</p>" | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             title: { | ||||
|                 "en-US": "Node Updates", | ||||
| @@ -124,14 +141,14 @@ export default { | ||||
|             // image: "images/", | ||||
|             description: { | ||||
|                 "en-US": `<ul> | ||||
|                             <li>The Debug node can be configured to count messages it receives</li> | ||||
|                             <li>The Link Call node can use a message property to dynamically target the link it should call</li> | ||||
|                             <li>The HTTP Request node can be preconfigured with HTTP headers</li> | ||||
|                             <li>The JSON node will now handle parsing Buffer payloads</li> | ||||
|                             <li>The TCP Client nodes support TLS connections</li> | ||||
|                             <li>The WebSocket node allows you to specify a sub-protocol when connecting</li> | ||||
|                           </ul>`, | ||||
|                 "ja": `<ul> | ||||
|                          <li>Debugノードは、受信したメッセージの数をカウントするよう設定できるようになりました。</li> | ||||
|                          <li>Link Callノードは、メッセージのプロパティによって、呼び出し対象のlinkを動的に指定できるようになりました。</li> | ||||
|                          <li>HTTP Requestノードは、HTTPヘッダを事前設定できるようになりました。</li> | ||||
|                          <li>JSONノードが、バッファ形式のペイロードを解析できるようになりました。</li> | ||||
|                          <li>TCPクライアントノードが、TLS接続をサポートしました。</li> | ||||
|                          <li>WebSocketノードで、接続時にサブプロトコルを指定できるようになりました。</li> | ||||
|                        </ul>` | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */ | ||||
|  | ||||
| declare module 'assert' { | ||||
|     /** An alias of `assert.ok()`. */ | ||||
| @@ -125,7 +125,3 @@ declare module 'assert' { | ||||
|  | ||||
|     export = assert; | ||||
| } | ||||
| declare module 'node:assert' { | ||||
|     import assert = require('assert'); | ||||
|     export = assert; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */ | ||||
|  | ||||
| /** | ||||
|  * Async Hooks module: https://nodejs.org/api/async_hooks.html | ||||
| @@ -227,6 +227,3 @@ declare module 'async_hooks' { | ||||
|         enterWith(store: T): void; | ||||
|     } | ||||
| } | ||||
| declare module 'node:async_hooks' { | ||||
|     export * from 'async_hooks'; | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
|  | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */ | ||||
|  | ||||
| declare module 'buffer' { | ||||
|     import { BinaryLike } from 'node:crypto'; | ||||
|     export const INSPECT_MAX_BYTES: number; | ||||
|     export const kMaxLength: number; | ||||
|     export const kStringMaxLength: number; | ||||
| @@ -21,72 +20,6 @@ declare module 'buffer' { | ||||
|         new(size: number): Buffer; | ||||
|         prototype: Buffer; | ||||
|     }; | ||||
|     /** | ||||
|      * @experimental | ||||
|      */ | ||||
|     export interface BlobOptions { | ||||
|         /** | ||||
|          * @default 'utf8' | ||||
|          */ | ||||
|         encoding?: BufferEncoding | undefined; | ||||
|         /** | ||||
|          * The Blob content-type. The intent is for `type` to convey | ||||
|          * the MIME media type of the data, however no validation of the type format | ||||
|          * is performed. | ||||
|          */ | ||||
|         type?: string | undefined; | ||||
|     } | ||||
|     /** | ||||
|      * A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) encapsulates immutable, raw data that can be safely shared across | ||||
|      * multiple worker threads. | ||||
|      * @since v14.18.0 | ||||
|      * @experimental | ||||
|      */ | ||||
|     export class Blob { | ||||
|         /** | ||||
|          * The total size of the `Blob` in bytes. | ||||
|          * @since v14.18.0 | ||||
|          */ | ||||
|         readonly size: number; | ||||
|         /** | ||||
|          * The content-type of the `Blob`. | ||||
|          * @since v14.18.0 | ||||
|          */ | ||||
|         readonly type: string; | ||||
|         /** | ||||
|          * Creates a new `Blob` object containing a concatenation of the given sources. | ||||
|          * | ||||
|          * {ArrayBuffer}, {TypedArray}, {DataView}, and {Buffer} sources are copied into | ||||
|          * the 'Blob' and can therefore be safely modified after the 'Blob' is created. | ||||
|          * | ||||
|          * String sources are also copied into the `Blob`. | ||||
|          */ | ||||
|         constructor(sources: Array<BinaryLike | Blob>, options?: BlobOptions); | ||||
|         /** | ||||
|          * Returns a promise that fulfills with an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) containing a copy of | ||||
|          * the `Blob` data. | ||||
|          * @since v14.18.0 | ||||
|          */ | ||||
|         arrayBuffer(): Promise<ArrayBuffer>; | ||||
|         /** | ||||
|          * Creates and returns a new `Blob` containing a subset of this `Blob` objects | ||||
|          * data. The original `Blob` is not altered. | ||||
|          * @since v14.18.0 | ||||
|          * @param start The starting index. | ||||
|          * @param end The ending index. | ||||
|          * @param type The content-type for the new `Blob` | ||||
|          */ | ||||
|         slice(start?: number, end?: number, type?: string): Blob; | ||||
|         /** | ||||
|          * Returns a promise that fulfills with the contents of the `Blob` decoded as a | ||||
|          * UTF-8 string. | ||||
|          * @since v14.18.0 | ||||
|          */ | ||||
|         text(): Promise<string>; | ||||
|     } | ||||
|  | ||||
|     export { BuffType as Buffer }; | ||||
| } | ||||
| declare module 'node:buffer' { | ||||
|     export * from 'buffer'; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */ | ||||
|  | ||||
| declare module 'child_process' { | ||||
|     import { BaseEncodingOptions } from 'fs'; | ||||
| @@ -512,6 +512,3 @@ declare module 'child_process' { | ||||
|     function execFileSync(command: string, args: ReadonlyArray<string>, options: ExecFileSyncOptionsWithBufferEncoding): Buffer; | ||||
|     function execFileSync(command: string, args?: ReadonlyArray<string>, options?: ExecFileSyncOptions): string | Buffer; | ||||
| } | ||||
| declare module 'node:child_process' { | ||||
|     export * from 'child_process'; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
|  | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ | ||||
| /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */ | ||||
|  | ||||
| declare module 'cluster' { | ||||
|     import * as child from 'child_process'; | ||||
| @@ -263,6 +263,3 @@ declare module 'cluster' { | ||||
|  | ||||
|     function eventNames(): string[]; | ||||
| } | ||||
| declare module 'node:cluster' { | ||||
|     export * from 'cluster'; | ||||
| } | ||||
|   | ||||