Compare commits
54 Commits
version-ch
...
4133-mqtt-
Author | SHA1 | Date | |
---|---|---|---|
|
a790136164 | ||
|
32a49a1ef1 | ||
|
4b88775183 | ||
|
29db82625f | ||
|
2b6c9e3439 | ||
|
9ea4853c89 | ||
|
3b5e21761b | ||
|
2d76bf29cf | ||
|
c21f7abe4e | ||
|
8c191263c0 | ||
|
2679ff277c | ||
|
9e3f148273 | ||
|
7e9042e9f7 | ||
|
67c5a248ad | ||
|
e8ddee24a9 | ||
|
be4eab65f6 | ||
|
c0650cc0f5 | ||
|
02c7d014cb | ||
|
67dd7e30fa | ||
|
e9a08af73b | ||
|
08b1ef2766 | ||
|
667d8673d4 | ||
|
d44ea9d558 | ||
|
86dfe86813 | ||
|
246409970d | ||
|
841f1849c8 | ||
|
00e7e4d43c | ||
|
ee43a845aa | ||
|
a7cc66af93 | ||
|
f8701cfed0 | ||
|
6b205bf303 | ||
|
6fbcec8b98 | ||
|
c30e57c31d | ||
|
df3dc36874 | ||
|
7b71d8d212 | ||
|
2eaae4b83f | ||
|
3c66af9506 | ||
|
e5d579c1bb | ||
|
ee811ca89b | ||
|
8e4933041d | ||
|
1f3559e14f | ||
|
f1fa1bbe4e | ||
|
5eb46c570d | ||
|
24178beafc | ||
|
e30df544db | ||
|
6044871438 | ||
|
e612bb6a38 | ||
|
81ea67d6da | ||
|
892d21fb77 | ||
|
95a7980ada | ||
|
281e9d1357 | ||
|
742f05f59d | ||
|
79db4f8aa1 | ||
|
f4d7b71984 |
16
.github/workflows/tests.yml
vendored
@@ -17,11 +17,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16, 18]
|
||||
node-version: [14, 16]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Dependencies
|
||||
@@ -29,8 +29,8 @@ jobs:
|
||||
- name: Run tests
|
||||
run: |
|
||||
npm run test
|
||||
- name: Publish to coveralls.io
|
||||
if: ${{ matrix.node-version == 16 }}
|
||||
uses: coverallsapp/github-action@v1.1.2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
# - name: Publish to coveralls.io
|
||||
# if: ${{ matrix.node-version == 14 }}
|
||||
# uses: coverallsapp/github-action@v1.1.2
|
||||
# with:
|
||||
# github-token: ${{ github.token }}
|
||||
|
@@ -15,5 +15,5 @@
|
||||
"shadow": true, // allow variable shadowing (re-use of names...)
|
||||
"sub": true, // don't warn that foo['bar'] should be written as foo.bar
|
||||
"proto": true, // allow setting of __proto__ in node < v0.12,
|
||||
"esversion": 11 // allow es11(ES2020)
|
||||
"esversion": 6 // allow es6
|
||||
}
|
||||
|
91
CHANGELOG.md
@@ -1,94 +1,3 @@
|
||||
#### 3.1.0-beta.1: Beta Release
|
||||
|
||||
|
||||
Editor
|
||||
|
||||
- NEW: Locking Flows (#3938) @knolleary
|
||||
- NEW: Improve UX around hiding flows via context menu (#3930) @knolleary
|
||||
- NEW: Add support for inline image in markdown editor by drag and drop of an image file (#4006) @HiroyasuNishiyama
|
||||
- NEW: Add support for mermaid diagram to markdown editor (#4007) @HiroyasuNishiyama
|
||||
- NEW: Support uri fragments for nodes and groups including edit support (#3870) @knolleary
|
||||
- NEW: Add global environment variable feature (#3941) @HiroyasuNishiyama
|
||||
|
||||
- Remember compact/pretty flow export user choice (#3974) @Steve-Mcl
|
||||
- fix .red-ui-notification class (#4035) @xiaobinqt
|
||||
- Fix border radius on Modules list header (#4038) @bonanitech
|
||||
- fix workspace reference error in case of empty tabs (#4029) @HiroyasuNishiyama
|
||||
- Disable delete tab menu when single tab exists (#4030) @HiroyasuNishiyama
|
||||
- Disable hide all menu if all tabs hidden (#4031) @HiroyasuNishiyama
|
||||
- fix hide subflow tooltip (#4033) @HiroyasuNishiyama
|
||||
- Fix disabled menu items in project feature (#4027) @kazuhitoyokoi
|
||||
- Let themes change radialMenu text colors (#3995) @bonanitech
|
||||
- Add Japanese translations for v3.0.3 (#4012) @kazuhitoyokoi
|
||||
- Add Japanese translation for v3.1.0-beta.0 (#3997) @kazuhitoyokoi
|
||||
- Add Japanese translation for v3.1.0-beta.0 (#3916) @kazuhitoyokoi
|
||||
- Hide subflow category after deleting subflow (#3980) @kazuhitoyokoi
|
||||
- Prevent dbl-click opening node edit dialog with text selected (#3970) @knolleary
|
||||
- Handle replacing unknown node inside group or subflow (#3921) @knolleary
|
||||
- Fix #3939, red border red-ui-typedInput-container (#3949) @Steveorevo
|
||||
- i18n item URL copy notification & add Japanese message (#3946) @HiroyasuNishiyama
|
||||
- add Japanese message for item url copy actions (#3947) @HiroyasuNishiyama
|
||||
- Fix autocomplete entry for responseUrl (#3884) @knolleary
|
||||
- Fix Japanese translation for JSONata editor (#3872) @HiroyasuNishiyama
|
||||
- Fix search type with spaces (#3841) @Steve-Mcl
|
||||
- Fix error hanndling of JSONata expression editor for extended functions (#3871) @HiroyasuNishiyama
|
||||
- Add button type to the adding SSH key button (#3866) @kazuhitoyokoi
|
||||
- Check radio button as default in project dialog (#3879) @kazuhitoyokoi
|
||||
- Add $clone as supported function (#3874) @HiroyasuNishiyama
|
||||
- Env var jsonata (#3807) @HiroyasuNishiyama
|
||||
- Add Japanese translation for v3.0.2 (#3852) @kazuhitoyokoi
|
||||
|
||||
Runtime
|
||||
|
||||
- Force IPv4 name resolution to have priority (#4019) @dceejay
|
||||
- Fix async loading of modules containing both nodes and plugins (#3999) @knolleary
|
||||
- Use main branch as default in project feature (#4036) @kazuhitoyokoi
|
||||
- Rename package var to avoid strict mode error (#4020) @knolleary
|
||||
- Fix typos in settings.js (#4013) @ypid
|
||||
- Ensure credentials object is removed before returning node in getFlow request (#3971) @knolleary
|
||||
- Ignore commit error in project feature (#3987) @kazuhitoyokoi
|
||||
- Update dependencies (#3969) @knolleary
|
||||
- Add check that node sends object rather than primitive type (#3909) @knolleary
|
||||
- Ensure key_path is quoted in GIT_SSH_COMMAND in case of spaces in pathname (#3912) @knolleary
|
||||
- Fix nodesDir scan when node package has js/html in sub dir to package.json (#3867) @Steve-Mcl
|
||||
- Fix file permissions (#3917) @kazuhitoyokoi
|
||||
- ci: add minimum GitHub token permissions for workflows (#3907) @boahc077
|
||||
|
||||
Nodes
|
||||
|
||||
- Catch: fix typo in catch.html (#3965) @we11adam
|
||||
- Change: Fix change node overwriting msg with itself (#3899) @dceejay
|
||||
- Comment node: Clarify where the text will appear (#4004) @dirkjanfaber
|
||||
- CSV: change replace to replaceAll (#3990) @dceejay
|
||||
- CSV node: check header properties for ' and " (#3920) @dceejay
|
||||
- CSV: Fix for CSV undefined property (#3906) @dceejay
|
||||
- Delay: let delay node handle both flush then reset (#3898) @dceejay
|
||||
- Function: Limit number of ports in function node (#3886) @kazuhitoyokoi
|
||||
- Function: Remove dot from variable name for external module in function node (#3880) @kazuhitoyokoi
|
||||
- Function: add function node monaco types util and promisify (#3868) @Steve-Mcl
|
||||
- HTTP In: Ensure msg.req.headers is enumerable (#3908) @knolleary
|
||||
- HTTP Request: Support form-data arrays (#3991) @hardillb
|
||||
- HTTP Request: Fix httprequest tests to be more lenient on error message (#3922) @knolleary
|
||||
- HTTP Request: Add missing property to node object HTTPRequest (#3842) @hardillb
|
||||
- HTTP Request/Response: Support sortable list on property UI of http request and http response nodes (#3857) @kazuhitoyokoi
|
||||
- HTTP Response: Ensure statusCode is a number (#3894) @hardillb
|
||||
- Inject: Allow Inject node to work with async context stores (#4021) @knolleary
|
||||
- Join/Batch: Add count to join and batch node labels (#4028) @dceejay
|
||||
- MQTT: Fix birth topic handling in MQTT node (#3905) @Steve-Mcl
|
||||
- MQTT: Fix pull-down menus of MQTT configuration node (#3890) @kazuhitoyokoi
|
||||
- MQTT: Prevent invalid mqtt birth topic crashing node-red (#3869) @Steve-Mcl
|
||||
- MQTT: ensure sessionExpiry(Interval) is applied (#3840) @Steve-Mcl
|
||||
- MQTT: Fix mqtt nodes not reconnecting on modified-flows deploy (#3992) @knolleary
|
||||
- MQTT: fix single subscription mqtt node status (#3966) @Steve-Mcl
|
||||
- Range: Add drop mode to range node (#3935) @dceejay
|
||||
- Remove done from describe (#3873) @HiroyasuNishiyama
|
||||
- Split node: avoid duplicate done call for buffer split (#4000) @knolleary
|
||||
- Status: Fix typo in 25-status.html (#3981) @kazuhitoyokoi
|
||||
- TCP Node: ensure newline substitution applies to whole message (#4009) @dceejay
|
||||
- Template: Add information about environment variable to template node (#3882) @kazuhitoyokoi
|
||||
- Trigger: Hide trigger node repeat send option if sending nothing (#4023) @dceejay
|
||||
- Watch: fix watch node test on MacOS/ARM (#3942) @HiroyasuNishiyama
|
||||
|
||||
#### 3.0.2: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
@@ -151,7 +151,6 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",
|
||||
@@ -170,7 +169,6 @@ module.exports = function(grunt) {
|
||||
"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/env-var.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/statusBar.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/view.js",
|
||||
@@ -226,7 +224,7 @@ module.exports = function(grunt) {
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js"
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js",
|
||||
],
|
||||
// "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
|
||||
// // TODO: resolve relative resource paths in
|
||||
@@ -235,9 +233,6 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
|
||||
],
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/mermaid/mermaid.min.js": [
|
||||
"node_modules/mermaid/dist/mermaid.min.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,7 @@
|
||||
|
||||
http://nodered.org
|
||||
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](https://coveralls.io/r/node-red/node-red?branch=master)
|
||||
[](https://github.com/node-red/node-red/actions?query=branch%3Amaster)
|
||||
|
||||
Low-code programming for event-driven applications.
|
||||
|
||||
|
49
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -26,30 +26,30 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.8.2",
|
||||
"acorn": "8.7.1",
|
||||
"acorn-walk": "8.2.0",
|
||||
"ajv": "8.12.0",
|
||||
"async-mutex": "0.4.0",
|
||||
"ajv": "8.11.0",
|
||||
"async-mutex": "0.3.2",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.2",
|
||||
"body-parser": "1.20.0",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"clone": "2.1.2",
|
||||
"content-type": "1.0.5",
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.5.0",
|
||||
"cookie-parser": "1.4.6",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.1.0",
|
||||
"express": "4.18.2",
|
||||
"express": "4.18.1",
|
||||
"express-session": "1.17.3",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "10.1.0",
|
||||
"got": "11.8.6",
|
||||
"got": "11.8.5",
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "1.2.0",
|
||||
"hpagent": "1.0.0",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"i18next": "21.10.0",
|
||||
"i18next": "21.8.16",
|
||||
"iconv-lite": "0.6.3",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "4.1.0",
|
||||
@@ -60,7 +60,7 @@
|
||||
"memorystore": "1.6.7",
|
||||
"mime": "3.0.0",
|
||||
"moment": "2.29.4",
|
||||
"moment-timezone": "0.5.41",
|
||||
"moment-timezone": "0.5.34",
|
||||
"mqtt": "4.3.7",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"mustache": "4.2.0",
|
||||
@@ -72,21 +72,21 @@
|
||||
"passport": "0.6.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.5.2",
|
||||
"semver": "7.3.8",
|
||||
"tar": "6.1.13",
|
||||
"tough-cookie": "4.1.2",
|
||||
"uglify-js": "3.17.4",
|
||||
"uuid": "9.0.0",
|
||||
"raw-body": "2.5.1",
|
||||
"semver": "7.3.7",
|
||||
"tar": "6.1.11",
|
||||
"tough-cookie": "4.0.0",
|
||||
"uglify-js": "3.16.3",
|
||||
"uuid": "8.3.2",
|
||||
"ws": "7.5.6",
|
||||
"xml2js": "0.4.23"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "5.1.0"
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.4.1",
|
||||
"grunt": "1.6.1",
|
||||
"dompurify": "2.3.10",
|
||||
"grunt": "1.5.3",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.4.3",
|
||||
"grunt-concurrent": "3.0.0",
|
||||
@@ -108,18 +108,17 @@
|
||||
"i18next-http-backend": "1.4.1",
|
||||
"jquery-i18next": "1.2.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "4.2.12",
|
||||
"mermaid": "^9.3.0",
|
||||
"marked": "4.0.18",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "9.2.2",
|
||||
"node-red-node-test-helper": "^0.3.0",
|
||||
"nodemon": "2.0.20",
|
||||
"nodemon": "2.0.19",
|
||||
"proxy": "^1.0.2",
|
||||
"sass": "1.58.3",
|
||||
"sass": "1.54.2",
|
||||
"should": "13.2.3",
|
||||
"sinon": "11.1.2",
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "6.3.3"
|
||||
"supertest": "6.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,14 +16,14 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.1.0-beta.1",
|
||||
"@node-red/editor-client": "3.1.0-beta.1",
|
||||
"@node-red/util": "3.0.2",
|
||||
"@node-red/editor-client": "3.0.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.2",
|
||||
"body-parser": "1.20.0",
|
||||
"clone": "2.1.2",
|
||||
"cors": "2.8.5",
|
||||
"express-session": "1.17.3",
|
||||
"express": "4.18.2",
|
||||
"express": "4.18.1",
|
||||
"memorystore": "1.6.7",
|
||||
"mime": "3.0.0",
|
||||
"multer": "1.4.5-lts.1",
|
||||
@@ -35,6 +35,6 @@
|
||||
"ws": "7.5.6"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "5.1.0"
|
||||
"bcrypt": "5.0.1"
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,7 @@
|
||||
"position": "Position",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"upload": "Upload",
|
||||
"lock": "Lock",
|
||||
"unlock": "Unlock",
|
||||
"locked": "Locked",
|
||||
"unlocked": "Unlocked"
|
||||
"upload": "Upload"
|
||||
},
|
||||
"type": {
|
||||
"string": "string",
|
||||
@@ -57,30 +53,22 @@
|
||||
"confirmDelete": "Confirm delete",
|
||||
"delete": "Are you sure you want to delete '__label__'?",
|
||||
"dropFlowHere": "Drop the flow here",
|
||||
"dropImageHere": "Drop the image here",
|
||||
"addFlow": "Add flow",
|
||||
"addFlowToRight": "Add flow to the right",
|
||||
"closeFlow": "Close flow",
|
||||
"hideFlow": "Hide flow",
|
||||
"hideOtherFlows": "Hide other flows",
|
||||
"showAllFlows": "Show all flows (__count__ hidden)",
|
||||
"showAllFlows": "Show all flows",
|
||||
"hideAllFlows": "Hide all flows",
|
||||
"hiddenFlows": "List __count__ hidden flow",
|
||||
"hiddenFlows_plural": "List __count__ hidden flows",
|
||||
"showLastHiddenFlow": "Reopen hidden flow",
|
||||
"showLastHiddenFlow": "Show last hidden flow",
|
||||
"listFlows": "List flows",
|
||||
"listSubflows": "List subflows",
|
||||
"status": "Status",
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"info": "Description",
|
||||
"selectNodes": "Click nodes to select",
|
||||
"enableFlow": "Enable flow",
|
||||
"disableFlow": "Disable flow",
|
||||
"lockFlow": "Lock flow",
|
||||
"unlockFlow": "Unlock flow",
|
||||
"moveToStart": "Move flow to start",
|
||||
"moveToEnd": "Move flow to end"
|
||||
"selectNodes": "Click nodes to select"
|
||||
},
|
||||
"menu": {
|
||||
"label": {
|
||||
@@ -113,7 +101,6 @@
|
||||
"displayStatus": "Show node status",
|
||||
"displayConfig": "Configuration nodes",
|
||||
"import": "Import",
|
||||
"importExample": "Import Example Flow",
|
||||
"export": "Export",
|
||||
"search": "Search flows",
|
||||
"searchInput": "search your flows",
|
||||
@@ -504,13 +491,13 @@
|
||||
"unassigned": "Unassigned",
|
||||
"global": "global",
|
||||
"workspace": "workspace",
|
||||
"editor": "edit dialog",
|
||||
"selectAll": "Select all",
|
||||
"selectNone": "Select none",
|
||||
"selectAllConnected": "Select connected",
|
||||
"addRemoveNode": "Add/remove node from selection",
|
||||
"editSelected": "Edit selected node",
|
||||
"deleteSelected": "Delete selected nodes or link",
|
||||
"deleteReconnect": "Delete and Reconnect",
|
||||
"importNode": "Import nodes",
|
||||
"exportNode": "Export nodes",
|
||||
"nudgeNode": "Move selected nodes (1px)",
|
||||
@@ -697,11 +684,9 @@
|
||||
"empty": "empty",
|
||||
"globalConfig": "Global Configuration Nodes",
|
||||
"triggerAction": "Trigger action",
|
||||
"find": "Find in workspace",
|
||||
"copyItemUrl": "Copy item url",
|
||||
"copyURL2Clipboard": "Copied url to clipboard",
|
||||
"showFlow": "Show",
|
||||
"hideFlow": "Hide"
|
||||
"hideFlow": "Hide",
|
||||
"find": "Find in workspace"
|
||||
},
|
||||
"help": {
|
||||
"name": "Help",
|
||||
@@ -1002,10 +987,7 @@
|
||||
"quote": "Quote",
|
||||
"link": "Link",
|
||||
"horizontal-rule": "Horizontal rule",
|
||||
"toggle-preview": "Toggle preview",
|
||||
"mermaid": {
|
||||
"summary": "Mermaid Diagram"
|
||||
}
|
||||
"toggle-preview": "Toggle preview"
|
||||
},
|
||||
"bufferEditor": {
|
||||
"title": "Buffer editor",
|
||||
@@ -1227,10 +1209,5 @@
|
||||
"node": "Node",
|
||||
"junction": "Junction",
|
||||
"linkNodes": "Link Nodes"
|
||||
},
|
||||
"env-var": {
|
||||
"environment": "Environment",
|
||||
"header": "Global Environment Variables",
|
||||
"revert": "Revert"
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,7 @@
|
||||
"position": "配置",
|
||||
"enable": "有効",
|
||||
"disable": "無効",
|
||||
"upload": "アップロード",
|
||||
"lock": "固定",
|
||||
"unlock": "固定を解除",
|
||||
"locked": "固定済み",
|
||||
"unlocked": "固定なし"
|
||||
"upload": "アップロード"
|
||||
},
|
||||
"type": {
|
||||
"string": "文字列",
|
||||
@@ -57,10 +53,8 @@
|
||||
"confirmDelete": "削除の確認",
|
||||
"delete": "本当に '__label__' を削除しますか?",
|
||||
"dropFlowHere": "ここにフローをドロップしてください",
|
||||
"dropImageHere": "ここに画像ファイルをドロップしてください",
|
||||
"addFlow": "フローの追加",
|
||||
"addFlowToRight": "右側にフローを追加",
|
||||
"closeFlow": "フローを閉じる",
|
||||
"hideFlow": "フローを非表示",
|
||||
"hideOtherFlows": "他のフローを非表示",
|
||||
"showAllFlows": "全てのフローを表示",
|
||||
@@ -74,13 +68,7 @@
|
||||
"enabled": "有効",
|
||||
"disabled": "無効",
|
||||
"info": "詳細",
|
||||
"selectNodes": "ノードをクリックして選択",
|
||||
"enableFlow": "フローを有効化",
|
||||
"disableFlow": "フローを無効化",
|
||||
"lockFlow": "フローを固定",
|
||||
"unlockFlow": "フローの固定を解除",
|
||||
"moveToStart": "フローを先頭へ移動",
|
||||
"moveToEnd": "フローを最後へ移動"
|
||||
"selectNodes": "ノードをクリックして選択"
|
||||
},
|
||||
"menu": {
|
||||
"label": {
|
||||
@@ -113,7 +101,6 @@
|
||||
"displayStatus": "ノードのステータスを表示",
|
||||
"displayConfig": "設定ノード",
|
||||
"import": "読み込み",
|
||||
"importExample": "フロー例を読み込み",
|
||||
"export": "書き出し",
|
||||
"search": "ノードを検索",
|
||||
"searchInput": "ノードを検索",
|
||||
@@ -504,13 +491,13 @@
|
||||
"unassigned": "未割当",
|
||||
"global": "グローバル",
|
||||
"workspace": "ワークスペース",
|
||||
"editor": "編集ダイアログ",
|
||||
"selectAll": "全てのノードを選択",
|
||||
"selectNone": "選択を外す",
|
||||
"selectAllConnected": "接続されたノードを選択",
|
||||
"addRemoveNode": "ノードの選択、選択解除",
|
||||
"editSelected": "選択したノードを編集",
|
||||
"deleteSelected": "選択したノードや接続を削除",
|
||||
"deleteReconnect": "削除と再接続",
|
||||
"importNode": "フローの読み込み",
|
||||
"exportNode": "フローの書き出し",
|
||||
"nudgeNode": "選択したノードを移動(移動量小)",
|
||||
@@ -697,11 +684,9 @@
|
||||
"empty": "空",
|
||||
"globalConfig": "グローバル設定ノード",
|
||||
"triggerAction": "アクションを実行",
|
||||
"find": "ワークスペース内を検索",
|
||||
"copyItemUrl": "要素のURLをコピー",
|
||||
"copyURL2Clipboard": "URLをクリップボードにコピーしました",
|
||||
"showFlow": "表示",
|
||||
"hideFlow": "非表示"
|
||||
"hideFlow": "非表示",
|
||||
"find": "ワークスペース内を検索"
|
||||
},
|
||||
"help": {
|
||||
"name": "ヘルプ",
|
||||
@@ -1002,10 +987,7 @@
|
||||
"quote": "引用",
|
||||
"link": "リンク",
|
||||
"horizontal-rule": "区切り線",
|
||||
"toggle-preview": "プレビュー表示切替え",
|
||||
"mermaid": {
|
||||
"summary": "Mermaid図"
|
||||
}
|
||||
"toggle-preview": "プレビュー表示切替え"
|
||||
},
|
||||
"bufferEditor": {
|
||||
"title": "バッファエディタ",
|
||||
@@ -1228,11 +1210,6 @@
|
||||
"junction": "分岐点",
|
||||
"linkNodes": "Linkノード"
|
||||
},
|
||||
"env-var": {
|
||||
"environment": "環境変数",
|
||||
"header": "大域環境変数",
|
||||
"revert": "破棄"
|
||||
},
|
||||
"action-list": {
|
||||
"toggle-show-tips": "ヒント表示切替",
|
||||
"show-about": "Node-REDの説明を表示",
|
||||
@@ -1317,7 +1294,6 @@
|
||||
"distribute-selection-vertically": "選択を上下に整列",
|
||||
"wire-series-of-nodes": "ノードを一続きに接続",
|
||||
"wire-node-to-multiple": "ノードを複数に接続",
|
||||
"wire-multiple-to-node": "複数からノードへ接続",
|
||||
"split-wire-with-link-nodes": "ワイヤーをlinkノードで分割",
|
||||
"generate-node-names": "ノード名を生成",
|
||||
"show-user-settings": "ユーザ設定を表示",
|
||||
@@ -1377,14 +1353,6 @@
|
||||
"show-project-settings": "プロジェクト設定を表示",
|
||||
"show-version-control-tab": "バージョンコントロールタブを表示",
|
||||
"start-flows": "フローを開始",
|
||||
"stop-flows": "フローを停止",
|
||||
"copy-item-url": "要素のURLをコピー",
|
||||
"copy-item-edit-url": "要素の編集URLをコピー",
|
||||
"move-flow-to-start": "フローを先頭に移動",
|
||||
"move-flow-to-end": "フローを末尾に移動",
|
||||
"show-global-env": "大域環境変数を表示",
|
||||
"lock-flow": "フローを固定",
|
||||
"unlock-flow": "フローの固定を解除",
|
||||
"show-node-help": "ノードのヘルプを表示"
|
||||
"stop-flows": "フローを停止"
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
/**
|
||||
/**
|
||||
* An API for undo / redo history buffer
|
||||
* @namespace RED.history
|
||||
*/
|
||||
@@ -378,8 +378,7 @@ RED.history = (function() {
|
||||
if (ev.addToGroup) {
|
||||
RED.group.removeFromGroup(ev.addToGroup,ev.nodes.map(function(n) { return n.n }),false);
|
||||
inverseEv.removeFromGroup = ev.addToGroup;
|
||||
}
|
||||
if (ev.removeFromGroup) {
|
||||
} else if (ev.removeFromGroup) {
|
||||
RED.group.addToGroup(ev.removeFromGroup,ev.nodes.map(function(n) { return n.n }));
|
||||
inverseEv.addToGroup = ev.removeFromGroup;
|
||||
}
|
||||
@@ -422,9 +421,6 @@ RED.history = (function() {
|
||||
ev.node[i] = ev.changes[i];
|
||||
}
|
||||
}
|
||||
ev.node.dirty = true;
|
||||
ev.node.changed = ev.changed;
|
||||
|
||||
var eventType;
|
||||
switch(ev.node.type) {
|
||||
case 'tab': eventType = "flows"; break;
|
||||
@@ -438,9 +434,7 @@ RED.history = (function() {
|
||||
|
||||
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) {
|
||||
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled);
|
||||
}
|
||||
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('locked')) {
|
||||
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-locked',!!ev.node.locked);
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!ev.node.disabled);
|
||||
}
|
||||
if (ev.subflow) {
|
||||
inverseEv.subflow = {};
|
||||
@@ -515,6 +509,8 @@ RED.history = (function() {
|
||||
inverseEv.links.push(ev.createdLinks[i]);
|
||||
}
|
||||
}
|
||||
ev.node.dirty = true;
|
||||
ev.node.changed = ev.changed;
|
||||
} else if (ev.t == "createSubflow") {
|
||||
inverseEv = {
|
||||
t: "deleteSubflow",
|
||||
@@ -650,12 +646,6 @@ RED.history = (function() {
|
||||
ev.groups[i].nodes = [];
|
||||
RED.nodes.addGroup(ev.groups[i]);
|
||||
RED.group.addToGroup(ev.groups[i],nodes);
|
||||
if (ev.groups[i].g) {
|
||||
const parentGroup = RED.nodes.group(ev.groups[i].g)
|
||||
if (parentGroup) {
|
||||
RED.group.addToGroup(parentGroup, ev.groups[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "addToGroup") {
|
||||
|
@@ -19,6 +19,7 @@
|
||||
* @namespace RED.nodes
|
||||
*/
|
||||
RED.nodes = (function() {
|
||||
|
||||
var PORT_TYPE_INPUT = 1;
|
||||
var PORT_TYPE_OUTPUT = 0;
|
||||
|
||||
@@ -46,9 +47,6 @@ RED.nodes = (function() {
|
||||
|
||||
function setDirty(d) {
|
||||
dirty = d;
|
||||
if (!d) {
|
||||
allNodes.clearState()
|
||||
}
|
||||
RED.events.emit("workspace:dirty",{dirty:dirty});
|
||||
}
|
||||
|
||||
@@ -65,12 +63,12 @@ RED.nodes = (function() {
|
||||
defaults: {
|
||||
label: {value:""},
|
||||
disabled: {value: false},
|
||||
locked: {value: false},
|
||||
info: {value: ""},
|
||||
env: {value: []}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var exports = {
|
||||
setModulePendingUpdated: function(module,version) {
|
||||
moduleList[module].pending_version = version;
|
||||
@@ -240,72 +238,22 @@ RED.nodes = (function() {
|
||||
|
||||
// allNodes holds information about the Flow nodes.
|
||||
var allNodes = (function() {
|
||||
// Map node.id -> node
|
||||
var nodes = {};
|
||||
// Map tab.id -> Array of nodes on that tab
|
||||
var tabMap = {};
|
||||
// Map tab.id -> Set of dirty object ids on that tab
|
||||
var tabDirtyMap = {};
|
||||
// Map tab.id -> Set of object ids of things deleted from the tab that weren't otherwise dirty
|
||||
var tabDeletedNodesMap = {};
|
||||
// Set of object ids of things added to a tab after initial import
|
||||
var addedDirtyObjects = new Set()
|
||||
|
||||
function changeCollectionDepth(tabNodes, toMove, direction, singleStep) {
|
||||
const result = []
|
||||
const moved = new Set();
|
||||
const startIndex = direction ? tabNodes.length - 1 : 0
|
||||
const endIndex = direction ? -1 : tabNodes.length
|
||||
const step = direction ? -1 : 1
|
||||
let target = startIndex // Only used for all-the-way moves
|
||||
for (let i = startIndex; i != endIndex; i += step) {
|
||||
if (toMove.size === 0) {
|
||||
break;
|
||||
}
|
||||
const n = tabNodes[i]
|
||||
if (toMove.has(n)) {
|
||||
if (singleStep) {
|
||||
if (i !== startIndex && !moved.has(tabNodes[i - step])) {
|
||||
tabNodes.splice(i, 1)
|
||||
tabNodes.splice(i - step, 0, n)
|
||||
n._reordered = true
|
||||
result.push(n)
|
||||
}
|
||||
} else {
|
||||
if (i !== target) {
|
||||
tabNodes.splice(i, 1)
|
||||
tabNodes.splice(target, 0, n)
|
||||
n._reordered = true
|
||||
result.push(n)
|
||||
}
|
||||
target += step
|
||||
}
|
||||
toMove.delete(n);
|
||||
moved.add(n);
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var api = {
|
||||
addTab: function(id) {
|
||||
tabMap[id] = [];
|
||||
tabDirtyMap[id] = new Set();
|
||||
tabDeletedNodesMap[id] = new Set();
|
||||
},
|
||||
hasTab: function(z) {
|
||||
return tabMap.hasOwnProperty(z)
|
||||
},
|
||||
removeTab: function(id) {
|
||||
delete tabMap[id];
|
||||
delete tabDirtyMap[id];
|
||||
delete tabDeletedNodesMap[id];
|
||||
},
|
||||
addNode: function(n) {
|
||||
nodes[n.id] = n;
|
||||
if (tabMap.hasOwnProperty(n.z)) {
|
||||
tabMap[n.z].push(n);
|
||||
api.addObjectToWorkspace(n.z, n.id, n.changed || n.moved)
|
||||
} else {
|
||||
console.warn("Node added to unknown tab/subflow:",n);
|
||||
tabMap["_"] = tabMap["_"] || [];
|
||||
@@ -319,37 +267,8 @@ RED.nodes = (function() {
|
||||
if (i > -1) {
|
||||
tabMap[n.z].splice(i,1);
|
||||
}
|
||||
api.removeObjectFromWorkspace(n.z, n.id)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add an object to our dirty/clean tracking state
|
||||
* @param {String} z
|
||||
* @param {String} id
|
||||
* @param {Boolean} isDirty
|
||||
*/
|
||||
addObjectToWorkspace: function (z, id, isDirty) {
|
||||
if (isDirty) {
|
||||
addedDirtyObjects.add(id)
|
||||
}
|
||||
if (tabDeletedNodesMap[z].has(id)) {
|
||||
tabDeletedNodesMap[z].delete(id)
|
||||
}
|
||||
api.markNodeDirty(z, id, isDirty)
|
||||
},
|
||||
/**
|
||||
* Remove an object from our dirty/clean tracking state
|
||||
* @param {String} z
|
||||
* @param {String} id
|
||||
*/
|
||||
removeObjectFromWorkspace: function (z, id) {
|
||||
if (!addedDirtyObjects.has(id)) {
|
||||
tabDeletedNodesMap[z].add(id)
|
||||
} else {
|
||||
addedDirtyObjects.delete(id)
|
||||
}
|
||||
api.markNodeDirty(z, id, false)
|
||||
},
|
||||
hasNode: function(id) {
|
||||
return nodes.hasOwnProperty(id);
|
||||
},
|
||||
@@ -361,54 +280,152 @@ RED.nodes = (function() {
|
||||
n.z = newZ;
|
||||
api.addNode(n)
|
||||
},
|
||||
/**
|
||||
* @param {array} nodes
|
||||
* @param {boolean} direction true:forwards false:back
|
||||
* @param {boolean} singleStep true:single-step false:all-the-way
|
||||
*/
|
||||
changeDepth: function(nodes, direction, singleStep) {
|
||||
moveNodesForwards: function(nodes) {
|
||||
var result = [];
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes]
|
||||
}
|
||||
let result = []
|
||||
const tabNodes = tabMap[nodes[0].z];
|
||||
const toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
|
||||
if (toMove.size > 0) {
|
||||
result = result.concat(changeCollectionDepth(tabNodes, toMove, direction, singleStep))
|
||||
if (result.length > 0) {
|
||||
RED.events.emit('nodes:reorder',{
|
||||
z: nodes[0].z,
|
||||
nodes: result
|
||||
});
|
||||
// Can only do this for nodes on the same tab.
|
||||
// Use nodes[0] to get the z
|
||||
var tabNodes = tabMap[nodes[0].z];
|
||||
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
|
||||
var moved = new Set();
|
||||
for (var i = tabNodes.length-1; i >= 0; i--) {
|
||||
if (toMove.size === 0) {
|
||||
break;
|
||||
}
|
||||
var n = tabNodes[i];
|
||||
if (toMove.has(n)) {
|
||||
// This is a node to move.
|
||||
if (i < tabNodes.length-1 && !moved.has(tabNodes[i+1])) {
|
||||
// Remove from current position
|
||||
tabNodes.splice(i,1);
|
||||
// Add it back one position higher
|
||||
tabNodes.splice(i+1,0,n);
|
||||
n._reordered = true;
|
||||
result.push(n);
|
||||
}
|
||||
toMove.delete(n);
|
||||
moved.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
const groupNodes = groupsByZ[nodes[0].z] || []
|
||||
const groupsToMove = new Set(nodes.filter(function(n) { return n.type === 'group'}))
|
||||
if (groupsToMove.size > 0) {
|
||||
const groupResult = changeCollectionDepth(groupNodes, groupsToMove, direction, singleStep)
|
||||
if (groupResult.length > 0) {
|
||||
result = result.concat(groupResult)
|
||||
RED.events.emit('groups:reorder',{
|
||||
z: nodes[0].z,
|
||||
nodes: groupResult
|
||||
});
|
||||
}
|
||||
if (result.length > 0) {
|
||||
RED.events.emit('nodes:reorder',{
|
||||
z: nodes[0].z,
|
||||
nodes: result
|
||||
});
|
||||
}
|
||||
RED.view.redraw(true)
|
||||
return result
|
||||
},
|
||||
moveNodesForwards: function(nodes) {
|
||||
return api.changeDepth(nodes, true, true)
|
||||
return result;
|
||||
},
|
||||
moveNodesBackwards: function(nodes) {
|
||||
return api.changeDepth(nodes, false, true)
|
||||
var result = [];
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes]
|
||||
}
|
||||
// Can only do this for nodes on the same tab.
|
||||
// Use nodes[0] to get the z
|
||||
var tabNodes = tabMap[nodes[0].z];
|
||||
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
|
||||
var moved = new Set();
|
||||
for (var i = 0; i < tabNodes.length; i++) {
|
||||
if (toMove.size === 0) {
|
||||
break;
|
||||
}
|
||||
var n = tabNodes[i];
|
||||
if (toMove.has(n)) {
|
||||
// This is a node to move.
|
||||
if (i > 0 && !moved.has(tabNodes[i-1])) {
|
||||
// Remove from current position
|
||||
tabNodes.splice(i,1);
|
||||
// Add it back one position lower
|
||||
tabNodes.splice(i-1,0,n);
|
||||
n._reordered = true;
|
||||
result.push(n);
|
||||
}
|
||||
toMove.delete(n);
|
||||
moved.add(n);
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
RED.events.emit('nodes:reorder',{
|
||||
z: nodes[0].z,
|
||||
nodes: result
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
moveNodesToFront: function(nodes) {
|
||||
return api.changeDepth(nodes, true, false)
|
||||
var result = [];
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes]
|
||||
}
|
||||
// Can only do this for nodes on the same tab.
|
||||
// Use nodes[0] to get the z
|
||||
var tabNodes = tabMap[nodes[0].z];
|
||||
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
|
||||
var target = tabNodes.length-1;
|
||||
for (var i = tabNodes.length-1; i >= 0; i--) {
|
||||
if (toMove.size === 0) {
|
||||
break;
|
||||
}
|
||||
var n = tabNodes[i];
|
||||
if (toMove.has(n)) {
|
||||
// This is a node to move.
|
||||
if (i < target) {
|
||||
// Remove from current position
|
||||
tabNodes.splice(i,1);
|
||||
tabNodes.splice(target,0,n);
|
||||
n._reordered = true;
|
||||
result.push(n);
|
||||
}
|
||||
target--;
|
||||
toMove.delete(n);
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
RED.events.emit('nodes:reorder',{
|
||||
z: nodes[0].z,
|
||||
nodes: result
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
moveNodesToBack: function(nodes) {
|
||||
return api.changeDepth(nodes, false, false)
|
||||
var result = [];
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes]
|
||||
}
|
||||
// Can only do this for nodes on the same tab.
|
||||
// Use nodes[0] to get the z
|
||||
var tabNodes = tabMap[nodes[0].z];
|
||||
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
|
||||
var target = 0;
|
||||
for (var i = 0; i < tabNodes.length; i++) {
|
||||
if (toMove.size === 0) {
|
||||
break;
|
||||
}
|
||||
var n = tabNodes[i];
|
||||
if (toMove.has(n)) {
|
||||
// This is a node to move.
|
||||
if (i > target) {
|
||||
// Remove from current position
|
||||
tabNodes.splice(i,1);
|
||||
// Add it back one position lower
|
||||
tabNodes.splice(target,0,n);
|
||||
n._reordered = true;
|
||||
result.push(n);
|
||||
}
|
||||
target++;
|
||||
toMove.delete(n);
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
RED.events.emit('nodes:reorder',{
|
||||
z: nodes[0].z,
|
||||
nodes: result
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
getNodes: function(z) {
|
||||
return tabMap[z];
|
||||
@@ -416,33 +433,6 @@ RED.nodes = (function() {
|
||||
clear: function() {
|
||||
nodes = {};
|
||||
tabMap = {};
|
||||
tabDirtyMap = {};
|
||||
tabDeletedNodesMap = {};
|
||||
addedDirtyObjects = new Set();
|
||||
},
|
||||
/**
|
||||
* Clear all internal state on what is dirty.
|
||||
*/
|
||||
clearState: function () {
|
||||
// Called when a deploy happens, we can forget about added/remove
|
||||
// items as they have now been deployed.
|
||||
addedDirtyObjects = new Set()
|
||||
const flowsToCheck = new Set()
|
||||
for (const [z, set] of Object.entries(tabDeletedNodesMap)) {
|
||||
if (set.size > 0) {
|
||||
set.clear()
|
||||
flowsToCheck.add(z)
|
||||
}
|
||||
}
|
||||
for (const [z, set] of Object.entries(tabDirtyMap)) {
|
||||
if (set.size > 0) {
|
||||
set.clear()
|
||||
flowsToCheck.add(z)
|
||||
}
|
||||
}
|
||||
for (const z of flowsToCheck) {
|
||||
api.checkTabState(z)
|
||||
}
|
||||
},
|
||||
eachNode: function(cb) {
|
||||
var nodeList,i,j;
|
||||
@@ -508,7 +498,7 @@ RED.nodes = (function() {
|
||||
return result;
|
||||
},
|
||||
getNodeOrder: function(z) {
|
||||
return (groupsByZ[z] || []).concat(tabMap[z]).map(n => n.id)
|
||||
return tabMap[z].map(function(n) { return n.id })
|
||||
},
|
||||
setNodeOrder: function(z, order) {
|
||||
var orderMap = {};
|
||||
@@ -520,41 +510,6 @@ RED.nodes = (function() {
|
||||
B._reordered = true;
|
||||
return orderMap[A.id] - orderMap[B.id];
|
||||
})
|
||||
if (groupsByZ[z]) {
|
||||
groupsByZ[z].sort(function(A,B) {
|
||||
return orderMap[A.id] - orderMap[B.id];
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Update our records if an object is dirty or not
|
||||
* @param {String} z tab id
|
||||
* @param {String} id object id
|
||||
* @param {Boolean} dirty whether the object is dirty or not
|
||||
*/
|
||||
markNodeDirty: function(z, id, dirty) {
|
||||
if (tabDirtyMap[z]) {
|
||||
if (dirty) {
|
||||
tabDirtyMap[z].add(id)
|
||||
} else {
|
||||
tabDirtyMap[z].delete(id)
|
||||
}
|
||||
api.checkTabState(z)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Check if a tab should update its contentsChange flag
|
||||
* @param {String} z tab id
|
||||
*/
|
||||
checkTabState: function (z) {
|
||||
const ws = workspaces[z]
|
||||
if (ws) {
|
||||
const contentsChanged = tabDirtyMap[z].size > 0 || tabDeletedNodesMap[z].size > 0
|
||||
if (Boolean(ws.contentsChanged) !== contentsChanged) {
|
||||
ws.contentsChanged = contentsChanged
|
||||
RED.events.emit("flows:change", ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return api;
|
||||
@@ -620,53 +575,15 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
const nodeProxyHandler = {
|
||||
get(node, prop) {
|
||||
if (prop === '__isProxy__') {
|
||||
return true
|
||||
} else if (prop == '__node__') {
|
||||
return node
|
||||
}
|
||||
return node[prop]
|
||||
},
|
||||
set(node, prop, value) {
|
||||
if (node.z && (RED.nodes.workspace(node.z)?.locked || RED.nodes.subflow(node.z)?.locked)) {
|
||||
if (
|
||||
node._def.defaults[prop] ||
|
||||
prop === 'z' ||
|
||||
prop === 'l' ||
|
||||
prop === 'd' ||
|
||||
(prop === 'changed' && (!!node.changed) !== (!!value)) || // jshint ignore:line
|
||||
((prop === 'x' || prop === 'y') && !node.resize && node.type !== 'group')
|
||||
) {
|
||||
throw new Error(`Cannot modified property '${prop}' of locked object '${node.type}:${node.id}'`)
|
||||
}
|
||||
}
|
||||
if (node.z && (prop === 'changed' || prop === 'moved')) {
|
||||
setTimeout(() => {
|
||||
allNodes.markNodeDirty(node.z, node.id, node.changed || node.moved)
|
||||
}, 0)
|
||||
}
|
||||
node[prop] = value;
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
function addNode(n) {
|
||||
let newNode
|
||||
if (!n.__isProxy__) {
|
||||
newNode = new Proxy(n, nodeProxyHandler)
|
||||
} else {
|
||||
newNode = n
|
||||
}
|
||||
|
||||
if (n.type.indexOf("subflow") !== 0) {
|
||||
n["_"] = n._def._;
|
||||
} else {
|
||||
var subflowId = n.type.substring(8);
|
||||
var sf = RED.nodes.subflow(subflowId);
|
||||
if (sf) {
|
||||
sf.instances.push(newNode);
|
||||
sf.instances.push(sf);
|
||||
}
|
||||
n["_"] = RED._;
|
||||
}
|
||||
@@ -683,13 +600,12 @@ RED.nodes = (function() {
|
||||
});
|
||||
n.i = nextId+1;
|
||||
}
|
||||
allNodes.addNode(newNode);
|
||||
allNodes.addNode(n);
|
||||
if (!nodeLinks[n.id]) {
|
||||
nodeLinks[n.id] = {in:[],out:[]};
|
||||
}
|
||||
}
|
||||
RED.events.emit('nodes:add',newNode);
|
||||
return newNode
|
||||
RED.events.emit('nodes:add',n);
|
||||
}
|
||||
function addLink(l) {
|
||||
if (nodeLinks[l.source.id]) {
|
||||
@@ -716,16 +632,10 @@ RED.nodes = (function() {
|
||||
}
|
||||
if (l.source.z === l.target.z && linkTabMap[l.source.z]) {
|
||||
linkTabMap[l.source.z].push(l);
|
||||
allNodes.addObjectToWorkspace(l.source.z, getLinkId(l), true)
|
||||
}
|
||||
RED.events.emit("links:add",l);
|
||||
}
|
||||
|
||||
function getLinkId(link) {
|
||||
return link.source.id + ':' + link.sourcePort + ':' + link.target.id
|
||||
}
|
||||
|
||||
|
||||
function getNode(id) {
|
||||
if (id in configNodes) {
|
||||
return configNodes[id];
|
||||
@@ -920,7 +830,6 @@ RED.nodes = (function() {
|
||||
if (index !== -1) {
|
||||
linkTabMap[l.source.z].splice(index,1)
|
||||
}
|
||||
allNodes.removeObjectFromWorkspace(l.source.z, getLinkId(l))
|
||||
}
|
||||
}
|
||||
RED.events.emit("links:remove",l);
|
||||
@@ -1137,9 +1046,6 @@ RED.nodes = (function() {
|
||||
node.type = n.type;
|
||||
for (var d in n._def.defaults) {
|
||||
if (n._def.defaults.hasOwnProperty(d)) {
|
||||
if (d === 'locked' && !n.locked) {
|
||||
continue
|
||||
}
|
||||
node[d] = n[d];
|
||||
}
|
||||
}
|
||||
@@ -1745,7 +1651,6 @@ RED.nodes = (function() {
|
||||
* Options:
|
||||
* - generateIds - whether to replace all node ids
|
||||
* - addFlow - whether to import nodes to a new tab
|
||||
* - markChanged - whether to set changed=true on all newly imported objects
|
||||
* - reimport - if node has a .z property, dont overwrite it
|
||||
* Only applicible when `generateIds` is false
|
||||
* - importMap - how to resolve any conflicts.
|
||||
@@ -1754,7 +1659,7 @@ RED.nodes = (function() {
|
||||
* - id:replace - import over the top of existing
|
||||
*/
|
||||
function importNodes(newNodesObj,options) { // createNewIds,createMissingWorkspace) {
|
||||
const defOpts = { generateIds: false, addFlow: false, markChanged: false, reimport: false, importMap: {} }
|
||||
const defOpts = { generateIds: false, addFlow: false, reimport: false, importMap: {} }
|
||||
options = Object.assign({}, defOpts, options)
|
||||
options.importMap = options.importMap || {}
|
||||
const createNewIds = options.generateIds;
|
||||
@@ -1780,7 +1685,7 @@ RED.nodes = (function() {
|
||||
newNodes = newNodesObj;
|
||||
}
|
||||
|
||||
if (!Array.isArray(newNodes)) {
|
||||
if (!$.isArray(newNodes)) {
|
||||
newNodes = [newNodes];
|
||||
}
|
||||
|
||||
@@ -2078,9 +1983,6 @@ RED.nodes = (function() {
|
||||
if (!n.z) {
|
||||
delete configNode.z;
|
||||
}
|
||||
if (options.markChanged) {
|
||||
configNode.changed = true
|
||||
}
|
||||
if (n.hasOwnProperty('d')) {
|
||||
configNode.d = n.d;
|
||||
}
|
||||
@@ -2143,9 +2045,6 @@ RED.nodes = (function() {
|
||||
if (n.hasOwnProperty('g')) {
|
||||
node.g = n.g;
|
||||
}
|
||||
if (options.markChanged) {
|
||||
node.changed = true
|
||||
}
|
||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||
if (subflow_denylist[n.z]) {
|
||||
continue;
|
||||
@@ -2196,16 +2095,27 @@ RED.nodes = (function() {
|
||||
} else if (n.type.substring(0,7) === "subflow") {
|
||||
var parentId = n.type.split(":")[1];
|
||||
var subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId);
|
||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||
parentId = subflow.id;
|
||||
node.type = "subflow:"+parentId;
|
||||
node._def = registry.getNodeType(node.type);
|
||||
delete node.i;
|
||||
if (!subflow){
|
||||
node._def = {
|
||||
color:"#fee",
|
||||
defaults: {},
|
||||
label: "unknown: "+n.type,
|
||||
labelStyle: "red-ui-flow-node-label-italic",
|
||||
outputs: n.outputs|| (n.wires && n.wires.length) || 0,
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
}
|
||||
} else {
|
||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||
parentId = subflow.id;
|
||||
node.type = "subflow:"+parentId;
|
||||
node._def = registry.getNodeType(node.type);
|
||||
delete node.i;
|
||||
}
|
||||
node.name = n.name;
|
||||
node.outputs = subflow.out.length;
|
||||
node.inputs = subflow.in.length;
|
||||
node.env = n.env;
|
||||
}
|
||||
node.name = n.name;
|
||||
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
|
||||
@@ -2366,7 +2276,7 @@ RED.nodes = (function() {
|
||||
// get added
|
||||
if (activeSubflow && /^link /.test(n.type) && n.links) {
|
||||
n.links = n.links.filter(function(id) {
|
||||
const otherNode = node_map[id] || RED.nodes.node(id);
|
||||
var otherNode = RED.nodes.node(id);
|
||||
return (otherNode && otherNode.z === activeWorkspace)
|
||||
});
|
||||
}
|
||||
@@ -2416,6 +2326,19 @@ RED.nodes = (function() {
|
||||
if (n.g && !new_group_set.has(n.g)) {
|
||||
delete n.g;
|
||||
}
|
||||
n.nodes = n.nodes.map(function(id) {
|
||||
return node_map[id];
|
||||
})
|
||||
// Just in case the group references a node that doesn't exist for some reason
|
||||
n.nodes = n.nodes.filter(function(v) {
|
||||
if (v) {
|
||||
// Repair any nodes that have forgotten they are in this group
|
||||
if (v.g !== n.id) {
|
||||
v.g = n.id;
|
||||
}
|
||||
}
|
||||
return !!v
|
||||
});
|
||||
if (!n.g) {
|
||||
groupDepthMap[n.id] = 0;
|
||||
}
|
||||
@@ -2438,22 +2361,21 @@ RED.nodes = (function() {
|
||||
return groupDepthMap[A.id] - groupDepthMap[B.id];
|
||||
});
|
||||
for (i=0;i<new_groups.length;i++) {
|
||||
new_groups[i] = addGroup(new_groups[i]);
|
||||
node_map[new_groups[i].id] = new_groups[i]
|
||||
n = new_groups[i];
|
||||
addGroup(n);
|
||||
}
|
||||
|
||||
for (i=0;i<new_junctions.length;i++) {
|
||||
new_junctions[i] = addJunction(new_junctions[i]);
|
||||
node_map[new_junctions[i].id] = new_junctions[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++) {
|
||||
new_nodes[i] = addNode(new_nodes[i])
|
||||
node_map[new_nodes[i].id] = new_nodes[i]
|
||||
var node = new_nodes[i];
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
// Finally validate them all.
|
||||
// This has to be done after everything is added so that any checks for
|
||||
// dependent config nodes will pass
|
||||
@@ -2461,39 +2383,6 @@ RED.nodes = (function() {
|
||||
var node = new_nodes[i];
|
||||
RED.editor.validateNode(node);
|
||||
}
|
||||
const lookupNode = (id) => {
|
||||
const mappedNode = node_map[id]
|
||||
if (!mappedNode) {
|
||||
return null
|
||||
}
|
||||
if (mappedNode.__isProxy__) {
|
||||
return mappedNode
|
||||
} else {
|
||||
return node_map[mappedNode.id]
|
||||
}
|
||||
}
|
||||
// Update groups to reference proxy node objects
|
||||
for (i=0;i<new_groups.length;i++) {
|
||||
n = new_groups[i];
|
||||
// bypass the proxy in case the flow is locked
|
||||
n.__node__.nodes = n.nodes.map(lookupNode)
|
||||
// Just in case the group references a node that doesn't exist for some reason
|
||||
n.__node__.nodes = n.nodes.filter(function(v) {
|
||||
if (v) {
|
||||
// Repair any nodes that have forgotten they are in this group
|
||||
if (v.g !== n.id) {
|
||||
v.g = n.id;
|
||||
}
|
||||
}
|
||||
return !!v
|
||||
});
|
||||
}
|
||||
|
||||
// Update links to use proxy node objects
|
||||
for (i=0;i<new_links.length;i++) {
|
||||
new_links[i].source = lookupNode(new_links[i].source.id) || new_links[i].source
|
||||
new_links[i].target = lookupNode(new_links[i].target.id) || new_links[i].target
|
||||
}
|
||||
|
||||
RED.workspaces.refresh();
|
||||
|
||||
@@ -2622,17 +2511,11 @@ RED.nodes = (function() {
|
||||
junctions = {};
|
||||
junctionsByZ = {};
|
||||
|
||||
var workspaceIds = Object.keys(workspaces);
|
||||
// Ensure all workspaces are unlocked so we don't get any edit-protection
|
||||
// preventing removal
|
||||
workspaceIds.forEach(function(id) {
|
||||
workspaces[id].locked = false
|
||||
});
|
||||
|
||||
var subflowIds = Object.keys(subflows);
|
||||
subflowIds.forEach(function(id) {
|
||||
RED.subflow.removeSubflow(id)
|
||||
});
|
||||
var workspaceIds = Object.keys(workspaces);
|
||||
workspaceIds.forEach(function(id) {
|
||||
RED.workspaces.remove(workspaces[id]);
|
||||
});
|
||||
@@ -2653,15 +2536,10 @@ RED.nodes = (function() {
|
||||
}
|
||||
|
||||
function addGroup(group) {
|
||||
if (!group.__isProxy__) {
|
||||
group = new Proxy(group, nodeProxyHandler)
|
||||
}
|
||||
groupsByZ[group.z] = groupsByZ[group.z] || [];
|
||||
groupsByZ[group.z].push(group);
|
||||
groups[group.id] = group;
|
||||
allNodes.addObjectToWorkspace(group.z, group.id, group.changed || group.moved)
|
||||
RED.events.emit("groups:add",group);
|
||||
return group
|
||||
}
|
||||
function removeGroup(group) {
|
||||
var i = groupsByZ[group.z].indexOf(group);
|
||||
@@ -2676,28 +2554,19 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
RED.group.markDirty(group);
|
||||
allNodes.removeObjectFromWorkspace(group.z, group.id)
|
||||
|
||||
delete groups[group.id];
|
||||
RED.events.emit("groups:remove",group);
|
||||
}
|
||||
function getGroupOrder(z) {
|
||||
const groups = groupsByZ[z]
|
||||
return groups.map(g => g.id)
|
||||
}
|
||||
|
||||
function addJunction(junction) {
|
||||
if (!junction.__isProxy__) {
|
||||
junction = new Proxy(junction, nodeProxyHandler)
|
||||
}
|
||||
junctionsByZ[junction.z] = junctionsByZ[junction.z] || []
|
||||
junctionsByZ[junction.z].push(junction)
|
||||
junctions[junction.id] = junction;
|
||||
if (!nodeLinks[junction.id]) {
|
||||
nodeLinks[junction.id] = {in:[],out:[]};
|
||||
}
|
||||
allNodes.addObjectToWorkspace(junction.z, junction.id, junction.changed || junction.moved)
|
||||
RED.events.emit("junctions:add", junction)
|
||||
return junction
|
||||
}
|
||||
function removeJunction(junction) {
|
||||
var i = junctionsByZ[junction.z].indexOf(junction)
|
||||
@@ -2707,7 +2576,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
delete junctions[junction.id]
|
||||
delete nodeLinks[junction.id];
|
||||
allNodes.removeObjectFromWorkspace(junction.z, junction.id)
|
||||
RED.events.emit("junctions:remove", junction)
|
||||
|
||||
var removedLinks = links.filter(function(l) { return (l.source === junction) || (l.target === junction); });
|
||||
@@ -2945,9 +2813,6 @@ RED.nodes = (function() {
|
||||
RED.view.redraw(true);
|
||||
}
|
||||
});
|
||||
RED.events.on('deploy', function () {
|
||||
allNodes.clearState()
|
||||
})
|
||||
},
|
||||
registry:registry,
|
||||
setNodeList: registry.setNodeList,
|
||||
@@ -2996,7 +2861,7 @@ RED.nodes = (function() {
|
||||
},
|
||||
addWorkspace: addWorkspace,
|
||||
removeWorkspace: removeWorkspace,
|
||||
getWorkspaceOrder: function() { return [...workspacesOrder] },
|
||||
getWorkspaceOrder: function() { return workspacesOrder },
|
||||
setWorkspaceOrder: function(order) { workspacesOrder = order; },
|
||||
workspace: getWorkspace,
|
||||
|
||||
@@ -3050,20 +2915,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
},
|
||||
eachGroup: function(cb) {
|
||||
for (var group of Object.values(groups)) {
|
||||
if (cb(group) === false) {
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
eachJunction: function(cb) {
|
||||
for (var junction of Object.values(junctions)) {
|
||||
if (cb(junction) === false) {
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
node: getNode,
|
||||
|
||||
|
@@ -249,35 +249,8 @@ var RED = (function() {
|
||||
RED.nodes.import(nodes.flows);
|
||||
RED.nodes.dirty(false);
|
||||
RED.view.redraw(true);
|
||||
if (/^#(flow|node|group)\/.+$/.test(currentHash)) {
|
||||
const hashParts = currentHash.split('/')
|
||||
const showEditDialog = hashParts.length > 2 && hashParts[2] === 'edit'
|
||||
if (hashParts[0] === '#flow') {
|
||||
RED.workspaces.show(hashParts[1], true);
|
||||
if (showEditDialog) {
|
||||
RED.workspaces.edit()
|
||||
}
|
||||
} else if (hashParts[0] === '#node') {
|
||||
const nodeToShow = RED.nodes.node(hashParts[1])
|
||||
if (nodeToShow) {
|
||||
setTimeout(() => {
|
||||
RED.view.reveal(nodeToShow.id)
|
||||
window.location.hash = currentHash
|
||||
if (showEditDialog) {
|
||||
RED.editor.edit(nodeToShow)
|
||||
}
|
||||
}, 50)
|
||||
}
|
||||
} else if (hashParts[0] === '#group') {
|
||||
const nodeToShow = RED.nodes.group(hashParts[1])
|
||||
if (nodeToShow) {
|
||||
RED.view.reveal(nodeToShow.id)
|
||||
window.location.hash = currentHash
|
||||
if (showEditDialog) {
|
||||
RED.editor.editGroup(nodeToShow)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (/^#flow\/.+$/.test(currentHash)) {
|
||||
RED.workspaces.show(currentHash.substring(6),true);
|
||||
}
|
||||
if (RED.workspaces.count() > 0) {
|
||||
const hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
@@ -670,6 +643,11 @@ var RED = (function() {
|
||||
]});
|
||||
|
||||
menuOptions.push({id:"menu-item-arrange-menu", label:RED._("menu.label.arrange"), options: [
|
||||
{id: "menu-item-view-tools-move-to-back", label:RED._("menu.label.moveToBack"), disabled: true, onselect: "core:move-selection-to-back"},
|
||||
{id: "menu-item-view-tools-move-to-front", label:RED._("menu.label.moveToFront"), disabled: true, onselect: "core:move-selection-to-front"},
|
||||
{id: "menu-item-view-tools-move-backwards", label:RED._("menu.label.moveBackwards"), disabled: true, onselect: "core:move-selection-backwards"},
|
||||
{id: "menu-item-view-tools-move-forwards", label:RED._("menu.label.moveForwards"), disabled: true, onselect: "core:move-selection-forwards"},
|
||||
null,
|
||||
{id: "menu-item-view-tools-align-left", label:RED._("menu.label.alignLeft"), disabled: true, onselect: "core:align-selection-to-left"},
|
||||
{id: "menu-item-view-tools-align-center", label:RED._("menu.label.alignCenter"), disabled: true, onselect: "core:align-selection-to-center"},
|
||||
{id: "menu-item-view-tools-align-right", label:RED._("menu.label.alignRight"), disabled: true, onselect: "core:align-selection-to-right"},
|
||||
@@ -679,12 +657,7 @@ var RED = (function() {
|
||||
{id: "menu-item-view-tools-align-bottom", label:RED._("menu.label.alignBottom"), disabled: true, onselect: "core:align-selection-to-bottom"},
|
||||
null,
|
||||
{id: "menu-item-view-tools-distribute-horizontally", label:RED._("menu.label.distributeHorizontally"), disabled: true, onselect: "core:distribute-selection-horizontally"},
|
||||
{id: "menu-item-view-tools-distribute-veritcally", label:RED._("menu.label.distributeVertically"), disabled: true, onselect: "core:distribute-selection-vertically"},
|
||||
null,
|
||||
{id: "menu-item-view-tools-move-to-back", label:RED._("menu.label.moveToBack"), disabled: true, onselect: "core:move-selection-to-back"},
|
||||
{id: "menu-item-view-tools-move-to-front", label:RED._("menu.label.moveToFront"), disabled: true, onselect: "core:move-selection-to-front"},
|
||||
{id: "menu-item-view-tools-move-backwards", label:RED._("menu.label.moveBackwards"), disabled: true, onselect: "core:move-selection-backwards"},
|
||||
{id: "menu-item-view-tools-move-forwards", label:RED._("menu.label.moveForwards"), disabled: true, onselect: "core:move-selection-forwards"}
|
||||
{id: "menu-item-view-tools-distribute-veritcally", label:RED._("menu.label.distributeVertically"), disabled: true, onselect: "core:distribute-selection-vertically"}
|
||||
]});
|
||||
|
||||
menuOptions.push(null);
|
||||
@@ -777,7 +750,6 @@ var RED = (function() {
|
||||
RED.deploy.init(RED.settings.theme("deployButton",null));
|
||||
|
||||
RED.keyboard.init(buildMainMenu);
|
||||
RED.envVar.init();
|
||||
|
||||
RED.nodes.init();
|
||||
RED.runtime.init()
|
||||
|
@@ -47,7 +47,7 @@ RED.actionList = (function() {
|
||||
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
|
||||
searchInput = $('<input type="text" data-i18n="[placeholder]keyboard.filterActions">').appendTo(searchDiv).searchBox({
|
||||
change: function() {
|
||||
filterTerm = $(this).val().trim();
|
||||
filterTerm = $(this).val().trim().toLowerCase();
|
||||
filterTerms = filterTerm.split(" ");
|
||||
searchResults.editableList('filter');
|
||||
searchResults.find("li.selected").removeClass("selected");
|
||||
|
@@ -37,13 +37,13 @@ RED.clipboard = (function() {
|
||||
// IE11 workaround
|
||||
// IE does not support data uri scheme for downloading data
|
||||
var blob = new Blob([data], {
|
||||
type: "data:text/plain;charset=utf-8"
|
||||
type: "data:application/json;charset=utf-8"
|
||||
});
|
||||
navigator.msSaveBlob(blob, file);
|
||||
}
|
||||
else {
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data));
|
||||
element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(data));
|
||||
element.setAttribute('download', file);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
@@ -423,10 +423,11 @@ RED.clipboard = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function showImportNodes(library = 'clipboard') {
|
||||
function showImportNodes(mode) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
mode = mode || "clipboard";
|
||||
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(importNodesDialog));
|
||||
@@ -503,7 +504,7 @@ RED.clipboard = (function() {
|
||||
$("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport);
|
||||
$("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)});
|
||||
|
||||
if (RED.workspaces.active() === 0 || RED.workspaces.isLocked()) {
|
||||
if (RED.workspaces.active() === 0) {
|
||||
$("#red-ui-clipboard-dialog-import-opt-current").addClass('disabled').removeClass("selected");
|
||||
$("#red-ui-clipboard-dialog-import-opt-new").addClass("selected");
|
||||
} else {
|
||||
@@ -532,8 +533,8 @@ RED.clipboard = (function() {
|
||||
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
|
||||
})
|
||||
|
||||
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+library);
|
||||
if (library === 'clipboard') {
|
||||
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
|
||||
if (mode === 'clipboard') {
|
||||
setTimeout(function() {
|
||||
$("#red-ui-clipboard-dialog-import-text").trigger("focus");
|
||||
},100)
|
||||
@@ -557,16 +558,13 @@ RED.clipboard = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the export dialog
|
||||
* @params library which export destination to show
|
||||
* @params mode whether to default to 'auto' (default) or 'flow'
|
||||
**/
|
||||
function showExportNodes(library = 'clipboard', mode = 'auto' ) {
|
||||
function showExportNodes(mode) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mode = mode || "clipboard";
|
||||
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(exportNodesDialog));
|
||||
|
||||
@@ -656,12 +654,7 @@ RED.clipboard = (function() {
|
||||
$("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select();
|
||||
|
||||
dialogContainer.i18n();
|
||||
|
||||
var format = RED.settings.flowFilePretty ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini";
|
||||
const userFormat = RED.settings.get("editor.dialog.export.pretty")
|
||||
if (userFormat === false || userFormat === true) {
|
||||
format = userFormat ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini";
|
||||
}
|
||||
|
||||
$("#red-ui-clipboard-dialog-export-fmt-group > a").on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
@@ -677,8 +670,7 @@ RED.clipboard = (function() {
|
||||
var nodes = JSON.parse(flow);
|
||||
|
||||
format = $(this).attr('id');
|
||||
const pretty = format === "red-ui-clipboard-dialog-export-fmt-full";
|
||||
if (pretty) {
|
||||
if (format === 'red-ui-clipboard-dialog-export-fmt-full') {
|
||||
flow = JSON.stringify(nodes,null,4);
|
||||
} else {
|
||||
flow = JSON.stringify(nodes);
|
||||
@@ -687,7 +679,6 @@ RED.clipboard = (function() {
|
||||
setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50);
|
||||
|
||||
$("#red-ui-clipboard-dialog-export-text").trigger("focus");
|
||||
RED.settings.set("editor.dialog.export.pretty", pretty)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -775,15 +766,12 @@ RED.clipboard = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mode === 'flow' && !$("#red-ui-clipboard-dialog-export-rng-flow").hasClass('disabled')) {
|
||||
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
|
||||
}
|
||||
if (format === "red-ui-clipboard-dialog-export-fmt-full") {
|
||||
$("#red-ui-clipboard-dialog-export-fmt-full").trigger("click");
|
||||
} else {
|
||||
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click");
|
||||
}
|
||||
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+library);
|
||||
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
|
||||
|
||||
var dialogHeight = 400;
|
||||
var winHeight = $(window).height();
|
||||
@@ -1278,17 +1266,15 @@ RED.clipboard = (function() {
|
||||
RED.keyboard.add("#red-ui-drop-target", "escape" ,hideDropTarget);
|
||||
|
||||
$('#red-ui-workspace-chart').on("dragenter",function(event) {
|
||||
if (!RED.workspaces.isLocked() && (
|
||||
$.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1)) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
$("#red-ui-drop-target").css({display:'table'}).focus();
|
||||
}
|
||||
});
|
||||
|
||||
$('#red-ui-drop-target').on("dragover",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
RED.workspaces.isLocked()) {
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
@@ -1296,29 +1282,27 @@ RED.clipboard = (function() {
|
||||
hideDropTarget();
|
||||
})
|
||||
.on("drop",function(event) {
|
||||
if (!RED.workspaces.isLocked()) {
|
||||
try {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
|
||||
importNodes(data);
|
||||
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
var files = event.originalEvent.dataTransfer.files;
|
||||
if (files.length === 1) {
|
||||
var file = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function(theFile) {
|
||||
return function(e) {
|
||||
importNodes(e.target.result);
|
||||
};
|
||||
})(file);
|
||||
reader.readAsText(file);
|
||||
}
|
||||
try {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
|
||||
importNodes(data);
|
||||
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
var files = event.originalEvent.dataTransfer.files;
|
||||
if (files.length === 1) {
|
||||
var file = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function(theFile) {
|
||||
return function(e) {
|
||||
importNodes(e.target.result);
|
||||
};
|
||||
})(file);
|
||||
reader.readAsText(file);
|
||||
}
|
||||
} catch(err) {
|
||||
// Ensure any errors throw above doesn't stop the drop target from
|
||||
// being hidden.
|
||||
}
|
||||
} catch(err) {
|
||||
// Ensure any errors throw above doesn't stop the drop target from
|
||||
// being hidden.
|
||||
}
|
||||
hideDropTarget();
|
||||
event.preventDefault();
|
||||
|
@@ -417,9 +417,6 @@
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
cancel: function() {
|
||||
this.element.sortable("cancel");
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
@@ -94,8 +94,8 @@ RED.menu = (function() {
|
||||
|
||||
var link = $(linkContent).appendTo(item);
|
||||
opt.link = link;
|
||||
if (typeof opt.onselect === 'string' || opt.shortcut) {
|
||||
var shortcut = opt.shortcut || RED.keyboard.getShortcut(opt.onselect);
|
||||
if (typeof opt.onselect === 'string') {
|
||||
var shortcut = RED.keyboard.getShortcut(opt.onselect);
|
||||
if (shortcut && shortcut.key) {
|
||||
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label"));
|
||||
}
|
||||
|
@@ -141,29 +141,7 @@ RED.tabs = (function() {
|
||||
})
|
||||
}
|
||||
|
||||
if (options.contextmenu) {
|
||||
wrapper.on('contextmenu', function(evt) {
|
||||
let clickedTab
|
||||
let target = evt.target
|
||||
while(target.nodeName !== 'A' && target.nodeName !== 'UL' && target.nodeName !== 'BODY') {
|
||||
target = target.parentNode
|
||||
}
|
||||
if (target.nodeName === 'A') {
|
||||
const href = target.getAttribute('href')
|
||||
if (href) {
|
||||
clickedTab = tabs[href.slice(1)]
|
||||
}
|
||||
}
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
RED.contextMenu.show({
|
||||
x:evt.clientX-5,
|
||||
y:evt.clientY-5,
|
||||
options: options.contextmenu(clickedTab)
|
||||
})
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
var scrollLeft;
|
||||
var scrollRight;
|
||||
@@ -183,7 +161,7 @@ RED.tabs = (function() {
|
||||
// Assume this is wheel event which might not trigger
|
||||
// the scroll event, so do things manually
|
||||
var sl = scrollContainer.scrollLeft();
|
||||
sl += evt.originalEvent.deltaY;
|
||||
sl -= evt.originalEvent.deltaY;
|
||||
scrollContainer.scrollLeft(sl);
|
||||
}
|
||||
})
|
||||
@@ -829,22 +807,23 @@ RED.tabs = (function() {
|
||||
event.preventDefault();
|
||||
removeTab(tab.id);
|
||||
});
|
||||
RED.popover.tooltip(closeLink,RED._("workspace.closeFlow"));
|
||||
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
|
||||
}
|
||||
if (tab.hideable) {
|
||||
li.addClass("red-ui-tabs-closeable")
|
||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
|
||||
closeLink.append('<i class="fa fa-eye" />');
|
||||
closeLink.append('<i class="fa fa-eye-slash" />');
|
||||
closeLink.on("click",function(event) {
|
||||
event.preventDefault();
|
||||
hideTab(tab.id);
|
||||
});
|
||||
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
|
||||
}
|
||||
// if (tab.hideable) {
|
||||
// li.addClass("red-ui-tabs-closeable")
|
||||
// var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
|
||||
// closeLink.append('<i class="fa fa-eye" />');
|
||||
// closeLink.append('<i class="fa fa-eye-slash" />');
|
||||
// closeLink.on("click",function(event) {
|
||||
// event.preventDefault();
|
||||
// hideTab(tab.id);
|
||||
// });
|
||||
// RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
|
||||
// }
|
||||
|
||||
var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
|
||||
if (options.onselect) {
|
||||
$('<i class="red-ui-tabs-badge-changed fa fa-circle"></i>').appendTo(badges);
|
||||
$('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges);
|
||||
}
|
||||
|
||||
@@ -959,9 +938,6 @@ RED.tabs = (function() {
|
||||
activeIndex: function() {
|
||||
return ul.find("li.active").index()
|
||||
},
|
||||
getTabIndex: function (id) {
|
||||
return ul.find("a[href='#"+id+"']").parent().index()
|
||||
},
|
||||
contains: function(id) {
|
||||
return ul.find("a[href='#"+id+"']").length > 0;
|
||||
},
|
||||
|
@@ -1,6 +1,21 @@
|
||||
RED.contextMenu = (function () {
|
||||
|
||||
let menu;
|
||||
function createMenu() {
|
||||
// menu = RED.popover.menu({
|
||||
// options: [
|
||||
// {
|
||||
// label: 'delete selection',
|
||||
// onselect: function() {
|
||||
// RED.actions.invoke('core:delete-selection')
|
||||
// RED.view.focus()
|
||||
// }
|
||||
// },
|
||||
// { label: 'world' }
|
||||
// ],
|
||||
// width: 200,
|
||||
// })
|
||||
}
|
||||
|
||||
function disposeMenu() {
|
||||
$(document).off("mousedown.red-ui-workspace-context-menu");
|
||||
@@ -13,172 +28,114 @@ RED.contextMenu = (function () {
|
||||
if (menu) {
|
||||
menu.remove()
|
||||
}
|
||||
let menuItems = []
|
||||
if (options.options) {
|
||||
menuItems = options.options
|
||||
} else if (options.type === 'workspace') {
|
||||
const selection = RED.view.selection()
|
||||
const noSelection = !selection || Object.keys(selection).length === 0
|
||||
const hasSelection = (selection.nodes && selection.nodes.length > 0);
|
||||
const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
|
||||
const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
|
||||
const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
|
||||
const hasLinks = wireLinks.length > 0;
|
||||
const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
|
||||
const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
|
||||
const canDelete = hasSelection || hasLinks
|
||||
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
|
||||
const canEdit = !RED.workspaces.isLocked()
|
||||
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
|
||||
const isAllGroups = hasSelection && selection.nodes.filter(n => n.type !== 'group').length === 0
|
||||
const hasGroup = hasSelection && selection.nodes.filter(n => n.type === 'group' ).length > 0
|
||||
const offset = $("#red-ui-workspace-chart").offset()
|
||||
|
||||
let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
|
||||
let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()
|
||||
const selection = RED.view.selection()
|
||||
const noSelection = !selection || Object.keys(selection).length === 0
|
||||
const hasSelection = (selection.nodes && selection.nodes.length > 0);
|
||||
const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
|
||||
const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
|
||||
const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
|
||||
const hasLinks = wireLinks.length > 0;
|
||||
const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
|
||||
const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
|
||||
const canDelete = hasSelection || hasLinks
|
||||
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
|
||||
|
||||
if (RED.view.snapGrid) {
|
||||
const gridSize = RED.view.gridSize()
|
||||
addX = gridSize * Math.floor(addX / gridSize)
|
||||
addY = gridSize * Math.floor(addY / gridSize)
|
||||
}
|
||||
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
|
||||
const offset = $("#red-ui-workspace-chart").offset()
|
||||
|
||||
menuItems.push(
|
||||
{ onselect: 'core:show-action-list', onpostselect: function () { } }
|
||||
)
|
||||
// addX/addY must be the position in the workspace accounting for both scroll and scale
|
||||
// The +5 is because we display the contextMenu -5,-5 to actual click position
|
||||
let addX = (options.x + 5 - offset.left + $("#red-ui-workspace-chart").scrollLeft()) / RED.view.scale()
|
||||
let addY = (options.y + 5 - offset.top + $("#red-ui-workspace-chart").scrollTop()) / RED.view.scale()
|
||||
|
||||
const insertOptions = []
|
||||
menuItems.push({ label: RED._("contextMenu.insert"), options: insertOptions })
|
||||
insertOptions.push(
|
||||
{
|
||||
label: RED._("contextMenu.node"),
|
||||
onselect: function () {
|
||||
RED.view.showQuickAddDialog({
|
||||
position: [addX, addY],
|
||||
touchTrigger: true,
|
||||
splice: isSingleLink ? selection.links[0] : undefined,
|
||||
// spliceMultiple: isMultipleLinks
|
||||
})
|
||||
},
|
||||
disabled: !canEdit
|
||||
},
|
||||
(hasLinks) ? { // has least 1 wire selected
|
||||
label: RED._("contextMenu.junction"),
|
||||
onselect: 'core:split-wires-with-junctions',
|
||||
disabled: !canEdit || !hasLinks
|
||||
} : {
|
||||
label: RED._("contextMenu.junction"),
|
||||
onselect: function () {
|
||||
const nn = {
|
||||
_def: { defaults: {} },
|
||||
type: 'junction',
|
||||
z: RED.workspaces.active(),
|
||||
id: RED.nodes.id(),
|
||||
x: addX,
|
||||
y: addY,
|
||||
w: 0, h: 0,
|
||||
outputs: 1,
|
||||
inputs: 1,
|
||||
dirty: true,
|
||||
moved: true
|
||||
const menuItems = [
|
||||
{ onselect: 'core:show-action-list', onpostselect: function () { } },
|
||||
{
|
||||
label: RED._("contextMenu.insert"),
|
||||
options: [
|
||||
{
|
||||
label: RED._("contextMenu.node"),
|
||||
onselect: function () {
|
||||
RED.view.showQuickAddDialog({
|
||||
position: [addX, addY],
|
||||
touchTrigger: true,
|
||||
splice: isSingleLink ? selection.links[0] : undefined,
|
||||
// spliceMultiple: isMultipleLinks
|
||||
})
|
||||
},
|
||||
onpostselect: function() {
|
||||
// ensure quick add dialog search input has focus
|
||||
$('#red-ui-type-search-input').trigger('focus')
|
||||
}
|
||||
const historyEvent = {
|
||||
dirty: RED.nodes.dirty(),
|
||||
t: 'add',
|
||||
junctions: [nn]
|
||||
}
|
||||
RED.nodes.addJunction(nn);
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.select({nodes: [nn] });
|
||||
RED.view.redraw(true)
|
||||
},
|
||||
disabled: !canEdit
|
||||
},
|
||||
{
|
||||
label: RED._("contextMenu.linkNodes"),
|
||||
onselect: 'core:split-wire-with-link-nodes',
|
||||
disabled: !canEdit || !hasLinks
|
||||
},
|
||||
null,
|
||||
{ onselect: 'core:show-import-dialog', label: RED._('common.label.import')},
|
||||
{ onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') }
|
||||
)
|
||||
if (hasSelection && canEdit) {
|
||||
const nodeOptions = []
|
||||
if (!hasMultipleSelection && !isGroup) {
|
||||
nodeOptions.push(
|
||||
{ onselect: 'core:show-node-help' },
|
||||
null
|
||||
)
|
||||
}
|
||||
nodeOptions.push(
|
||||
{ onselect: 'core:enable-selected-nodes' },
|
||||
{ onselect: 'core:disable-selected-nodes' },
|
||||
null,
|
||||
{ onselect: 'core:show-selected-node-labels' },
|
||||
{ onselect: 'core:hide-selected-node-labels' }
|
||||
)
|
||||
menuItems.push({
|
||||
label: RED._('sidebar.info.node'),
|
||||
options: nodeOptions
|
||||
})
|
||||
menuItems.push({
|
||||
label: RED._('sidebar.info.group'),
|
||||
options: [
|
||||
{ onselect: 'core:group-selection' },
|
||||
{ onselect: 'core:ungroup-selection', disabled: !hasGroup },
|
||||
]
|
||||
})
|
||||
if (hasGroup) {
|
||||
menuItems[menuItems.length - 1].options.push(
|
||||
{ onselect: 'core:merge-selection-to-group', label: RED._("menu.label.groupMergeSelection") }
|
||||
)
|
||||
(hasLinks) ? { // has least 1 wire selected
|
||||
label: RED._("contextMenu.junction"),
|
||||
onselect: 'core:split-wires-with-junctions',
|
||||
disabled: !hasLinks
|
||||
} : {
|
||||
label: RED._("contextMenu.junction"),
|
||||
onselect: function () {
|
||||
const nn = {
|
||||
_def: { defaults: {} },
|
||||
type: 'junction',
|
||||
z: RED.workspaces.active(),
|
||||
id: RED.nodes.id(),
|
||||
x: addX,
|
||||
y: addY,
|
||||
w: 0, h: 0,
|
||||
outputs: 1,
|
||||
inputs: 1,
|
||||
dirty: true
|
||||
}
|
||||
const historyEvent = {
|
||||
dirty: RED.nodes.dirty(),
|
||||
t: 'add',
|
||||
junctions: [nn]
|
||||
}
|
||||
RED.nodes.addJunction(nn);
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.select({nodes: [nn] });
|
||||
RED.view.redraw(true)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: RED._("contextMenu.linkNodes"),
|
||||
onselect: 'core:split-wire-with-link-nodes',
|
||||
disabled: !hasLinks
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
}
|
||||
if (canRemoveFromGroup) {
|
||||
menuItems[menuItems.length - 1].options.push(
|
||||
{ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") }
|
||||
)
|
||||
}
|
||||
menuItems[menuItems.length - 1].options.push(
|
||||
null,
|
||||
{ onselect: 'core:copy-group-style', disabled: !hasGroup },
|
||||
{ onselect: 'core:paste-group-style', disabled: !hasGroup}
|
||||
)
|
||||
}
|
||||
if (canEdit && hasMultipleSelection) {
|
||||
menuItems.push({
|
||||
label: RED._('menu.label.arrange'),
|
||||
options: [
|
||||
{ label:RED._("menu.label.alignLeft"), onselect: "core:align-selection-to-left"},
|
||||
{ label:RED._("menu.label.alignCenter"), onselect: "core:align-selection-to-center"},
|
||||
{ label:RED._("menu.label.alignRight"), onselect: "core:align-selection-to-right"},
|
||||
null,
|
||||
{ label:RED._("menu.label.alignTop"), onselect: "core:align-selection-to-top"},
|
||||
{ label:RED._("menu.label.alignMiddle"), onselect: "core:align-selection-to-middle"},
|
||||
{ label:RED._("menu.label.alignBottom"), onselect: "core:align-selection-to-bottom"},
|
||||
null,
|
||||
{ label:RED._("menu.label.distributeHorizontally"), onselect: "core:distribute-selection-horizontally"},
|
||||
{ label:RED._("menu.label.distributeVertically"), onselect: "core:distribute-selection-vertically"}
|
||||
]
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
menuItems.push(
|
||||
null,
|
||||
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 },
|
||||
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
|
||||
null,
|
||||
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection },
|
||||
{ onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
|
||||
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
|
||||
{ onselect: 'core:delete-selection', disabled: !canDelete },
|
||||
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
|
||||
{ onselect: 'core:select-all-nodes' }
|
||||
)
|
||||
|
||||
if (hasSelection) {
|
||||
menuItems.push(
|
||||
null,
|
||||
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 },
|
||||
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
|
||||
null,
|
||||
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !canEdit || !hasSelection },
|
||||
{ onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
|
||||
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !canEdit || !RED.view.clipboard() },
|
||||
{ onselect: 'core:delete-selection', disabled: !canEdit || !canDelete },
|
||||
{ onselect: 'core:delete-selection-and-reconnect', label: RED._('keyboard.deleteReconnect'), disabled: !canEdit || !canDelete },
|
||||
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
|
||||
{ onselect: 'core:select-all-nodes' },
|
||||
isGroup ?
|
||||
{ onselect: 'core:ungroup-selection', disabled: !isGroup }
|
||||
: { onselect: 'core:group-selection', disabled: !hasSelection }
|
||||
)
|
||||
if (canRemoveFromGroup) {
|
||||
menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var direction = "right";
|
||||
|
@@ -557,17 +557,7 @@ RED.deploy = (function() {
|
||||
} else {
|
||||
RED.notify('<p>' + RED._("deploy.successfulDeploy") + '</p>', "success");
|
||||
}
|
||||
const flowsToLock = new Set()
|
||||
function ensureUnlocked(id) {
|
||||
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null);
|
||||
const isLocked = flow ? flow.locked : false;
|
||||
if (flow && isLocked) {
|
||||
flow.locked = false;
|
||||
flowsToLock.add(flow)
|
||||
}
|
||||
}
|
||||
RED.nodes.eachNode(function (node) {
|
||||
ensureUnlocked(node.z)
|
||||
if (node.changed) {
|
||||
node.dirty = true;
|
||||
node.changed = false;
|
||||
@@ -580,32 +570,7 @@ RED.deploy = (function() {
|
||||
delete node.credentials;
|
||||
}
|
||||
});
|
||||
RED.nodes.eachGroup(function (node) {
|
||||
ensureUnlocked(node.z)
|
||||
if (node.changed) {
|
||||
node.dirty = true;
|
||||
node.changed = false;
|
||||
}
|
||||
if (node.moved) {
|
||||
node.dirty = true;
|
||||
node.moved = false;
|
||||
}
|
||||
})
|
||||
RED.nodes.eachJunction(function (node) {
|
||||
ensureUnlocked(node.z)
|
||||
if (node.changed) {
|
||||
node.dirty = true;
|
||||
node.changed = false;
|
||||
}
|
||||
if (node.moved) {
|
||||
node.dirty = true;
|
||||
node.moved = false;
|
||||
}
|
||||
})
|
||||
RED.nodes.eachConfig(function (confNode) {
|
||||
if (confNode.z) {
|
||||
ensureUnlocked(confNode.z)
|
||||
}
|
||||
confNode.changed = false;
|
||||
if (confNode.credentials) {
|
||||
delete confNode.credentials;
|
||||
@@ -615,16 +580,8 @@ RED.deploy = (function() {
|
||||
subflow.changed = false;
|
||||
});
|
||||
RED.nodes.eachWorkspace(function (ws) {
|
||||
if (ws.changed || ws.added) {
|
||||
ensureUnlocked(ws.z)
|
||||
ws.changed = false;
|
||||
delete ws.added
|
||||
RED.events.emit("flows:change", ws)
|
||||
}
|
||||
ws.changed = false;
|
||||
});
|
||||
flowsToLock.forEach(flow => {
|
||||
flow.locked = true
|
||||
})
|
||||
// Once deployed, cannot undo back to a clean state
|
||||
RED.history.markAllDirty();
|
||||
RED.view.redraw();
|
||||
|
@@ -45,11 +45,13 @@ RED.editor = (function() {
|
||||
var hasChanged;
|
||||
if (node.type.indexOf("subflow:")===0) {
|
||||
subflow = RED.nodes.subflow(node.type.substring(8));
|
||||
isValid = subflow.valid;
|
||||
hasChanged = subflow.changed;
|
||||
if (isValid === undefined) {
|
||||
isValid = validateNode(subflow);
|
||||
if (subflow){
|
||||
isValid = subflow.valid;
|
||||
hasChanged = subflow.changed;
|
||||
if (isValid === undefined) {
|
||||
isValid = validateNode(subflow);
|
||||
hasChanged = subflow.changed;
|
||||
}
|
||||
}
|
||||
validationErrors = validateNodeProperties(node, node._def.defaults, node);
|
||||
node.valid = isValid && validationErrors.length === 0;
|
||||
@@ -860,7 +862,6 @@ RED.editor = (function() {
|
||||
function showEditDialog(node, defaultTab) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
if (node.z && RED.workspaces.isLocked(node.z)) { return }
|
||||
var editing_node = node;
|
||||
var removeInfoEditorOnClose = false;
|
||||
var skipInfoRefreshOnClose = false;
|
||||
@@ -1046,13 +1047,6 @@ RED.editor = (function() {
|
||||
|
||||
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
|
||||
|
||||
var helpButton = $('<button type="button" class="red-ui-button"><i class="fa fa-book"></button>').on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
RED.sidebar.help.show(editing_node.type);
|
||||
}).appendTo(trayFooterLeft);
|
||||
RED.popover.tooltip(helpButton, RED._("sidebar.help.showHelp"));
|
||||
|
||||
$('<input id="node-input-node-disabled" type="checkbox">').prop("checked",!!node.d).appendTo(trayFooterLeft).toggleButton({
|
||||
enabledIcon: "fa-circle-thin",
|
||||
disabledIcon: "fa-ban",
|
||||
@@ -1156,8 +1150,6 @@ RED.editor = (function() {
|
||||
var editing_config_node = RED.nodes.node(id);
|
||||
var activeEditPanes = [];
|
||||
|
||||
if (editing_config_node && editing_config_node.z && RED.workspaces.isLocked(editing_config_node.z)) { return }
|
||||
|
||||
var configNodeScope = ""; // default to global
|
||||
var activeSubflow = RED.nodes.subflow(RED.workspaces.active());
|
||||
if (activeSubflow) {
|
||||
@@ -1200,13 +1192,6 @@ RED.editor = (function() {
|
||||
|
||||
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
|
||||
|
||||
var helpButton = $('<button type="button" class="red-ui-button"><i class="fa fa-book"></button>').on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
RED.sidebar.help.show(editing_config_node.type);
|
||||
}).appendTo(trayFooterLeft);
|
||||
RED.popover.tooltip(helpButton, RED._("sidebar.help.showHelp"));
|
||||
|
||||
$('<input id="node-config-input-node-disabled" type="checkbox">').prop("checked",!!editing_config_node.d).appendTo(trayFooterLeft).toggleButton({
|
||||
enabledIcon: "fa-circle-thin",
|
||||
disabledIcon: "fa-ban",
|
||||
@@ -1711,7 +1696,6 @@ RED.editor = (function() {
|
||||
function showEditGroupDialog(group, defaultTab) {
|
||||
if (buildingEditDialog) { return }
|
||||
buildingEditDialog = true;
|
||||
if (group.z && RED.workspaces.isLocked(group.z)) { return }
|
||||
var editing_node = group;
|
||||
editStack.push(group);
|
||||
RED.view.state(RED.state.EDITING);
|
||||
@@ -1871,15 +1855,11 @@ RED.editor = (function() {
|
||||
workspace.disabled = disabled;
|
||||
|
||||
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
|
||||
if (workspace.id === RED.workspaces.active()) {
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
|
||||
}
|
||||
}
|
||||
|
||||
var locked = $("#node-input-locked").prop("checked");
|
||||
if (workspace.locked !== locked) {
|
||||
editState.changes.locked = workspace.locked;
|
||||
editState.changed = true;
|
||||
workspace.locked = locked;
|
||||
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-locked',!!workspace.locked);
|
||||
}
|
||||
if (editState.changed) {
|
||||
var historyEvent = {
|
||||
t: "edit",
|
||||
@@ -1920,7 +1900,6 @@ RED.editor = (function() {
|
||||
var trayBody = tray.find('.red-ui-tray-body');
|
||||
trayBody.parent().css('overflow','hidden');
|
||||
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
|
||||
var trayFooterRight = $('<div class="red-ui-tray-footer-right"></div>').appendTo(trayFooter)
|
||||
|
||||
var nodeEditPanes = [
|
||||
'editor-tab-flow-properties',
|
||||
@@ -1935,18 +1914,6 @@ RED.editor = (function() {
|
||||
disabledIcon: "fa-ban",
|
||||
invertState: true
|
||||
})
|
||||
|
||||
if (!workspace.hasOwnProperty("locked")) {
|
||||
workspace.locked = false;
|
||||
}
|
||||
$('<input id="node-input-locked" type="checkbox">').prop("checked",workspace.locked).appendTo(trayFooterRight).toggleButton({
|
||||
enabledLabel: RED._("common.label.unlocked"),
|
||||
enabledIcon: "fa-unlock-alt",
|
||||
disabledLabel: RED._("common.label.locked"),
|
||||
disabledIcon: "fa-lock",
|
||||
invertState: true
|
||||
})
|
||||
|
||||
prepareEditDialog(trayBody, nodeEditPanes, workspace, {}, "node-input", defaultTab, function(_activeEditPanes) {
|
||||
activeEditPanes = _activeEditPanes;
|
||||
trayBody.i18n();
|
||||
|
@@ -45,9 +45,6 @@
|
||||
selectedCodeEditor = RED.editor.codeEditor[defaultEditor];
|
||||
initialised = selectedCodeEditor.init();
|
||||
}
|
||||
|
||||
$('<div id="red-ui-image-drop-target"><div data-i18n="[append]workspace.dropImageHere"><i class="fa fa-download"></i><br></div></div>').appendTo('#red-ui-editor');
|
||||
$("#red-ui-image-drop-target").hide();
|
||||
}
|
||||
|
||||
function create(options) {
|
||||
@@ -67,7 +64,6 @@
|
||||
options = {};
|
||||
}
|
||||
|
||||
var editor = null;
|
||||
if (this.editor.type === MONACO) {
|
||||
// compatibility (see above note)
|
||||
if (!options.element && !options.id) {
|
||||
@@ -78,14 +74,10 @@
|
||||
console.warn("createEditor() options.element or options.id is not valid", options);
|
||||
$("#dialog-form").append('<div id="' + options.id + '" style="display: none;" />');
|
||||
}
|
||||
editor = this.editor.create(options);
|
||||
return this.editor.create(options);
|
||||
} else {
|
||||
editor = this.editor.create(options);//fallback to ACE
|
||||
return this.editor.create(options);//fallback to ACE
|
||||
}
|
||||
if (options.mode === "ace/mode/markdown") {
|
||||
RED.editor.customEditTypes['_markdown'].postInit(editor, options);
|
||||
}
|
||||
return editor;
|
||||
}
|
||||
|
||||
return {
|
||||
|
@@ -2,7 +2,7 @@ RED.editor.envVarList = (function() {
|
||||
|
||||
var currentLocale = 'en-US';
|
||||
var DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
|
||||
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred','jsonata'];
|
||||
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred'];
|
||||
|
||||
/**
|
||||
* Create env var edit interface
|
||||
|
@@ -14,61 +14,6 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
(function() {
|
||||
/**
|
||||
* Converts dropped image file to date URL
|
||||
*/
|
||||
function file2base64Image(file, cb) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function (fd) {
|
||||
return function (e) {
|
||||
cb(e.target.result);
|
||||
};
|
||||
})(file);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
var initialized = false;
|
||||
var currentEditor = null;
|
||||
/**
|
||||
* Initialize handler for image file drag events
|
||||
*/
|
||||
function initImageDrag(elem, editor) {
|
||||
$(elem).on("dragenter", function (ev) {
|
||||
ev.preventDefault();
|
||||
$("#red-ui-image-drop-target").css({display:'table'}).focus();
|
||||
currentEditor = editor;
|
||||
});
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
$("#red-ui-image-drop-target").on("dragover", function (ev) {
|
||||
ev.preventDefault();
|
||||
}).on("dragleave", function (ev) {
|
||||
$("#red-ui-image-drop-target").hide();
|
||||
}).on("drop", function (ev) {
|
||||
ev.preventDefault();
|
||||
if ($.inArray("Files",ev.originalEvent.dataTransfer.types) != -1) {
|
||||
var files = ev.originalEvent.dataTransfer.files;
|
||||
if (files.length === 1) {
|
||||
var file = files[0];
|
||||
var name = file.name.toLowerCase();
|
||||
|
||||
if (name.match(/\.(apng|avif|gif|jpeg|png|svg|webp)$/)) {
|
||||
file2base64Image(file, function (image) {
|
||||
var session = currentEditor.getSession();
|
||||
var img = `<img src="${image}"/>\n`;
|
||||
var pos = session.getCursorPosition();
|
||||
session.insert(pos, img);
|
||||
$("#red-ui-image-drop-target").hide();
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$("#red-ui-image-drop-target").hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var toolbarTemplate = '<div style="margin-bottom: 5px">'+
|
||||
'<span class="button-group">'+
|
||||
@@ -169,7 +114,6 @@
|
||||
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
|
||||
mermaid.init();
|
||||
},200);
|
||||
})
|
||||
if (options.header) {
|
||||
@@ -178,7 +122,6 @@
|
||||
|
||||
if (value) {
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
mermaid.init();
|
||||
}
|
||||
panels = RED.panels.create({
|
||||
id:"red-ui-editor-type-markdown-panels",
|
||||
@@ -205,14 +148,10 @@
|
||||
});
|
||||
RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview"));
|
||||
|
||||
if(!expressionEditor._initState) {
|
||||
if (options.cursor) {
|
||||
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
|
||||
}
|
||||
else {
|
||||
expressionEditor.gotoLine(0, 0, false);
|
||||
}
|
||||
}
|
||||
if (options.cursor && !expressionEditor._initState) {
|
||||
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
|
||||
}
|
||||
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
@@ -276,11 +215,7 @@
|
||||
}
|
||||
})
|
||||
return toolbar;
|
||||
},
|
||||
postInit: function (editor, options) {
|
||||
var elem = $("#"+options.id);
|
||||
initImageDrag(elem, editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
RED.editor.registerTypeEditor("_markdown", definition);
|
||||
})();
|
||||
|
@@ -52,6 +52,8 @@
|
||||
node.info = info;
|
||||
}
|
||||
$("#red-ui-tab-"+(node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!node.disabled);
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!node.disabled);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,179 +0,0 @@
|
||||
RED.envVar = (function() {
|
||||
function saveEnvList(list) {
|
||||
const items = list.editableList("items")
|
||||
const new_env = [];
|
||||
items.each(function (i,el) {
|
||||
var data = el.data('data');
|
||||
var item;
|
||||
if (data.nameField && data.valueField) {
|
||||
item = {
|
||||
name: data.nameField.val(),
|
||||
value: data.valueField.typedInput("value"),
|
||||
type: data.valueField.typedInput("type")
|
||||
};
|
||||
new_env.push(item);
|
||||
}
|
||||
});
|
||||
return new_env;
|
||||
}
|
||||
|
||||
function getGlobalConf(create) {
|
||||
var gconf = null;
|
||||
RED.nodes.eachConfig(function (conf) {
|
||||
if (conf.type === "global-config") {
|
||||
gconf = conf;
|
||||
}
|
||||
});
|
||||
if ((gconf === null) && create) {
|
||||
var cred = {
|
||||
_ : {},
|
||||
map: {}
|
||||
};
|
||||
gconf = {
|
||||
id: RED.nodes.id(),
|
||||
type: "global-config",
|
||||
env: [],
|
||||
name: "global-config",
|
||||
label: "",
|
||||
hasUsers: false,
|
||||
users: [],
|
||||
credentials: cred,
|
||||
_def: RED.nodes.getType("global-config"),
|
||||
};
|
||||
RED.nodes.add(gconf);
|
||||
}
|
||||
return gconf;
|
||||
}
|
||||
|
||||
function applyChanges(list) {
|
||||
var gconf = getGlobalConf(false);
|
||||
var new_env = [];
|
||||
var items = list.editableList('items');
|
||||
var credentials = gconf ? gconf.credentials : null;
|
||||
|
||||
if (!credentials) {
|
||||
credentials = {
|
||||
_ : {},
|
||||
map: {}
|
||||
};
|
||||
}
|
||||
items.each(function (i,el) {
|
||||
var data = el.data('data');
|
||||
if (data.nameField && data.valueField) {
|
||||
var item = {
|
||||
name: data.nameField.val(),
|
||||
value: data.valueField.typedInput("value"),
|
||||
type: data.valueField.typedInput("type")
|
||||
};
|
||||
if (item.name.trim() !== "") {
|
||||
new_env.push(item);
|
||||
if ((item.type === "cred") && (item.value !== "__PWRD__")) {
|
||||
credentials.map[item.name] = item.value;
|
||||
credentials.map["has_"+item.name] = (item.value !== "");
|
||||
item.value = "__PWRD__";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (gconf === null) {
|
||||
gconf = getGlobalConf(true);
|
||||
}
|
||||
if ((JSON.stringify(new_env) !== JSON.stringify(gconf.env)) ||
|
||||
(JSON.stringify(credentials) !== JSON.stringify(gconf.credentials))) {
|
||||
gconf.env = new_env;
|
||||
gconf.credentials = credentials;
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
function getSettingsPane() {
|
||||
var gconf = getGlobalConf(false);
|
||||
var env = gconf ? gconf.env : [];
|
||||
var cred = gconf ? gconf.credentials : null;
|
||||
if (!cred) {
|
||||
cred = {
|
||||
_ : {},
|
||||
map: {}
|
||||
};
|
||||
}
|
||||
|
||||
var pane = $("<div/>", {
|
||||
id: "red-ui-settings-tab-envvar",
|
||||
class: "form-horizontal"
|
||||
});
|
||||
var content = $("<div/>", {
|
||||
class: "form-row node-input-env-container-row"
|
||||
}).css({
|
||||
"margin": "10px"
|
||||
}).appendTo(pane);
|
||||
|
||||
var label = $("<label></label>").css({
|
||||
width: "100%"
|
||||
}).appendTo(content);
|
||||
$("<i/>", {
|
||||
class: "fa fa-list"
|
||||
}).appendTo(label);
|
||||
$("<span/>").text(" "+RED._("env-var.header")).appendTo(label);
|
||||
|
||||
var list = $("<ol/>", {
|
||||
id: "node-input-env-container"
|
||||
}).appendTo(content);
|
||||
var node = {
|
||||
type: "",
|
||||
env: env,
|
||||
credentials: cred.map,
|
||||
};
|
||||
RED.editor.envVarList.create(list, node);
|
||||
|
||||
var buttons = $("<div/>").css({
|
||||
"text-align": "right",
|
||||
}).appendTo(content);
|
||||
var revertButton = $("<button/>", {
|
||||
class: "red-ui-button"
|
||||
}).css({
|
||||
}).text(RED._("env-var.revert")).appendTo(buttons);
|
||||
|
||||
var items = saveEnvList(list);
|
||||
revertButton.on("click", function (ev) {
|
||||
list.editableList("empty");
|
||||
list.editableList("addItems", items);
|
||||
});
|
||||
|
||||
return pane;
|
||||
}
|
||||
|
||||
function init(done) {
|
||||
if (!RED.user.hasPermission("settings.write")) {
|
||||
RED.notify(RED._("user.errors.settings"),"error");
|
||||
return;
|
||||
}
|
||||
RED.userSettings.add({
|
||||
id:'envvar',
|
||||
title: RED._("env-var.environment"),
|
||||
get: getSettingsPane,
|
||||
focus: function() {
|
||||
var height = $("#red-ui-settings-tab-envvar").parent().height();
|
||||
$("#node-input-env-container").editableList("height", (height -100));
|
||||
},
|
||||
close: function() {
|
||||
var list = $("#node-input-env-container");
|
||||
try {
|
||||
applyChanges(list);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
console.log(e.stack);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
RED.actions.add("core:show-global-env", function() {
|
||||
RED.userSettings.show('envvar');
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
};
|
||||
|
||||
})();
|
@@ -188,8 +188,6 @@ RED.group = (function() {
|
||||
var activateMerge = false;
|
||||
var activateRemove = false;
|
||||
var singleGroupSelected = false;
|
||||
var locked = RED.workspaces.isLocked()
|
||||
|
||||
if (activateGroup) {
|
||||
singleGroupSelected = selection.nodes.length === 1 && selection.nodes[0].type === 'group';
|
||||
selection.nodes.forEach(function (n) {
|
||||
@@ -204,12 +202,12 @@ RED.group = (function() {
|
||||
activateMerge = (selection.nodes.length > 1);
|
||||
}
|
||||
}
|
||||
RED.menu.setDisabled("menu-item-group-group", locked || !activateGroup);
|
||||
RED.menu.setDisabled("menu-item-group-ungroup", locked || !activateUngroup);
|
||||
RED.menu.setDisabled("menu-item-group-merge", locked || !activateMerge);
|
||||
RED.menu.setDisabled("menu-item-group-remove", locked || !activateRemove);
|
||||
RED.menu.setDisabled("menu-item-group-group", !activateGroup);
|
||||
RED.menu.setDisabled("menu-item-group-ungroup", !activateUngroup);
|
||||
RED.menu.setDisabled("menu-item-group-merge", !activateMerge);
|
||||
RED.menu.setDisabled("menu-item-group-remove", !activateRemove);
|
||||
RED.menu.setDisabled("menu-item-edit-copy-group-style", !singleGroupSelected);
|
||||
RED.menu.setDisabled("menu-item-edit-paste-group-style", locked || !activateUngroup);
|
||||
RED.menu.setDisabled("menu-item-edit-paste-group-style", !activateUngroup);
|
||||
});
|
||||
|
||||
RED.actions.add("core:group-selection", function() { groupSelection() })
|
||||
@@ -266,7 +264,6 @@ RED.group = (function() {
|
||||
}
|
||||
}
|
||||
function pasteGroupStyle() {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
if (groupStyleClipboard) {
|
||||
var selection = RED.view.selection();
|
||||
@@ -301,7 +298,6 @@ RED.group = (function() {
|
||||
}
|
||||
|
||||
function groupSelection() {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
@@ -320,12 +316,11 @@ RED.group = (function() {
|
||||
}
|
||||
}
|
||||
function ungroupSelection() {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var newSelection = [];
|
||||
let groups = selection.nodes.filter(function(n) { return n.type === "group" });
|
||||
groups = selection.nodes.filter(function(n) { return n.type === "group" });
|
||||
|
||||
var historyEvent = {
|
||||
t:"ungroup",
|
||||
@@ -344,7 +339,6 @@ RED.group = (function() {
|
||||
}
|
||||
|
||||
function ungroup(g) {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
var nodes = [];
|
||||
var parentGroup = RED.nodes.group(g.g);
|
||||
g.nodes.forEach(function(n) {
|
||||
@@ -371,7 +365,6 @@ RED.group = (function() {
|
||||
}
|
||||
|
||||
function mergeSelection() {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
@@ -441,7 +434,6 @@ RED.group = (function() {
|
||||
}
|
||||
|
||||
function removeSelection() {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
@@ -469,21 +461,12 @@ RED.group = (function() {
|
||||
}
|
||||
}
|
||||
function createGroup(nodes) {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
const existingGroup = nodes[0].g
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const n = nodes[i]
|
||||
if (n.type === 'subflow') {
|
||||
RED.notify(RED._("group.errors.cannotAddSubflowPorts"),"error");
|
||||
return;
|
||||
}
|
||||
if (n.g !== existingGroup) {
|
||||
console.warn("Cannot add nooes with different z properties")
|
||||
return
|
||||
}
|
||||
if (nodes.filter(function(n) { return n.type === "subflow" }).length > 0) {
|
||||
RED.notify(RED._("group.errors.cannotAddSubflowPorts"),"error");
|
||||
return;
|
||||
}
|
||||
// nodes is an array
|
||||
// each node must be on the same tab (z)
|
||||
@@ -496,16 +479,11 @@ RED.group = (function() {
|
||||
y: Number.POSITIVE_INFINITY,
|
||||
w: 0,
|
||||
h: 0,
|
||||
_def: RED.group.def,
|
||||
changed: true
|
||||
_def: RED.group.def
|
||||
}
|
||||
|
||||
group.z = nodes[0].z;
|
||||
group = RED.nodes.addGroup(group);
|
||||
|
||||
if (existingGroup) {
|
||||
addToGroup(RED.nodes.group(existingGroup), group)
|
||||
}
|
||||
RED.nodes.addGroup(group);
|
||||
|
||||
try {
|
||||
addToGroup(group,nodes);
|
||||
@@ -530,7 +508,7 @@ RED.group = (function() {
|
||||
if (!z) {
|
||||
z = n.z;
|
||||
} else if (z !== n.z) {
|
||||
throw new Error("Cannot add nodes with different z properties")
|
||||
throw new Error("Cannot add nooes with different z properties")
|
||||
}
|
||||
if (n.g) {
|
||||
// This is already in a group.
|
||||
@@ -547,10 +525,14 @@ RED.group = (function() {
|
||||
throw new Error(RED._("group.errors.cannotCreateDiffGroups"))
|
||||
}
|
||||
}
|
||||
// The nodes are already in a group - so we need to remove them first
|
||||
// The nodes are already in a group. The assumption is they should be
|
||||
// wrapped in the newly provided group, and that group added to in their
|
||||
// place to the existing containing group.
|
||||
if (g) {
|
||||
g = RED.nodes.group(g);
|
||||
g.nodes.push(group);
|
||||
g.dirty = true;
|
||||
group.g = g.id;
|
||||
}
|
||||
// Second pass - add them to the group
|
||||
for (i=0;i<nodes.length;i++) {
|
||||
@@ -584,7 +566,6 @@ RED.group = (function() {
|
||||
markDirty(group);
|
||||
}
|
||||
function removeFromGroup(group, nodes, reparent) {
|
||||
if (RED.workspaces.isLocked()) { return }
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes];
|
||||
}
|
||||
@@ -602,7 +583,7 @@ RED.group = (function() {
|
||||
n.dirty = true;
|
||||
var index = group.nodes.indexOf(n);
|
||||
group.nodes.splice(index,1);
|
||||
if (reparent && parentGroup) {
|
||||
if (reparent && group.g) {
|
||||
n.g = group.g
|
||||
parentGroup.nodes.push(n);
|
||||
} else {
|
||||
|
@@ -491,7 +491,11 @@ RED.keyboard = (function() {
|
||||
okButton.attr("disabled",!valid);
|
||||
});
|
||||
|
||||
var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope);
|
||||
var scopeSelect = $('<select>'+
|
||||
'<option value="*" data-i18n="keyboard.global"></option>'+
|
||||
'<option value="red-ui-workspace" data-i18n="keyboard.workspace"></option>'+
|
||||
'<option value="red-ui-editor-stack" data-i18n="keyboard.editor"></option>'+
|
||||
'</select>').appendTo(scope);
|
||||
scopeSelect.i18n();
|
||||
if (object.scope === "workspace") {
|
||||
object.scope = "red-ui-workspace";
|
||||
|
@@ -1,46 +0,0 @@
|
||||
// Mermaid diagram stub library for on-demand dynamic loading
|
||||
// Will be overwritten after script loading by $.getScript
|
||||
var mermaid = (function () {
|
||||
var enabled /* = undefined */;
|
||||
|
||||
var initializing = false;
|
||||
var initCalled = false;
|
||||
|
||||
function initialize(opt) {
|
||||
if (enabled === undefined) {
|
||||
if (RED.settings.markdownEditor &&
|
||||
RED.settings.markdownEditor.mermaid) {
|
||||
enabled = RED.settings.markdownEditor.mermaid.enabled;
|
||||
}
|
||||
else {
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
initializing = true;
|
||||
$.getScript("vendor/mermaid/mermaid.min.js",
|
||||
function (data, stat, jqxhr) {
|
||||
$(".mermaid").show();
|
||||
// invoke loaded mermaid API
|
||||
initializing = false;
|
||||
mermaid.initialize(opt);
|
||||
if (initCalled) {
|
||||
mermaid.init();
|
||||
initCalled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (initializing) {
|
||||
$(".mermaid").hide();
|
||||
initCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
initialize: initialize,
|
||||
init: init,
|
||||
};
|
||||
})();
|
@@ -292,7 +292,6 @@ RED.palette = (function() {
|
||||
var hoverGroup;
|
||||
var paletteWidth;
|
||||
var paletteTop;
|
||||
var dropEnabled;
|
||||
$(d).draggable({
|
||||
helper: 'clone',
|
||||
appendTo: '#red-ui-editor',
|
||||
@@ -300,7 +299,6 @@ RED.palette = (function() {
|
||||
revertDuration: 200,
|
||||
containment:'#red-ui-main-container',
|
||||
start: function() {
|
||||
dropEnabled = !(RED.nodes.workspace(RED.workspaces.active())?.locked);
|
||||
paletteWidth = $("#red-ui-palette").width();
|
||||
paletteTop = $("#red-ui-palette").parent().position().top + $("#red-ui-palette-container").position().top;
|
||||
hoverGroup = null;
|
||||
@@ -311,100 +309,96 @@ RED.palette = (function() {
|
||||
RED.view.focus();
|
||||
},
|
||||
stop: function() {
|
||||
if (dropEnabled) {
|
||||
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
|
||||
if (hoverGroup) {
|
||||
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
|
||||
}
|
||||
if (activeGroup) {
|
||||
document.getElementById("group_select_"+activeGroup.id).classList.remove("red-ui-flow-group-active-hovered");
|
||||
}
|
||||
if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null; }
|
||||
if (groupTimer) { clearTimeout(groupTimer); groupTimer = null; }
|
||||
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
|
||||
if (hoverGroup) {
|
||||
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
|
||||
}
|
||||
if (activeGroup) {
|
||||
document.getElementById("group_select_"+activeGroup.id).classList.remove("red-ui-flow-group-active-hovered");
|
||||
}
|
||||
if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null; }
|
||||
if (groupTimer) { clearTimeout(groupTimer); groupTimer = null; }
|
||||
},
|
||||
drag: function(e,ui) {
|
||||
var paletteNode = getPaletteNode(nt);
|
||||
ui.originalPosition.left = paletteNode.offset().left;
|
||||
if (dropEnabled) {
|
||||
mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft();
|
||||
mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop() + 10;
|
||||
if (!groupTimer) {
|
||||
groupTimer = setTimeout(function() {
|
||||
mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft();
|
||||
mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop() + 10;
|
||||
if (!groupTimer) {
|
||||
groupTimer = setTimeout(function() {
|
||||
var mx = mouseX / RED.view.scale();
|
||||
var my = mouseY / RED.view.scale();
|
||||
var group = RED.view.getGroupAtPoint(mx,my);
|
||||
if (group !== hoverGroup) {
|
||||
if (hoverGroup) {
|
||||
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
|
||||
}
|
||||
if (group) {
|
||||
document.getElementById("group_select_"+group.id).classList.add("red-ui-flow-group-hovered");
|
||||
}
|
||||
hoverGroup = group;
|
||||
if (hoverGroup) {
|
||||
$(ui.helper).data('group',hoverGroup);
|
||||
} else {
|
||||
$(ui.helper).removeData('group');
|
||||
}
|
||||
}
|
||||
groupTimer = null;
|
||||
|
||||
},200)
|
||||
}
|
||||
if (def.inputs > 0 && def.outputs > 0) {
|
||||
if (!spliceTimer) {
|
||||
spliceTimer = setTimeout(function() {
|
||||
var nodes = [];
|
||||
var bestDistance = Infinity;
|
||||
var bestLink = null;
|
||||
if (chartSVG.getIntersectionList) {
|
||||
var svgRect = chartSVG.createSVGRect();
|
||||
svgRect.x = mouseX;
|
||||
svgRect.y = mouseY;
|
||||
svgRect.width = 1;
|
||||
svgRect.height = 1;
|
||||
nodes = chartSVG.getIntersectionList(svgRect,chartSVG);
|
||||
} else {
|
||||
// Firefox doesn't do getIntersectionList and that
|
||||
// makes us sad
|
||||
nodes = RED.view.getLinksAtPoint(mouseX,mouseY);
|
||||
}
|
||||
var mx = mouseX / RED.view.scale();
|
||||
var my = mouseY / RED.view.scale();
|
||||
var group = RED.view.getGroupAtPoint(mx,my);
|
||||
if (group !== hoverGroup) {
|
||||
if (hoverGroup) {
|
||||
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
|
||||
}
|
||||
if (group) {
|
||||
document.getElementById("group_select_"+group.id).classList.add("red-ui-flow-group-hovered");
|
||||
}
|
||||
hoverGroup = group;
|
||||
if (hoverGroup) {
|
||||
$(ui.helper).data('group',hoverGroup);
|
||||
} else {
|
||||
$(ui.helper).removeData('group');
|
||||
}
|
||||
}
|
||||
groupTimer = null;
|
||||
|
||||
},200)
|
||||
}
|
||||
if (def.inputs > 0 && def.outputs > 0) {
|
||||
if (!spliceTimer) {
|
||||
spliceTimer = setTimeout(function() {
|
||||
var nodes = [];
|
||||
var bestDistance = Infinity;
|
||||
var bestLink = null;
|
||||
if (chartSVG.getIntersectionList) {
|
||||
var svgRect = chartSVG.createSVGRect();
|
||||
svgRect.x = mouseX;
|
||||
svgRect.y = mouseY;
|
||||
svgRect.width = 1;
|
||||
svgRect.height = 1;
|
||||
nodes = chartSVG.getIntersectionList(svgRect,chartSVG);
|
||||
} else {
|
||||
// Firefox doesn't do getIntersectionList and that
|
||||
// makes us sad
|
||||
nodes = RED.view.getLinksAtPoint(mouseX,mouseY);
|
||||
}
|
||||
var mx = mouseX / RED.view.scale();
|
||||
var my = mouseY / RED.view.scale();
|
||||
for (var i=0;i<nodes.length;i++) {
|
||||
var node = d3.select(nodes[i]);
|
||||
if (node.classed('red-ui-flow-link-background') && !node.classed('red-ui-flow-link-link')) {
|
||||
var length = nodes[i].getTotalLength();
|
||||
for (var j=0;j<length;j+=10) {
|
||||
var p = nodes[i].getPointAtLength(j);
|
||||
var d2 = ((p.x-mx)*(p.x-mx))+((p.y-my)*(p.y-my));
|
||||
if (d2 < 200 && d2 < bestDistance) {
|
||||
bestDistance = d2;
|
||||
bestLink = nodes[i];
|
||||
}
|
||||
for (var i=0;i<nodes.length;i++) {
|
||||
var node = d3.select(nodes[i]);
|
||||
if (node.classed('red-ui-flow-link-background') && !node.classed('red-ui-flow-link-link')) {
|
||||
var length = nodes[i].getTotalLength();
|
||||
for (var j=0;j<length;j+=10) {
|
||||
var p = nodes[i].getPointAtLength(j);
|
||||
var d2 = ((p.x-mx)*(p.x-mx))+((p.y-my)*(p.y-my));
|
||||
if (d2 < 200 && d2 < bestDistance) {
|
||||
bestDistance = d2;
|
||||
bestLink = nodes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (activeSpliceLink && activeSpliceLink !== bestLink) {
|
||||
d3.select(activeSpliceLink.parentNode).classed('red-ui-flow-link-splice',false);
|
||||
}
|
||||
}
|
||||
if (activeSpliceLink && activeSpliceLink !== bestLink) {
|
||||
d3.select(activeSpliceLink.parentNode).classed('red-ui-flow-link-splice',false);
|
||||
}
|
||||
if (bestLink) {
|
||||
d3.select(bestLink.parentNode).classed('red-ui-flow-link-splice',true)
|
||||
} else {
|
||||
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
|
||||
}
|
||||
if (activeSpliceLink !== bestLink) {
|
||||
if (bestLink) {
|
||||
d3.select(bestLink.parentNode).classed('red-ui-flow-link-splice',true)
|
||||
$(ui.helper).data('splice',d3.select(bestLink).data()[0]);
|
||||
} else {
|
||||
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
|
||||
$(ui.helper).removeData('splice');
|
||||
}
|
||||
if (activeSpliceLink !== bestLink) {
|
||||
if (bestLink) {
|
||||
$(ui.helper).data('splice',d3.select(bestLink).data()[0]);
|
||||
} else {
|
||||
$(ui.helper).removeData('splice');
|
||||
}
|
||||
}
|
||||
activeSpliceLink = bestLink;
|
||||
spliceTimer = null;
|
||||
},200);
|
||||
}
|
||||
}
|
||||
activeSpliceLink = bestLink;
|
||||
spliceTimer = null;
|
||||
},200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -165,9 +165,6 @@ RED.projects.settings = (function() {
|
||||
}
|
||||
var description = addTargetToExternalLinks($('<span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(desc)+'">'+desc+'</span>')).appendTo(container);
|
||||
description.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
||||
setTimeout(function () {
|
||||
mermaid.init();
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function editSummary(activeProject, summary, container, version, versionContainer) {
|
||||
|
@@ -747,14 +747,14 @@ RED.projects = (function() {
|
||||
var row = $('<div class="form-row"></div>').appendTo(body);
|
||||
$('<label for="red-ui-projects-dialog-screen-create-project-file">'+RED._("projects.default-files.flow-file")+'</label>').appendTo(row);
|
||||
var subrow = $('<div style="position:relative;"></div>').appendTo(row);
|
||||
var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || (RED.settings.files && RED.settings.files.flow)||"flow.json";
|
||||
var defaultFlowFile = (createProjectOptions.files &&createProjectOptions.files.flow) || (RED.settings.files && RED.settings.files.flow) || "flows.json";
|
||||
projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val(defaultFlowFile)
|
||||
.on("change keyup paste",validateForm)
|
||||
.appendTo(subrow);
|
||||
$('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);
|
||||
$('<label class="red-ui-projects-edit-form-sublabel"><small>*.json</small></label>').appendTo(row);
|
||||
|
||||
var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || (RED.settings.files && RED.settings.files.credentials)||"flow_cred.json";
|
||||
var defaultCredentialsFile = (createProjectOptions.files &&createProjectOptions.files.credentials) || (RED.settings.files && RED.settings.files.credentials) || "flows_cred.json";
|
||||
row = $('<div class="form-row"></div>').appendTo(body);
|
||||
$('<label for="red-ui-projects-dialog-screen-create-project-credfile">'+RED._("projects.default-files.credentials-file")+'</label>').appendTo(row);
|
||||
subrow = $('<div style="position:relative;"></div>').appendTo(row);
|
||||
@@ -1257,7 +1257,7 @@ RED.projects = (function() {
|
||||
row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty"></div>').appendTo(container);
|
||||
$('<label for="red-ui-projects-dialog-screen-create-project-file">'+RED._("projects.create.flow-file")+'</label>').appendTo(row);
|
||||
subrow = $('<div style="position:relative;"></div>').appendTo(row);
|
||||
projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val("flow.json")
|
||||
projectFlowFileInput = $('<input id="red-ui-projects-dialog-screen-create-project-file" type="text">').val("flows.json")
|
||||
.on("change keyup paste",validateForm)
|
||||
.appendTo(subrow);
|
||||
$('<div class="red-ui-projects-dialog-screen-input-status"></div>').appendTo(subrow);
|
||||
|
@@ -273,11 +273,6 @@ RED.subflow = (function() {
|
||||
var subflowInstances = [];
|
||||
if (activeSubflow) {
|
||||
RED.nodes.filterNodes({type:"subflow:"+activeSubflow.id}).forEach(function(n) {
|
||||
const parentFlow = RED.nodes.workspace(n.z)
|
||||
const wasLocked = parentFlow && parentFlow.locked
|
||||
if (wasLocked) {
|
||||
parentFlow.locked = false
|
||||
}
|
||||
subflowInstances.push({
|
||||
id: n.id,
|
||||
changed: n.changed
|
||||
@@ -290,9 +285,6 @@ RED.subflow = (function() {
|
||||
n.resize = true;
|
||||
n.dirty = true;
|
||||
RED.editor.updateNodeProperties(n);
|
||||
if (wasLocked) {
|
||||
parentFlow.locked = true
|
||||
}
|
||||
});
|
||||
RED.editor.validateNode(activeSubflow);
|
||||
return {
|
||||
@@ -439,7 +431,44 @@ RED.subflow = (function() {
|
||||
|
||||
$("#red-ui-subflow-delete").on("click", function(event) {
|
||||
event.preventDefault();
|
||||
RED.subflow.delete(RED.workspaces.active())
|
||||
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
||||
if (subflow.instances.length > 0) {
|
||||
var msg = $('<div>')
|
||||
$('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
|
||||
$('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg);
|
||||
var confirmDeleteNotification = RED.notify(msg, {
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._('common.label.cancel'),
|
||||
click: function() {
|
||||
confirmDeleteNotification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._('workspace.confirmDelete'),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
confirmDeleteNotification.close();
|
||||
completeDelete();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
return;
|
||||
} else {
|
||||
completeDelete();
|
||||
}
|
||||
function completeDelete() {
|
||||
var startDirty = RED.nodes.dirty();
|
||||
var historyEvent = removeSubflow(RED.workspaces.active());
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = startDirty;
|
||||
RED.history.push(historyEvent);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
refreshToolbar(activeSubflow);
|
||||
@@ -452,51 +481,7 @@ RED.subflow = (function() {
|
||||
$("#red-ui-workspace-toolbar").hide().empty();
|
||||
$("#red-ui-workspace-chart").css({"margin-top": "0"});
|
||||
}
|
||||
function deleteSubflow(id) {
|
||||
const subflow = RED.nodes.subflow(id || RED.workspaces.active());
|
||||
if (!subflow) {
|
||||
return
|
||||
}
|
||||
if (subflow.instances.length > 0) {
|
||||
if (subflow.instances.some(sf => { const ws = RED.nodes.workspace(sf.z); return ws?ws.locked:false })) {
|
||||
return
|
||||
}
|
||||
const msg = $('<div>')
|
||||
$('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
|
||||
$('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg);
|
||||
const confirmDeleteNotification = RED.notify(msg, {
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._('common.label.cancel'),
|
||||
click: function() {
|
||||
confirmDeleteNotification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._('workspace.confirmDelete'),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
confirmDeleteNotification.close();
|
||||
completeDelete();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
return;
|
||||
} else {
|
||||
completeDelete();
|
||||
}
|
||||
function completeDelete() {
|
||||
const startDirty = RED.nodes.dirty();
|
||||
const historyEvent = removeSubflow(subflow.id);
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = startDirty;
|
||||
RED.history.push(historyEvent);
|
||||
}
|
||||
}
|
||||
function removeSubflow(id, keepInstanceNodes) {
|
||||
// TODO: A lot of this logic is common with RED.nodes.removeWorkspace
|
||||
var removedNodes = [];
|
||||
@@ -573,7 +558,7 @@ RED.subflow = (function() {
|
||||
}
|
||||
});
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
if (!selection.nodes || RED.workspaces.isLocked()) {
|
||||
if (!selection.nodes) {
|
||||
RED.menu.setDisabled("menu-item-subflow-convert",true);
|
||||
} else {
|
||||
RED.menu.setDisabled("menu-item-subflow-convert",false);
|
||||
@@ -636,9 +621,6 @@ RED.subflow = (function() {
|
||||
}
|
||||
|
||||
function convertToSubflow() {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
if (!selection.nodes) {
|
||||
RED.notify(RED._("subflow.errors.noNodesSelected"),"error");
|
||||
@@ -681,24 +663,23 @@ RED.subflow = (function() {
|
||||
var candidateOutputs = [];
|
||||
var candidateInputNodes = {};
|
||||
|
||||
var boundingBox = [nodeList[0].x,
|
||||
nodeList[0].y,
|
||||
nodeList[0].x,
|
||||
nodeList[0].y];
|
||||
var boundingBox = [nodeList[0].x-(nodeList[0].w/2),
|
||||
nodeList[0].y-(nodeList[0].h/2),
|
||||
nodeList[0].x+(nodeList[0].w/2),
|
||||
nodeList[0].y+(nodeList[0].h/2)];
|
||||
|
||||
for (i=0;i<nodeList.length;i++) {
|
||||
n = nodeList[i];
|
||||
nodes[n.id] = {n:n,outputs:{}};
|
||||
boundingBox = [
|
||||
Math.min(boundingBox[0],n.x),
|
||||
Math.min(boundingBox[1],n.y),
|
||||
Math.max(boundingBox[2],n.x),
|
||||
Math.max(boundingBox[3],n.y)
|
||||
Math.min(boundingBox[0],n.x-(n.w/2)),
|
||||
Math.min(boundingBox[1],n.y-(n.h/2)),
|
||||
Math.max(boundingBox[2],n.x+(n.w/2)),
|
||||
Math.max(boundingBox[3],n.y+(n.h/2))
|
||||
]
|
||||
}
|
||||
var offsetX = snapToGrid(boundingBox[0] - 200);
|
||||
var offsetY = snapToGrid(boundingBox[1] - 80);
|
||||
|
||||
var offsetX = snapToGrid(boundingBox[0] - 140);
|
||||
var offsetY = snapToGrid(boundingBox[1] - 60);
|
||||
|
||||
var center = [
|
||||
snapToGrid((boundingBox[2]+boundingBox[0]) / 2),
|
||||
@@ -794,7 +775,7 @@ RED.subflow = (function() {
|
||||
}
|
||||
subflowInstance._def = RED.nodes.getType(subflowInstance.type);
|
||||
RED.editor.validateNode(subflowInstance);
|
||||
subflowInstance = RED.nodes.add(subflowInstance);
|
||||
RED.nodes.add(subflowInstance);
|
||||
|
||||
if (containingGroup) {
|
||||
RED.group.addToGroup(containingGroup, subflowInstance);
|
||||
@@ -1348,10 +1329,7 @@ RED.subflow = (function() {
|
||||
init: init,
|
||||
createSubflow: createSubflow,
|
||||
convertToSubflow: convertToSubflow,
|
||||
// removeSubflow: Internal function to remove subflow
|
||||
removeSubflow: removeSubflow,
|
||||
// delete: Prompt user for confirmation
|
||||
delete: deleteSubflow,
|
||||
refresh: refresh,
|
||||
removeInput: removeSubflowInput,
|
||||
removeOutput: removeSubflowOutput,
|
||||
|
@@ -43,15 +43,12 @@ RED.sidebar.config = (function() {
|
||||
|
||||
var categories = {};
|
||||
|
||||
function getOrCreateCategory(name,parent,label,isLocked) {
|
||||
function getOrCreateCategory(name,parent,label) {
|
||||
name = name.replace(/\./i,"-");
|
||||
if (!categories[name]) {
|
||||
var container = $('<div class="red-ui-palette-category red-ui-sidebar-config-category" id="red-ui-sidebar-config-category-'+name+'"></div>').appendTo(parent);
|
||||
var header = $('<div class="red-ui-sidebar-config-tray-header red-ui-palette-header"><i class="fa fa-angle-down expanded"></i></div>').appendTo(container);
|
||||
let lockIcon
|
||||
if (label) {
|
||||
lockIcon = $('<span style="margin-right: 5px"><i class="fa fa-lock"/></span>').appendTo(header)
|
||||
lockIcon.toggle(!!isLocked)
|
||||
$('<span class="red-ui-palette-node-config-label"/>').text(label).appendTo(header);
|
||||
} else {
|
||||
$('<span class="red-ui-palette-node-config-label" data-i18n="sidebar.config.'+name+'">').appendTo(header);
|
||||
@@ -65,7 +62,6 @@ RED.sidebar.config = (function() {
|
||||
var icon = header.find("i");
|
||||
var result = {
|
||||
label: label,
|
||||
lockIcon,
|
||||
list: category,
|
||||
size: function() {
|
||||
return result.list.find("li:not(.red-ui-palette-node-config-none)").length
|
||||
@@ -104,9 +100,6 @@ RED.sidebar.config = (function() {
|
||||
});
|
||||
categories[name] = result;
|
||||
} else {
|
||||
if (isLocked !== undefined && categories[name].lockIcon) {
|
||||
categories[name].lockIcon.toggle(!!isLocked)
|
||||
}
|
||||
if (categories[name].label !== label) {
|
||||
categories[name].list.parent().find('.red-ui-palette-node-config-label').text(label);
|
||||
categories[name].label = label;
|
||||
@@ -145,19 +138,17 @@ RED.sidebar.config = (function() {
|
||||
} else {
|
||||
var currentType = "";
|
||||
nodes.forEach(function(node) {
|
||||
var labelText = RED.utils.getNodeLabel(node,node.id);
|
||||
var label = RED.utils.getNodeLabel(node,node.id);
|
||||
if (node.type != currentType) {
|
||||
$('<li class="red-ui-palette-node-config-type">'+node.type+'</li>').appendTo(list);
|
||||
currentType = node.type;
|
||||
}
|
||||
if (node.changed) {
|
||||
labelText += "!!"
|
||||
}
|
||||
|
||||
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(labelText).appendTo(nodeDiv);
|
||||
var label = $('<div class="red-ui-palette-label"></div>').text(label).appendTo(nodeDiv);
|
||||
if (node.d) {
|
||||
nodeDiv.addClass("red-ui-palette-node-config-disabled");
|
||||
$('<i class="fa fa-ban"></i>').prependTo(label);
|
||||
@@ -225,7 +216,7 @@ RED.sidebar.config = (function() {
|
||||
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
validList[ws.id.replace(/\./g,"-")] = true;
|
||||
getOrCreateCategory(ws.id,flowCategories,ws.label, ws.locked);
|
||||
getOrCreateCategory(ws.id,flowCategories,ws.label);
|
||||
})
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
validList[sf.id.replace(/\./g,"-")] = true;
|
||||
@@ -283,15 +274,6 @@ RED.sidebar.config = (function() {
|
||||
changes: {},
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
for (let i = 0; i < selectedNodes.length; i++) {
|
||||
let node = RED.nodes.node(selectedNodes[i])
|
||||
if (node.z) {
|
||||
let ws = RED.nodes.workspace(node.z)
|
||||
if (ws && ws.locked) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
selectedNodes.forEach(function(id) {
|
||||
var node = RED.nodes.node(id);
|
||||
try {
|
||||
|
@@ -141,8 +141,7 @@ RED.sidebar.help = (function() {
|
||||
RED.events.on('registry:node-type-removed', queueRefresh);
|
||||
RED.events.on('subflows:change', refreshSubflow);
|
||||
|
||||
RED.actions.add("core:show-help-tab", show);
|
||||
RED.actions.add("core:show-node-help", showNodeHelp)
|
||||
RED.actions.add("core:show-help-tab",show);
|
||||
|
||||
}
|
||||
|
||||
@@ -339,19 +338,6 @@ RED.sidebar.help = (function() {
|
||||
resizeStack();
|
||||
}
|
||||
|
||||
function showNodeHelp(node) {
|
||||
if (!node) {
|
||||
const selection = RED.view.selection()
|
||||
if (selection.nodes && selection.nodes.length > 0) {
|
||||
node = selection.nodes.find(n => n.type !== 'group' && n.type !== 'junction')
|
||||
}
|
||||
}
|
||||
if (node) {
|
||||
show(node.type, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: DRY - projects.js
|
||||
function addTargetToExternalLinks(el) {
|
||||
$(el).find("a").each(function(el) {
|
||||
|
@@ -225,22 +225,6 @@ RED.sidebar.info.outliner = (function() {
|
||||
} else {
|
||||
$('<div class="red-ui-info-outline-item-control-spacer">').appendTo(controls)
|
||||
}
|
||||
if (n.type === 'tab') {
|
||||
var lockToggleButton = $('<button type="button" class="red-ui-info-outline-item-control-lock red-ui-button red-ui-button-small"><i class="fa fa-unlock-alt"></i><i class="fa fa-lock"></i></button>').appendTo(controls).on("click",function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (n.locked) {
|
||||
RED.workspaces.unlock(n.id)
|
||||
} else {
|
||||
RED.workspaces.lock(n.id)
|
||||
}
|
||||
})
|
||||
RED.popover.tooltip(lockToggleButton,function() {
|
||||
return RED._("common.label."+(n.locked?"unlock":"lock"));
|
||||
});
|
||||
} else {
|
||||
$('<div class="red-ui-info-outline-item-control-spacer">').appendTo(controls)
|
||||
}
|
||||
controls.find("button").on("dblclick", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
@@ -384,8 +368,6 @@ RED.sidebar.info.outliner = (function() {
|
||||
flowList.treeList.addChild(objects[ws.id])
|
||||
objects[ws.id].element.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
|
||||
objects[ws.id].treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
|
||||
objects[ws.id].element.toggleClass("red-ui-info-outline-item-locked", !!ws.locked)
|
||||
objects[ws.id].treeList.container.toggleClass("red-ui-info-outline-item-locked", !!ws.locked)
|
||||
updateSearch();
|
||||
|
||||
}
|
||||
@@ -400,8 +382,6 @@ RED.sidebar.info.outliner = (function() {
|
||||
existingObject.element.find(".red-ui-info-outline-item-label").text(label);
|
||||
existingObject.element.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled)
|
||||
existingObject.treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled)
|
||||
existingObject.element.toggleClass("red-ui-info-outline-item-locked", !!n.locked)
|
||||
existingObject.treeList.container.toggleClass("red-ui-info-outline-item-locked", !!n.locked)
|
||||
updateSearch();
|
||||
}
|
||||
function onFlowsReorder(order) {
|
||||
|
@@ -25,7 +25,6 @@ RED.sidebar.info = (function() {
|
||||
var propertiesPanelHeaderLabel;
|
||||
var propertiesPanelHeaderReveal;
|
||||
var propertiesPanelHeaderHelp;
|
||||
var propertiesPanelHeaderCopyLink;
|
||||
|
||||
var selectedObject;
|
||||
|
||||
@@ -68,20 +67,10 @@ RED.sidebar.info = (function() {
|
||||
|
||||
propertiesPanelHeaderIcon = $("<span>").appendTo(propertiesPanelHeader);
|
||||
propertiesPanelHeaderLabel = $("<span>").appendTo(propertiesPanelHeader);
|
||||
|
||||
propertiesPanelHeaderCopyLink = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-link"></button>').css({
|
||||
propertiesPanelHeaderHelp = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '12px',
|
||||
right: '32px'
|
||||
}).on("click", function(evt) {
|
||||
RED.actions.invoke('core:copy-item-url',selectedObject)
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
RED.popover.tooltip(propertiesPanelHeaderCopyLink,RED._("sidebar.info.copyItemUrl"));
|
||||
|
||||
propertiesPanelHeaderHelp = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-book"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '12px',
|
||||
right: '56px'
|
||||
}).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
@@ -91,7 +80,8 @@ RED.sidebar.info = (function() {
|
||||
}).appendTo(propertiesPanelHeader);
|
||||
RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp"));
|
||||
|
||||
propertiesPanelHeaderReveal = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-search"></button>').css({
|
||||
|
||||
propertiesPanelHeaderReveal = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-search"></button>').css({
|
||||
position: 'absolute',
|
||||
top: '12px',
|
||||
right: '8px'
|
||||
@@ -195,7 +185,6 @@ RED.sidebar.info = (function() {
|
||||
propertiesPanelHeaderLabel.text("");
|
||||
propertiesPanelHeaderReveal.hide();
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
propertiesPanelHeaderCopyLink.hide();
|
||||
return;
|
||||
} else if (Array.isArray(node)) {
|
||||
// Multiple things selected
|
||||
@@ -207,7 +196,6 @@ RED.sidebar.info = (function() {
|
||||
propertiesPanelHeaderLabel.text("Selection");
|
||||
propertiesPanelHeaderReveal.hide();
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
propertiesPanelHeaderCopyLink.hide();
|
||||
selectedObject = null;
|
||||
|
||||
var types = {
|
||||
@@ -289,11 +277,9 @@ RED.sidebar.info = (function() {
|
||||
if (node.type === "tab" || node.type === "subflow") {
|
||||
// If nothing is selected, but we're on a flow or subflow tab.
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
propertiesPanelHeaderCopyLink.show();
|
||||
|
||||
} else if (node.type === "group") {
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
propertiesPanelHeaderCopyLink.show();
|
||||
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td> </td><td></td></tr>').appendTo(tableBody);
|
||||
|
||||
@@ -318,10 +304,8 @@ RED.sidebar.info = (function() {
|
||||
}
|
||||
} else if (node.type === 'junction') {
|
||||
propertiesPanelHeaderHelp.hide();
|
||||
propertiesPanelHeaderCopyLink.hide();
|
||||
} else {
|
||||
propertiesPanelHeaderHelp.show();
|
||||
propertiesPanelHeaderCopyLink.show();
|
||||
|
||||
if (!subflowRegex) {
|
||||
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("sidebar.info.type")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
@@ -463,8 +447,7 @@ RED.sidebar.info = (function() {
|
||||
el = el.next();
|
||||
}
|
||||
$(this).toggleClass('expanded',!isExpanded);
|
||||
});
|
||||
mermaid.init();
|
||||
})
|
||||
}
|
||||
|
||||
var tips = (function() {
|
||||
|
@@ -435,15 +435,10 @@ RED.tourGuide = (function() {
|
||||
|
||||
function listTour() {
|
||||
return [
|
||||
{
|
||||
id: "3_1",
|
||||
label: "3.1",
|
||||
path: "./tours/welcome.js"
|
||||
},
|
||||
{
|
||||
id: "3_0",
|
||||
label: "3.0",
|
||||
path: "./tours/3.0/welcome.js"
|
||||
path: "./tours/welcome.js"
|
||||
},
|
||||
{
|
||||
id: "2_2",
|
||||
|
@@ -96,37 +96,6 @@ RED.utils = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
var mermaidIsInitialized = false;
|
||||
var mermaidIsEnabled /* = undefined */;
|
||||
|
||||
renderer.code = function (code, lang) {
|
||||
if(lang === "mermaid") {
|
||||
// mermaid diagram rendering
|
||||
if (mermaidIsEnabled === undefined) {
|
||||
if (RED.settings.markdownEditor &&
|
||||
RED.settings.markdownEditor.mermaid) {
|
||||
mermaidIsEnabled = RED.settings.markdownEditor.mermaid.enabled;
|
||||
}
|
||||
else {
|
||||
mermaidIsEnabled = true;
|
||||
}
|
||||
}
|
||||
if (mermaidIsEnabled) {
|
||||
if (!mermaidIsInitialized) {
|
||||
mermaidIsInitialized = true;
|
||||
mermaid.initialize({startOnLoad:false});
|
||||
}
|
||||
return `<pre class='mermaid'>${code}</pre>`;
|
||||
}
|
||||
else {
|
||||
return `<details><summary>${RED._("markdownEditor.mermaid.summary")}</summary><pre><code>${code}</code></pre></details>`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "<pre><code>" +code +"</code></pre>";
|
||||
}
|
||||
};
|
||||
|
||||
window._marked.setOptions({
|
||||
renderer: renderer,
|
||||
gfm: true,
|
||||
|
@@ -15,7 +15,7 @@
|
||||
**/
|
||||
|
||||
RED.view.tools = (function() {
|
||||
'use strict';
|
||||
|
||||
function selectConnected(type) {
|
||||
var selection = RED.view.selection();
|
||||
var visited = new Set();
|
||||
@@ -39,9 +39,6 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function alignToGrid() {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var changedNodes = [];
|
||||
@@ -90,9 +87,6 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function moveSelection(dx,dy) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
if (moving_set === null) {
|
||||
moving_set = [];
|
||||
var selection = RED.view.selection();
|
||||
@@ -159,9 +153,6 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function setSelectedNodeLabelState(labelShown) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
var historyEvents = [];
|
||||
var nodes = [];
|
||||
@@ -448,9 +439,6 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function alignSelectionToEdge(direction) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return;
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
|
||||
if (selection.nodes && selection.nodes.length > 1) {
|
||||
@@ -551,10 +539,8 @@ RED.view.tools = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function distributeSelection(direction) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
|
||||
if (selection.nodes && selection.nodes.length > 2) {
|
||||
@@ -713,16 +699,14 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function reorderSelection(dir) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var nodesToMove = [];
|
||||
selection.nodes.forEach(function(n) {
|
||||
if (n.type === "group") {
|
||||
nodesToMove.push(n)
|
||||
nodesToMove = nodesToMove.concat(RED.group.getNodes(n, true))
|
||||
nodesToMove = nodesToMove.concat(RED.group.getNodes(n, true).filter(function(n) {
|
||||
return n.type !== "group";
|
||||
}))
|
||||
} else if (n.type !== "subflow"){
|
||||
nodesToMove.push(n);
|
||||
}
|
||||
@@ -750,10 +734,8 @@ RED.view.tools = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wireSeriesOfNodes() {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length > 1) {
|
||||
@@ -794,9 +776,6 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function wireNodeToMultiple() {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length > 1) {
|
||||
@@ -839,72 +818,11 @@ RED.view.tools = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function wireMultipleToNode() {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length > 1) {
|
||||
var targetNode = selection.nodes[selection.nodes.length - 1];
|
||||
if (targetNode.inputs === 0) {
|
||||
return;
|
||||
}
|
||||
var i = 0;
|
||||
var newLinks = [];
|
||||
for (i = 0; i < selection.nodes.length - 1; i++) {
|
||||
var sourceNode = selection.nodes[i];
|
||||
if (sourceNode.outputs > 0) {
|
||||
|
||||
// Wire the first output to the target that has no link to the target yet.
|
||||
// This allows for connecting all combinations of inputs/outputs.
|
||||
// The user may then delete links quickly that aren't needed.
|
||||
var sourceConnectedOutports = RED.nodes.filterLinks({
|
||||
source: sourceNode,
|
||||
target: targetNode
|
||||
});
|
||||
|
||||
// Get outport indices that have no link yet
|
||||
var sourceOutportIndices = Array.from({ length: sourceNode.outputs }, (_, i) => i);
|
||||
var sourceConnectedOutportIndices = sourceConnectedOutports.map( x => x.sourcePort );
|
||||
var sourceFreeOutportIndices = sourceOutportIndices.filter(x => !sourceConnectedOutportIndices.includes(x));
|
||||
|
||||
// Does an unconnected source port exist?
|
||||
if (sourceFreeOutportIndices.length == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Connect the first free outport to the target
|
||||
var newLink = {
|
||||
source: sourceNode,
|
||||
target: targetNode,
|
||||
sourcePort: sourceFreeOutportIndices[0]
|
||||
}
|
||||
RED.nodes.addLink(newLink);
|
||||
newLinks.push(newLink);
|
||||
}
|
||||
}
|
||||
if (newLinks.length > 0) {
|
||||
RED.history.push({
|
||||
t: 'add',
|
||||
links: newLinks,
|
||||
dirty: RED.nodes.dirty()
|
||||
})
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
|
||||
if (!wiresToSplit) {
|
||||
return
|
||||
@@ -959,6 +877,7 @@ RED.view.tools = (function() {
|
||||
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) {
|
||||
|
||||
@@ -973,8 +892,7 @@ RED.view.tools = (function() {
|
||||
updateNewNodePosXY(nSrc, nnLinkOut, false, RED.view.snapGrid, yOffset);
|
||||
}
|
||||
//add created node
|
||||
nnLinkOut = RED.nodes.add(nnLinkOut);
|
||||
nodeSrcMap[linkOutMapId] = nnLinkOut;
|
||||
RED.nodes.add(nnLinkOut);
|
||||
RED.editor.validateNode(nnLinkOut);
|
||||
history.events.push(nLinkOut.historyEvent);
|
||||
//connect node to link node
|
||||
@@ -995,10 +913,10 @@ RED.view.tools = (function() {
|
||||
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
|
||||
nnLinkIn = RED.nodes.add(nnLinkIn);
|
||||
nodeTrgMap[nTrg.id] = nnLinkIn;
|
||||
RED.nodes.add(nnLinkIn);
|
||||
RED.editor.validateNode(nnLinkIn);
|
||||
history.events.push(nLinkIn.historyEvent);
|
||||
//connect node to link node
|
||||
@@ -1073,9 +991,6 @@ RED.view.tools = (function() {
|
||||
* @param {{ renameBlank: boolean, renameClash: boolean, generateHistory: boolean }} options Possible options are `renameBlank`, `renameClash` and `generateHistory`
|
||||
*/
|
||||
function generateNodeNames(node, options) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
options = Object.assign({
|
||||
renameBlank: true,
|
||||
renameClash: true,
|
||||
@@ -1146,9 +1061,6 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
function addJunctionsToWires(wires) {
|
||||
if (RED.workspaces.isLocked()) {
|
||||
return
|
||||
}
|
||||
let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
|
||||
if (!wiresToSplit) {
|
||||
return
|
||||
@@ -1190,8 +1102,7 @@ RED.view.tools = (function() {
|
||||
w: 0, h: 0,
|
||||
outputs: 1,
|
||||
inputs: 1,
|
||||
dirty: true,
|
||||
moved: true
|
||||
dirty: true
|
||||
}
|
||||
links = links.filter(function(l) { return !removedLinks.has(l) })
|
||||
if (links.length === 0) {
|
||||
@@ -1220,7 +1131,7 @@ RED.view.tools = (function() {
|
||||
|
||||
var nodeGroups = new Set()
|
||||
|
||||
junction = RED.nodes.addJunction(junction)
|
||||
RED.nodes.addJunction(junction)
|
||||
addedJunctions.push(junction)
|
||||
let newLink
|
||||
if (gid === links[0].source.id+":"+links[0].sourcePort) {
|
||||
@@ -1281,30 +1192,6 @@ RED.view.tools = (function() {
|
||||
RED.view.redraw(true);
|
||||
}
|
||||
|
||||
function copyItemUrl(node, isEdit) {
|
||||
if (!node) {
|
||||
const selection = RED.view.selection();
|
||||
if (selection.nodes && selection.nodes.length > 0) {
|
||||
node = selection.nodes[0]
|
||||
}
|
||||
}
|
||||
if (node) {
|
||||
let thingType = 'node'
|
||||
if (node.type === 'group') {
|
||||
thingType = 'group'
|
||||
} else if (node.type === 'tab' || node.type === 'subflow') {
|
||||
thingType = 'flow'
|
||||
}
|
||||
let url = `${window.location.origin}${window.location.pathname}#${thingType}/${node.id}`
|
||||
if (isEdit) {
|
||||
url += '/edit'
|
||||
}
|
||||
if (RED.clipboard.copyText(url)) {
|
||||
RED.notify(RED._("sidebar.info.copyURL2Clipboard"), { timeout: 2000 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
||||
@@ -1365,16 +1252,12 @@ 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:wire-multiple-to-node", function() { wireMultipleToNode() })
|
||||
|
||||
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
|
||||
RED.actions.add("core:split-wires-with-junctions", function () { addJunctionsToWires() });
|
||||
|
||||
RED.actions.add("core:generate-node-names", generateNodeNames )
|
||||
|
||||
RED.actions.add("core:copy-item-url", function (node) { copyItemUrl(node) })
|
||||
RED.actions.add("core:copy-item-edit-url", function (node) { copyItemUrl(node, true) })
|
||||
|
||||
// RED.actions.add("core:add-node", function() { addNode() })
|
||||
},
|
||||
/**
|
||||
|
@@ -58,9 +58,6 @@ RED.workspaces = (function() {
|
||||
if (!ws.closeable) {
|
||||
ws.hideable = true;
|
||||
}
|
||||
if (!ws.hasOwnProperty('locked')) {
|
||||
ws.locked = false
|
||||
}
|
||||
workspace_tabs.addTab(ws,targetIndex);
|
||||
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
@@ -78,15 +75,11 @@ RED.workspaces = (function() {
|
||||
type: "tab",
|
||||
id: tabId,
|
||||
disabled: false,
|
||||
locked: false,
|
||||
info: "",
|
||||
label: RED._('workspace.defaultName',{number:workspaceIndex}),
|
||||
env: [],
|
||||
hideable: true,
|
||||
hideable: true
|
||||
};
|
||||
if (!skipHistoryEntry) {
|
||||
ws.added = true
|
||||
}
|
||||
RED.nodes.addWorkspace(ws,targetIndex);
|
||||
workspace_tabs.addTab(ws,targetIndex);
|
||||
|
||||
@@ -96,7 +89,8 @@ RED.workspaces = (function() {
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label).toggleClass('red-ui-workspace-changed',!!(ws.contentsChanged || ws.changed || ws.added));
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
|
||||
|
||||
RED.view.focus();
|
||||
return ws;
|
||||
}
|
||||
@@ -105,9 +99,6 @@ RED.workspaces = (function() {
|
||||
if (workspaceTabCount === 1) {
|
||||
return;
|
||||
}
|
||||
if (ws.locked) {
|
||||
return
|
||||
}
|
||||
var workspaceOrder = RED.nodes.getWorkspaceOrder();
|
||||
ws._index = workspaceOrder.indexOf(ws.id);
|
||||
removeWorkspace(ws);
|
||||
@@ -128,206 +119,13 @@ RED.workspaces = (function() {
|
||||
RED.editor.editSubflow(subflow);
|
||||
}
|
||||
} else {
|
||||
if (!workspace.locked) {
|
||||
RED.editor.editFlow(workspace);
|
||||
}
|
||||
RED.editor.editFlow(workspace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var workspace_tabs;
|
||||
var workspaceTabCount = 0;
|
||||
|
||||
function getMenuItems(isMenuButton, tab) {
|
||||
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 hiddenflowCount = hiddenFlows.size;
|
||||
let activeWorkspace = tab || RED.nodes.workspace(RED.workspaces.active()) || RED.nodes.subflow(RED.workspaces.active())
|
||||
let isFlowDisabled = activeWorkspace ? activeWorkspace.disabled : false
|
||||
const currentTabs = workspace_tabs.listTabs();
|
||||
let flowCount = 0;
|
||||
currentTabs.forEach(tab => {
|
||||
if (RED.nodes.workspace(tab)) {
|
||||
flowCount++;
|
||||
}
|
||||
});
|
||||
|
||||
let isCurrentLocked = RED.workspaces.isLocked()
|
||||
if (tab) {
|
||||
isCurrentLocked = tab.locked
|
||||
}
|
||||
|
||||
var menuItems = []
|
||||
if (isMenuButton) {
|
||||
menuItems.push({
|
||||
id:"red-ui-tabs-menu-option-search-flows",
|
||||
label: RED._("workspace.listFlows"),
|
||||
onselect: "core:list-flows"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-search-subflows",
|
||||
label: RED._("workspace.listSubflows"),
|
||||
onselect: "core:list-subflows"
|
||||
},
|
||||
null)
|
||||
}
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow",
|
||||
label: RED._("workspace.addFlow"),
|
||||
onselect: "core:add-flow"
|
||||
}
|
||||
)
|
||||
if (isMenuButton || !!tab) {
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow-right",
|
||||
label: RED._("workspace.addFlowToRight"),
|
||||
shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:add-flow-to-right", tab)
|
||||
}
|
||||
},
|
||||
null
|
||||
)
|
||||
if (activeWorkspace && activeWorkspace.type === 'tab') {
|
||||
menuItems.push(
|
||||
isFlowDisabled ? {
|
||||
label: RED._("workspace.enableFlow"),
|
||||
shortcut: RED.keyboard.getShortcut("core:enable-flow"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:enable-flow", tab?tab.id:undefined)
|
||||
},
|
||||
disabled: isCurrentLocked
|
||||
} : {
|
||||
label: RED._("workspace.disableFlow"),
|
||||
shortcut: RED.keyboard.getShortcut("core:disable-flow"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:disable-flow", tab?tab.id:undefined)
|
||||
},
|
||||
disabled: isCurrentLocked
|
||||
},
|
||||
isCurrentLocked? {
|
||||
label: RED._("workspace.unlockFlow"),
|
||||
shortcut: RED.keyboard.getShortcut("core:unlock-flow"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke('core:unlock-flow', tab?tab.id:undefined)
|
||||
}
|
||||
} : {
|
||||
label: RED._("workspace.lockFlow"),
|
||||
shortcut: RED.keyboard.getShortcut("core:lock-flow"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke('core:lock-flow', tab?tab.id:undefined)
|
||||
}
|
||||
},
|
||||
null
|
||||
)
|
||||
}
|
||||
const activeIndex = currentTabs.findIndex(id => (activeWorkspace && (id === activeWorkspace.id)));
|
||||
menuItems.push(
|
||||
{
|
||||
label: RED._("workspace.moveToStart"),
|
||||
shortcut: RED.keyboard.getShortcut("core:move-flow-to-start"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:move-flow-to-start", tab?tab.id:undefined)
|
||||
},
|
||||
disabled: activeIndex === 0
|
||||
},
|
||||
{
|
||||
label: RED._("workspace.moveToEnd"),
|
||||
shortcut: RED.keyboard.getShortcut("core:move-flow-to-end"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:move-flow-to-end", tab?tab.id:undefined)
|
||||
},
|
||||
disabled: activeIndex === currentTabs.length - 1
|
||||
}
|
||||
)
|
||||
}
|
||||
menuItems.push(null)
|
||||
if (isMenuButton || !!tab) {
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-hide-flows",
|
||||
label: RED._("workspace.hideFlow"),
|
||||
shortcut: RED.keyboard.getShortcut("core:hide-flow"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:hide-flow", tab)
|
||||
}
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-hide-other-flows",
|
||||
label: RED._("workspace.hideOtherFlows"),
|
||||
shortcut: RED.keyboard.getShortcut("core:hide-other-flows"),
|
||||
onselect: function() {
|
||||
RED.actions.invoke("core:hide-other-flows", tab)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
menuItems.push(
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-hide-all-flows",
|
||||
label: RED._("workspace.hideAllFlows"),
|
||||
onselect: "core:hide-all-flows",
|
||||
disabled: (hiddenflowCount === flowCount)
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-show-all-flows",
|
||||
disabled: hiddenflowCount === 0,
|
||||
label: RED._("workspace.showAllFlows", { count: hiddenflowCount }),
|
||||
onselect: "core:show-all-flows"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-show-last-flow",
|
||||
disabled: hideStack.length === 0,
|
||||
label: RED._("workspace.showLastHiddenFlow"),
|
||||
onselect: "core:show-last-hidden-flow"
|
||||
}
|
||||
)
|
||||
if (tab) {
|
||||
menuItems.push(
|
||||
null,
|
||||
{
|
||||
label: RED._("common.label.delete"),
|
||||
onselect: function() {
|
||||
if (tab.type === 'tab') {
|
||||
RED.workspaces.delete(tab)
|
||||
} else if (tab.type === 'subflow') {
|
||||
RED.subflow.delete(tab.id)
|
||||
}
|
||||
},
|
||||
disabled: isCurrentLocked || (workspaceTabCount === 1)
|
||||
},
|
||||
{
|
||||
label: RED._("menu.label.export"),
|
||||
shortcut: RED.keyboard.getShortcut("core:show-export-dialog"),
|
||||
onselect: function() {
|
||||
RED.workspaces.show(tab.id)
|
||||
RED.actions.invoke('core:show-export-dialog', null, 'flow')
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
// if (isMenuButton && hiddenflowCount > 0) {
|
||||
// menuItems.unshift({
|
||||
// label: RED._("workspace.hiddenFlows",{count: hiddenflowCount}),
|
||||
// onselect: "core:list-hidden-flows"
|
||||
// })
|
||||
// }
|
||||
return menuItems;
|
||||
}
|
||||
function createWorkspaceTabs() {
|
||||
workspace_tabs = RED.tabs.create({
|
||||
id: "red-ui-workspace-tabs",
|
||||
@@ -339,9 +137,8 @@ RED.workspaces = (function() {
|
||||
$("#red-ui-workspace-chart").show();
|
||||
activeWorkspace = tab.id;
|
||||
window.location.hash = 'flow/'+tab.id;
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled", !!tab.disabled);
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-locked", !!tab.locked);
|
||||
} else {
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled);
|
||||
} else {
|
||||
$("#red-ui-workspace-chart").hide();
|
||||
activeWorkspace = 0;
|
||||
window.location.hash = '';
|
||||
@@ -372,18 +169,6 @@ RED.workspaces = (function() {
|
||||
if (tab.disabled) {
|
||||
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-disabled');
|
||||
}
|
||||
$('<span class="red-ui-workspace-locked-icon"><i class="fa fa-lock"></i> </span>').prependTo("#red-ui-tab-"+(tab.id.replace(".","-"))+" .red-ui-tab-label");
|
||||
if (tab.locked) {
|
||||
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-locked');
|
||||
}
|
||||
|
||||
const changeBadgeContainer = $('<svg class="red-ui-flow-tab-changed red-ui-flow-node-changed" width="10" height="10" viewBox="-1 -1 12 12"></svg>').appendTo("#red-ui-tab-"+(tab.id.replace(".","-")))
|
||||
const changeBadge = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
||||
changeBadge.setAttribute("cx",5);
|
||||
changeBadge.setAttribute("cy",5);
|
||||
changeBadge.setAttribute("r",5);
|
||||
changeBadgeContainer.append(changeBadge)
|
||||
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
|
||||
if (workspaceTabCount === 1) {
|
||||
showWorkspace();
|
||||
@@ -404,19 +189,13 @@ RED.workspaces = (function() {
|
||||
RED.history.push({
|
||||
t:'reorder',
|
||||
workspaces: {
|
||||
from: oldOrder,
|
||||
to: newOrder
|
||||
from:oldOrder,
|
||||
to:newOrder
|
||||
},
|
||||
dirty:RED.nodes.dirty()
|
||||
});
|
||||
// Only mark flows dirty if flow-order has changed (excluding subflows)
|
||||
const filteredOldOrder = oldOrder.filter(id => !!RED.nodes.workspace(id))
|
||||
const filteredNewOrder = newOrder.filter(id => !!RED.nodes.workspace(id))
|
||||
|
||||
if (JSON.stringify(filteredOldOrder) !== JSON.stringify(filteredNewOrder)) {
|
||||
RED.nodes.dirty(true);
|
||||
setWorkspaceOrder(newOrder);
|
||||
}
|
||||
RED.nodes.dirty(true);
|
||||
setWorkspaceOrder(newOrder);
|
||||
},
|
||||
onselect: function(selectedTabs) {
|
||||
RED.view.select(false)
|
||||
@@ -435,12 +214,12 @@ RED.workspaces = (function() {
|
||||
},
|
||||
onhide: function(tab) {
|
||||
hideStack.push(tab.id);
|
||||
if (tab.type === "tab") {
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
hiddenTabs[tab.id] = true;
|
||||
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
|
||||
RED.events.emit("workspace:hide",{workspace: tab.id})
|
||||
}
|
||||
|
||||
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
|
||||
hiddenTabs[tab.id] = true;
|
||||
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
|
||||
|
||||
RED.events.emit("workspace:hide",{workspace: tab.id})
|
||||
},
|
||||
onshow: function(tab) {
|
||||
removeFromHideStack(tab.id);
|
||||
@@ -455,8 +234,77 @@ RED.workspaces = (function() {
|
||||
scrollable: true,
|
||||
addButton: "core:add-flow",
|
||||
addButtonCaption: RED._("workspace.addFlow"),
|
||||
menu: function() { return getMenuItems(true) },
|
||||
contextmenu: function(tab) { return getMenuItems(false, tab) }
|
||||
menu: function() {
|
||||
var menuItems = [
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-search-flows",
|
||||
label: RED._("workspace.listFlows"),
|
||||
onselect: "core:list-flows"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-search-subflows",
|
||||
label: RED._("workspace.listSubflows"),
|
||||
onselect: "core:list-subflows"
|
||||
},
|
||||
null,
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow",
|
||||
label: RED._("workspace.addFlow"),
|
||||
onselect: "core:add-flow"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-flow-right",
|
||||
label: RED._("workspace.addFlowToRight"),
|
||||
onselect: "core:add-flow-to-right"
|
||||
},
|
||||
null,
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-hide-flows",
|
||||
label: RED._("workspace.hideFlow"),
|
||||
onselect: "core:hide-flow"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-hide-other-flows",
|
||||
label: RED._("workspace.hideOtherFlows"),
|
||||
onselect: "core:hide-other-flows"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-show-all-flows",
|
||||
label: RED._("workspace.showAllFlows"),
|
||||
onselect: "core:show-all-flows"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-hide-all-flows",
|
||||
label: RED._("workspace.hideAllFlows"),
|
||||
onselect: "core:hide-all-flows"
|
||||
},
|
||||
{
|
||||
id:"red-ui-tabs-menu-option-add-show-last-flow",
|
||||
label: RED._("workspace.showLastHiddenFlow"),
|
||||
onselect: "core:show-last-hidden-flow"
|
||||
}
|
||||
]
|
||||
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: flowCount}),
|
||||
onselect: "core:list-hidden-flows"
|
||||
})
|
||||
}
|
||||
return menuItems;
|
||||
}
|
||||
});
|
||||
workspaceTabCount = 0;
|
||||
}
|
||||
@@ -507,33 +355,16 @@ RED.workspaces = (function() {
|
||||
});
|
||||
|
||||
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
|
||||
RED.actions.add("core:add-flow-to-right",function(workspace) {
|
||||
let index
|
||||
if (workspace) {
|
||||
index = workspace_tabs.getTabIndex(workspace.id)+1
|
||||
} else {
|
||||
index = workspace_tabs.activeIndex()+1
|
||||
}
|
||||
addWorkspace(undefined,undefined,index)
|
||||
});
|
||||
RED.actions.add("core:add-flow-to-right",function(opts) { addWorkspace(undefined,undefined,workspace_tabs.activeIndex()+1)});
|
||||
RED.actions.add("core:edit-flow",editWorkspace);
|
||||
RED.actions.add("core:remove-flow",removeWorkspace);
|
||||
RED.actions.add("core:enable-flow",enableWorkspace);
|
||||
RED.actions.add("core:disable-flow",disableWorkspace);
|
||||
RED.actions.add("core:lock-flow",lockWorkspace);
|
||||
RED.actions.add("core:unlock-flow",unlockWorkspace);
|
||||
RED.actions.add("core:move-flow-to-start", function(id) { moveWorkspace(id, 'start') });
|
||||
RED.actions.add("core:move-flow-to-end", function(id) { moveWorkspace(id, 'end') });
|
||||
|
||||
RED.actions.add("core:hide-flow", function(workspace) {
|
||||
let selection
|
||||
if (workspace) {
|
||||
selection = [workspace]
|
||||
} else {
|
||||
selection = workspace_tabs.selection();
|
||||
if (selection.length === 0) {
|
||||
selection = [{id:activeWorkspace}]
|
||||
}
|
||||
RED.actions.add("core:hide-flow", function() {
|
||||
var selection = workspace_tabs.selection();
|
||||
if (selection.length === 0) {
|
||||
selection = [{id:activeWorkspace}]
|
||||
}
|
||||
var hiddenTabs = [];
|
||||
selection.forEach(function(ws) {
|
||||
@@ -547,15 +378,10 @@ RED.workspaces = (function() {
|
||||
workspace_tabs.clearSelection();
|
||||
})
|
||||
|
||||
RED.actions.add("core:hide-other-flows", function(workspace) {
|
||||
let selection
|
||||
if (workspace) {
|
||||
selection = [workspace]
|
||||
} else {
|
||||
selection = workspace_tabs.selection();
|
||||
if (selection.length === 0) {
|
||||
selection = [{id:activeWorkspace}]
|
||||
}
|
||||
RED.actions.add("core:hide-other-flows", function() {
|
||||
var selection = workspace_tabs.selection();
|
||||
if (selection.length === 0) {
|
||||
selection = [{id:activeWorkspace}]
|
||||
}
|
||||
var selected = new Set(selection.map(function(ws) { return ws.id }))
|
||||
|
||||
@@ -645,11 +471,6 @@ RED.workspaces = (function() {
|
||||
RED.workspaces.show(viewStack[++viewStackPos],true);
|
||||
}
|
||||
})
|
||||
|
||||
RED.events.on("flows:change", (ws) => {
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).toggleClass('red-ui-workspace-changed',!!(ws.contentsChanged || ws.changed || ws.added));
|
||||
})
|
||||
|
||||
hideWorkspace();
|
||||
}
|
||||
|
||||
@@ -665,7 +486,7 @@ RED.workspaces = (function() {
|
||||
}
|
||||
function setWorkspaceState(id,disabled) {
|
||||
var workspace = RED.nodes.workspace(id||activeWorkspace);
|
||||
if (!workspace || workspace.locked) {
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
if (workspace.disabled !== disabled) {
|
||||
@@ -700,58 +521,11 @@ RED.workspaces = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
function lockWorkspace(id) {
|
||||
setWorkspaceLockState(id,true);
|
||||
}
|
||||
function unlockWorkspace(id) {
|
||||
setWorkspaceLockState(id,false);
|
||||
}
|
||||
function setWorkspaceLockState(id,locked) {
|
||||
var workspace = RED.nodes.workspace(id||activeWorkspace);
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
if (workspace.locked !== locked) {
|
||||
var changes = { locked: workspace.locked };
|
||||
workspace.locked = locked;
|
||||
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-locked',!!workspace.locked);
|
||||
if (!id || (id === activeWorkspace)) {
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-locked",!!workspace.locked);
|
||||
}
|
||||
var historyEvent = {
|
||||
t: "edit",
|
||||
changes:changes,
|
||||
node: workspace,
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
workspace.changed = true;
|
||||
RED.history.push(historyEvent);
|
||||
RED.events.emit("flows:change",workspace);
|
||||
RED.nodes.dirty(true);
|
||||
// RED.sidebar.config.refresh();
|
||||
// var selection = RED.view.selection();
|
||||
// if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
|
||||
// RED.sidebar.info.refresh(workspace);
|
||||
// }
|
||||
// if (changes.hasOwnProperty('disabled')) {
|
||||
// RED.nodes.eachNode(function(n) {
|
||||
// if (n.z === workspace.id) {
|
||||
// n.dirty = true;
|
||||
// }
|
||||
// });
|
||||
// RED.view.redraw();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
function removeWorkspace(ws) {
|
||||
if (!ws) {
|
||||
ws = RED.nodes.workspace(activeWorkspace)
|
||||
if (ws && !ws.locked) {
|
||||
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
|
||||
}
|
||||
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
|
||||
} else {
|
||||
if (ws.locked) { return }
|
||||
if (workspace_tabs.contains(ws.id)) {
|
||||
workspace_tabs.removeTab(ws.id);
|
||||
}
|
||||
@@ -761,46 +535,16 @@ RED.workspaces = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function moveWorkspace(id, direction) {
|
||||
const workspace = RED.nodes.workspace(id||activeWorkspace) || RED.nodes.subflow(id||activeWorkspace);
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
const currentOrder = workspace_tabs.listTabs()
|
||||
const oldOrder = [...currentOrder]
|
||||
const currentIndex = currentOrder.findIndex(id => id === workspace.id)
|
||||
currentOrder.splice(currentIndex, 1)
|
||||
if (direction === 'start') {
|
||||
currentOrder.unshift(workspace.id)
|
||||
} else if (direction === 'end') {
|
||||
currentOrder.push(workspace.id)
|
||||
}
|
||||
const newOrder = setWorkspaceOrder(currentOrder)
|
||||
if (JSON.stringify(newOrder) !== JSON.stringify(oldOrder)) {
|
||||
RED.history.push({
|
||||
t:'reorder',
|
||||
workspaces: {
|
||||
from:oldOrder,
|
||||
to:newOrder
|
||||
},
|
||||
dirty:RED.nodes.dirty()
|
||||
});
|
||||
const filteredOldOrder = oldOrder.filter(id => !!RED.nodes.workspace(id))
|
||||
const filteredNewOrder = newOrder.filter(id => !!RED.nodes.workspace(id))
|
||||
if (JSON.stringify(filteredOldOrder) !== JSON.stringify(filteredNewOrder)) {
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
function setWorkspaceOrder(order) {
|
||||
var newOrder = order.filter(id => !!RED.nodes.workspace(id))
|
||||
var newOrder = order.filter(function(id) {
|
||||
return RED.nodes.workspace(id) !== undefined;
|
||||
})
|
||||
var currentOrder = RED.nodes.getWorkspaceOrder();
|
||||
if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) {
|
||||
RED.nodes.setWorkspaceOrder(newOrder);
|
||||
RED.events.emit("flows:reorder",newOrder);
|
||||
}
|
||||
workspace_tabs.order(order);
|
||||
return newOrder
|
||||
}
|
||||
|
||||
function flashTab(tabId) {
|
||||
@@ -846,11 +590,6 @@ RED.workspaces = (function() {
|
||||
active: function() {
|
||||
return activeWorkspace
|
||||
},
|
||||
isLocked: function(id) {
|
||||
id = id || activeWorkspace
|
||||
var ws = RED.nodes.workspace(id) || RED.nodes.subflow(id)
|
||||
return ws && ws.locked
|
||||
},
|
||||
selection: function() {
|
||||
return workspace_tabs.selection();
|
||||
},
|
||||
@@ -907,8 +646,6 @@ RED.workspaces = (function() {
|
||||
workspace_tabs.resize();
|
||||
},
|
||||
enable: enableWorkspace,
|
||||
disable: disableWorkspace,
|
||||
lock: lockWorkspace,
|
||||
unlock: unlockWorkspace
|
||||
disable: disableWorkspace
|
||||
}
|
||||
})();
|
||||
|
@@ -37,27 +37,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#red-ui-image-drop-target {
|
||||
position: absolute;
|
||||
top: 0; bottom: 0;
|
||||
left: 0; right: 0;
|
||||
background: var(--red-ui-dnd-background);
|
||||
display:table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
z-index:100;
|
||||
div {
|
||||
pointer-events: none;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-size: 40px;
|
||||
color: var(--red-ui-dnd-color);
|
||||
i {
|
||||
pointer-events: none;
|
||||
font-size: 80px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -87,18 +87,16 @@
|
||||
padding: 0px 8px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
&.toggle.selected {
|
||||
&.toggle:not(.selected) {
|
||||
color: var(--red-ui-workspace-button-color-selected) !important;
|
||||
background: var(--red-ui-workspace-button-background) !important;
|
||||
background: var(--red-ui-workspace-button-background-active);
|
||||
}
|
||||
}
|
||||
|
||||
.red-ui-tray-footer-left {
|
||||
display:inline-block;
|
||||
margin-right: 20px;
|
||||
float:left;
|
||||
& :not(:first-child) {
|
||||
margin-left: 5px
|
||||
}
|
||||
}
|
||||
.red-ui-tray-footer-right {
|
||||
float: right;
|
||||
@@ -126,7 +124,7 @@
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding:0;
|
||||
|
||||
overflow-wrap: anywhere;
|
||||
li {
|
||||
display: inline-block;
|
||||
padding:0;
|
||||
|
@@ -68,9 +68,6 @@
|
||||
stroke: var(--red-ui-node-border);
|
||||
cursor: move;
|
||||
stroke-width: 1;
|
||||
.red-ui-workspace-locked & {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.red-ui-workspace-select-mode {
|
||||
g.red-ui-flow-node.red-ui-flow-node-hovered * {
|
||||
@@ -91,13 +88,10 @@
|
||||
|
||||
.red-ui-flow-group {
|
||||
&.red-ui-flow-group-hovered {
|
||||
.red-ui-flow-group-outline-select-line {
|
||||
.red-ui-flow-group-outline-select {
|
||||
stroke-opacity: 0.8 !important;
|
||||
stroke-dasharray: 10 4 !important;
|
||||
}
|
||||
.red-ui-flow-group-outline-select-outline {
|
||||
stroke-opacity: 0.8 !important;
|
||||
}
|
||||
}
|
||||
&.red-ui-flow-group-active-hovered:not(.red-ui-flow-group-hovered) {
|
||||
.red-ui-flow-group-outline-select {
|
||||
@@ -116,35 +110,15 @@
|
||||
.red-ui-flow-group-outline-select {
|
||||
fill: none;
|
||||
stroke: var(--red-ui-node-selected-color);
|
||||
pointer-events: none;
|
||||
pointer-events: stroke;
|
||||
stroke-opacity: 0;
|
||||
stroke-width: 2;
|
||||
stroke-width: 3;
|
||||
|
||||
&.red-ui-flow-group-outline-select-outline {
|
||||
stroke: var(--red-ui-view-background);
|
||||
stroke-width: 4;
|
||||
}
|
||||
&.red-ui-flow-group-outline-select-background {
|
||||
fill: white;
|
||||
fill-opacity: 0;
|
||||
pointer-events: stroke;
|
||||
stroke-width: 16;
|
||||
stroke: var(--red-ui-view-background);
|
||||
stroke-width: 6;
|
||||
}
|
||||
}
|
||||
|
||||
svg:not(.red-ui-workspace-lasso-active) {
|
||||
.red-ui-flow-group:not(.red-ui-flow-group-selected) {
|
||||
.red-ui-flow-group-outline-select.red-ui-flow-group-outline-select-background:hover {
|
||||
~ .red-ui-flow-group-outline-select {
|
||||
stroke-opacity: 0.4 !important;
|
||||
}
|
||||
~ .red-ui-flow-group-outline-select-line {
|
||||
stroke-dasharray: 10 4 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.red-ui-flow-group-body {
|
||||
pointer-events: none;
|
||||
fill: var(--red-ui-group-default-fill);
|
||||
@@ -313,11 +287,9 @@ g.red-ui-flow-node-selected {
|
||||
text-anchor:start;
|
||||
}
|
||||
|
||||
#red-ui-workspace:not(.red-ui-workspace-locked) {
|
||||
.red-ui-flow-port-hovered {
|
||||
stroke: var(--red-ui-port-selected-color);
|
||||
fill: var(--red-ui-port-selected-color);
|
||||
}
|
||||
.red-ui-flow-port-hovered {
|
||||
stroke: var(--red-ui-port-selected-color);
|
||||
fill: var(--red-ui-port-selected-color);
|
||||
}
|
||||
|
||||
.red-ui-flow-subflow-port {
|
||||
|
@@ -55,7 +55,7 @@
|
||||
.red-ui-palette-search {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: var(--red-ui-secondary-background);
|
||||
background: var(--red-ui-form-input-background);
|
||||
text-align: center;
|
||||
height: 35px;
|
||||
padding: 3px;
|
||||
|
@@ -35,6 +35,7 @@
|
||||
padding: 8px;
|
||||
border-radius: 2px;
|
||||
background: var(--red-ui-popover-background);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.red-ui-popover:after, .red-ui-popover:before {
|
||||
border: solid transparent;
|
||||
|
@@ -108,6 +108,8 @@
|
||||
}
|
||||
.red-ui-search-result-node-label {
|
||||
color: var(--red-ui-secondary-text-color);
|
||||
width: 240px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
> span {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
border-bottom: 1px solid var(--red-ui-secondary-border-color);
|
||||
}
|
||||
@@ -467,9 +468,6 @@ div.red-ui-info-table {
|
||||
.fa-eye {
|
||||
display: none;
|
||||
}
|
||||
.fa-unlock-alt {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.red-ui-info-outline-item-control-reveal,
|
||||
.red-ui-info-outline-item-control-action {
|
||||
@@ -503,25 +501,6 @@ div.red-ui-info-table {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.fa-lock {
|
||||
display: none;
|
||||
}
|
||||
.red-ui-info-outline-item.red-ui-info-outline-item-locked & {
|
||||
.fa-lock {
|
||||
display: inline-block;
|
||||
}
|
||||
.fa-unlock-alt {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
// If the parent is locked, do not show the display/action buttons when
|
||||
// hovering in the outline
|
||||
.red-ui-info-outline-item-locked .red-ui-info-outline-item & {
|
||||
.red-ui-info-outline-item-control-disable,
|
||||
.red-ui-info-outline-item-control-action {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
button {
|
||||
margin-right: 3px
|
||||
}
|
||||
@@ -539,6 +518,8 @@ div.red-ui-info-table {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.red-ui-icons {
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
|
@@ -105,38 +105,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.red-ui-tab:not(.red-ui-workspace-changed) .red-ui-flow-tab-changed {
|
||||
display: none;
|
||||
}
|
||||
.red-ui-tab.red-ui-workspace-changed .red-ui-flow-tab-changed {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
.red-ui-workspace-locked-icon {
|
||||
display: none;
|
||||
}
|
||||
.red-ui-workspace-locked {
|
||||
&.red-ui-tab {
|
||||
// border-top-style: dashed;
|
||||
// border-left-style: dashed;
|
||||
// border-right-style: dashed;
|
||||
|
||||
// a {
|
||||
// font-style: italic;
|
||||
// color: var(--red-ui-tab-text-color-disabled-inactive) !important;
|
||||
// }
|
||||
// &.active a {
|
||||
// font-weight: normal;
|
||||
// color: var(--red-ui-tab-text-color-disabled-active) !important;
|
||||
// }
|
||||
.red-ui-workspace-locked-icon {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#red-ui-navigator-canvas {
|
||||
position: absolute;
|
||||
|
Before Width: | Height: | Size: 66 KiB |
@@ -1,155 +0,0 @@
|
||||
export default {
|
||||
version: "3.0.0",
|
||||
steps: [
|
||||
{
|
||||
titleIcon: "fa fa-map-o",
|
||||
title: {
|
||||
"en-US": "Welcome to Node-RED 3.0!",
|
||||
"ja": "Node-RED 3.0へようこそ!"
|
||||
},
|
||||
description: {
|
||||
"en-US": "<p>Let's take a moment to discover the new features in this release.</p>",
|
||||
"ja": "<p>本リリースの新機能を見つけてみましょう。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Context Menu",
|
||||
"ja": "コンテキストメニュー"
|
||||
},
|
||||
image: '3.0/images/context-menu.png',
|
||||
description: {
|
||||
"en-US": `<p>The editor now has its own context menu when you
|
||||
right-click in the workspace.</p>
|
||||
<p>This makes many of the built-in actions much easier
|
||||
to access.</p>`,
|
||||
"ja": `<p>ワークスペースで右クリックすると、エディタに独自のコンテキストメニューが表示されるようになりました。</p>
|
||||
<p>これによって多くの組み込み動作を、より簡単に利用できます。</p>`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Wire Junctions",
|
||||
"ja": "分岐点をワイヤーに追加"
|
||||
},
|
||||
image: '3.0/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 both the Alt key and the Shift key
|
||||
then click and drag the mouse across the wires.</p>`,
|
||||
"ja": `<p>フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。</p>
|
||||
<p>Altキーとシフトキーを押しながらマウスをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。</p>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Wire Junctions",
|
||||
"ja": "分岐点をワイヤーに追加"
|
||||
},
|
||||
image: '3.0/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>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Debug Path Tooltip",
|
||||
"ja": "デバッグパスのツールチップ"
|
||||
},
|
||||
image: '3.0/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: '3.0/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>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "New wiring actions",
|
||||
"ja": "新しいワイヤー操作"
|
||||
},
|
||||
image: "3.0/images/split-wire-with-links.gif",
|
||||
description: {
|
||||
"en-US": `<p>A new action has been added that will replace a wire with a pair of connected Link nodes:</p>
|
||||
<ul>
|
||||
<li><b><code>Split Wire With Link Nodes</code></b></li>
|
||||
</ul>
|
||||
<p>Actions can be accessed from the Action List in the main menu.</p>`,
|
||||
"ja": `<p>ワイヤーを、接続されたLinkノードのペアに置き換える動作が新たに追加されました:</p>
|
||||
<ul>
|
||||
<li><b><code>ワイヤーをlinkノードで分割</code></b></li>
|
||||
</ul>
|
||||
<p>本アクションは、メインメニュー内の動作一覧から呼び出せます。</p>`,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Default node names",
|
||||
"ja": "標準ノードの名前"
|
||||
},
|
||||
// image: "images/",
|
||||
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>
|
||||
`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Node Updates",
|
||||
"ja": "ノードの更新"
|
||||
},
|
||||
// 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>
|
||||
</ul>`,
|
||||
"ja": `<ul>
|
||||
<li>Debugノードは、受信したメッセージの数をカウントするよう設定できるようになりました。</li>
|
||||
<li>Link Callノードは、メッセージのプロパティによって、呼び出し対象のlinkを動的に指定できるようになりました。</li>
|
||||
<li>HTTP Requestノードは、HTTPヘッダを事前設定できるようになりました。</li>
|
||||
</ul>`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -1,105 +1,137 @@
|
||||
export default {
|
||||
version: "3.1.0-beta.1",
|
||||
version: "3.0.0",
|
||||
steps: [
|
||||
{
|
||||
titleIcon: "fa fa-map-o",
|
||||
title: {
|
||||
"en-US": "Welcome to Node-RED 3.1 Beta 1!",
|
||||
"ja": "Node-RED 3.1 ベータ1へようこそ!"
|
||||
"en-US": "Welcome to Node-RED 3.0!",
|
||||
"ja": "Node-RED 3.0へようこそ!"
|
||||
},
|
||||
description: {
|
||||
"en-US": "<p>This is the first beta release for 3.1.0 and we have a few new features to tell you about.</p>",
|
||||
"ja": "<p>これは3.1.0の最初のベータリリースです。いくつかの新機能について説明します。</p>"
|
||||
"en-US": "<p>Let's take a moment to discover the new features in this release.</p>",
|
||||
"ja": "<p>本リリースの新機能を見つけてみましょう。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Improved Context Menu",
|
||||
"ja": "コンテキストメニューの改善"
|
||||
"en-US": "Context Menu",
|
||||
"ja": "コンテキストメニュー"
|
||||
},
|
||||
image: 'images/context-menu.png',
|
||||
description: {
|
||||
"en-US": `<p>The editor's context menu has been expanded to make lots more of
|
||||
the built-in actions available.</p>
|
||||
<p>Adding nodes, working with groups and plenty
|
||||
of other useful tools are now just a click away.</p>
|
||||
<p>The flow tab bar also has its own context menu to make working
|
||||
with your flows much easier.</p>`,
|
||||
"ja": `<p>より多くの組み込み動作を利用できるように、エディタのコンテキストメニューが拡張されました。</p>
|
||||
<p>ノードの追加、グループの操作、その他の便利なツールをクリックするだけで実行できるようになりました。</p>
|
||||
<p>フローのタブバーには、フローの操作をより簡単にする独自のコンテキストメニューもあります。</p>`
|
||||
"en-US": `<p>The editor now has its own context menu when you
|
||||
right-click in the workspace.</p>
|
||||
<p>This makes many of the built-in actions much easier
|
||||
to access.</p>`,
|
||||
"ja": `<p>ワークスペースで右クリックすると、エディタに独自のコンテキストメニューが表示されるようになりました。</p>
|
||||
<p>これによって多くの組み込み動作を、より簡単に利用できます。</p>`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Hiding Flows",
|
||||
"ja": "フローを非表示"
|
||||
"en-US": "Wire Junctions",
|
||||
"ja": "分岐点をワイヤーに追加"
|
||||
},
|
||||
image: 'images/hiding-flows.png',
|
||||
image: 'images/junction-slice.gif',
|
||||
description: {
|
||||
"en-US": `<p>Hiding flows is now done through the flow context menu.</p>
|
||||
<p>The 'hide' button in previous releases has been removed from the tabs
|
||||
as they were being clicked accidentally too often.</p>`,
|
||||
"ja": `<p>フローを非表示にする機能は、フローのコンテキストメニューから実行するようになりました。</p>
|
||||
<p>これまでのリリースでタブに存在していた「非表示」ボタンは、よく誤ってクリックされていたため、削除されました。</p>`
|
||||
"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 both the Alt key and the Shift key
|
||||
then click and drag the mouse across the wires.</p>`,
|
||||
"ja": `<p>フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。</p>
|
||||
<p>Altキーとシフトキーを押しながらマウスをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。</p>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Locking Flows",
|
||||
"ja": "フローを固定"
|
||||
"en-US": "Wire Junctions",
|
||||
"ja": "分岐点をワイヤーに追加"
|
||||
},
|
||||
image: 'images/locking-flows.png',
|
||||
image: 'images/junction-quick-add.png',
|
||||
description: {
|
||||
"en-US": `<p>Flows can now be locked to prevent accidental changes being made.</p>
|
||||
<p>When locked you cannot modify the nodes in any way.</p>
|
||||
<p>The flow context menu provides the options to lock and unlock flows,
|
||||
as well as in the Info sidebar explorer.</p>`,
|
||||
"ja": `<p>誤ってフローに変更が加えられてしまうのを防ぐために、フローを固定できるようになりました。</p>
|
||||
<p>固定されている時は、ノードを修正することはできません。</p>
|
||||
<p>フローのコンテキストメニューと、情報サイドバーのエクスプローラには、フローの固定や解除をするためのオプションが用意されています。</p>`
|
||||
"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>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Adding Images to node/flow descriptions",
|
||||
"ja": "ノードやフローの説明へ画像を追加"
|
||||
"en-US": "Debug Path Tooltip",
|
||||
"ja": "デバッグパスのツールチップ"
|
||||
},
|
||||
// image: 'images/debug-path-tooltip.png',
|
||||
image: 'images/debug-path-tooltip.png',
|
||||
description: {
|
||||
"en-US": `<p>You can now add images to a node's or flows's description.</p>
|
||||
<p>Simply drag the image into the text editor and it will get added inline.</p>
|
||||
<p>When the description is shown in the Info sidebar, the image will be displayed.</p>`,
|
||||
"ja": `<p>ノードまたはフローの説明に、画像を追加できるようになりました。</p>
|
||||
<p>画像をテキストエディタにドラッグするだけで、行内に埋め込まれます。</p>
|
||||
<p>情報サイドバーの説明を開くと、その画像が表示されます。</p>`
|
||||
"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": "Adding Mermaid Diagrams",
|
||||
"ja": "Mermaidの図を追加"
|
||||
"en-US": "Continuous Search",
|
||||
"ja": "連続した検索"
|
||||
},
|
||||
image: 'images/mermaid.png',
|
||||
image: 'images/continuous-search.png',
|
||||
description: {
|
||||
"en-US": `<p>You can also add <a href="https://github.com/mermaid-js/mermaid">Mermaid</a> diagrams directly into your node or flow descriptions.</p>
|
||||
<p>This gives you much richer options for documenting your flows.</p>`,
|
||||
"ja": `<p>ノードやフローの説明に、<a href="https://github.com/mermaid-js/mermaid">Mermaid</a>の図を直接追加することもできます。</p>
|
||||
<p>これによって、フローを説明する文書作成の選択肢がより多くなります。</p>`
|
||||
"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>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Managing Global Environment Variables",
|
||||
"ja": "グローバル環境変数の管理"
|
||||
"en-US": "New wiring actions",
|
||||
"ja": "新しいワイヤー操作"
|
||||
},
|
||||
image: 'images/global-env-vars.png',
|
||||
image: "images/split-wire-with-links.gif",
|
||||
description: {
|
||||
"en-US": `<p>You can set environment variables that apply to all nodes and flows in the new
|
||||
'Global Environment Variables' section of User Settings.</p>`,
|
||||
"ja": `<p>ユーザ設定に新しく追加された「大域環境変数」のセクションで、全てのノードとフローに適用される環境変数を登録できます。</p>`
|
||||
"en-US": `<p>A new action has been added that will replace a wire with a pair of connected Link nodes:</p>
|
||||
<ul>
|
||||
<li><b><code>Split Wire With Link Nodes</code></b></li>
|
||||
</ul>
|
||||
<p>Actions can be accessed from the Action List in the main menu.</p>`,
|
||||
"ja": `<p>ワイヤーを、接続されたLinkノードのペアに置き換える動作が新たに追加されました:</p>
|
||||
<ul>
|
||||
<li><b><code>ワイヤーをlinkノードで分割</code></b></li>
|
||||
</ul>
|
||||
<p>本アクションは、メインメニュー内の動作一覧から呼び出せます。</p>`,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Default node names",
|
||||
"ja": "標準ノードの名前"
|
||||
},
|
||||
// image: "images/",
|
||||
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>
|
||||
`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Node Updates",
|
||||
@@ -107,9 +139,16 @@ export default {
|
||||
},
|
||||
// image: "images/",
|
||||
description: {
|
||||
"en-US": `<p>The core nodes have received lots of minor fixes, documentation updates and
|
||||
small enhancements. Check the full changelog in the Help sidebar for a full list.</p>`,
|
||||
"ja": `<p>コアノードにマイナーな修正、ドキュメント更新、小規模な拡張が数多く追加されています。全ての一覧は、ヘルプサイドバーの全ての更新履歴を確認してください。</p>`
|
||||
"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>
|
||||
</ul>`,
|
||||
"ja": `<ul>
|
||||
<li>Debugノードは、受信したメッセージの数をカウントするよう設定できるようになりました。</li>
|
||||
<li>Link Callノードは、メッセージのプロパティによって、呼び出し対象のlinkを動的に指定できるようになりました。</li>
|
||||
<li>HTTP Requestノードは、HTTPヘッダを事前設定できるようになりました。</li>
|
||||
</ul>`
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -1,27 +0,0 @@
|
||||
<script type="text/html" data-template-name="global-config">
|
||||
<div class="form-row">
|
||||
<label style="width: 100%"><span data-i18n="global-config.label.open-conf"></span>:</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<button class="red-ui-button" type="button" id="node-input-edit-env-var" data-i18n="editor:env-var.header" style="margin-left: 20px"></button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('global-config',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
name: { value: "" },
|
||||
env: { value: [] },
|
||||
},
|
||||
credentials: {
|
||||
map: { type: "map" }
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$('#node-input-edit-env-var').on('click', function(evt) {
|
||||
RED.actions.invoke('core:show-user-settings', 'envvar')
|
||||
});
|
||||
},
|
||||
hasUsers: false
|
||||
});
|
||||
</script>
|
@@ -1,7 +0,0 @@
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
function GlobalConfigNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
}
|
||||
RED.nodes.registerType("global-config", GlobalConfigNode);
|
||||
}
|
@@ -10,7 +10,6 @@
|
||||
<option value="scale" data-i18n="range.scale.payload"></option>
|
||||
<option value="clamp" data-i18n="range.scale.limit"></option>
|
||||
<option value="roll" data-i18n="range.scale.wrap"></option>
|
||||
<option value="drop" data-i18n="range.scale.drop"></option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
|
@@ -32,15 +32,11 @@ module.exports = function(RED) {
|
||||
if (value !== undefined) {
|
||||
var n = Number(value);
|
||||
if (!isNaN(n)) {
|
||||
if (node.action === "drop") {
|
||||
if (n < node.minin) { done(); return; }
|
||||
if (n > node.maxin) { done(); return; }
|
||||
}
|
||||
if (node.action === "clamp") {
|
||||
if (node.action == "clamp") {
|
||||
if (n < node.minin) { n = node.minin; }
|
||||
if (n > node.maxin) { n = node.maxin; }
|
||||
}
|
||||
if (node.action === "roll") {
|
||||
if (node.action == "roll") {
|
||||
var divisor = node.maxin - node.minin;
|
||||
n = ((n - node.minin) % divisor + divisor) % divisor + node.minin;
|
||||
}
|
||||
|
@@ -201,7 +201,6 @@ module.exports = function(RED) {
|
||||
});
|
||||
node.on("close", function() { clearDelayList(); });
|
||||
}
|
||||
|
||||
else if (node.pauseType === "random") {
|
||||
node.on("input", function(msg, send, done) {
|
||||
var wait = node.randomFirst + (node.diff * Math.random());
|
||||
@@ -227,19 +226,34 @@ module.exports = function(RED) {
|
||||
// The rate limit/queue type modes
|
||||
else if (node.pauseType === "rate") {
|
||||
node.on("input", function(msg, send, done) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (node.intervalID !== -1 ) {
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = -1;
|
||||
}
|
||||
delete node.lastSent;
|
||||
node.buffer = [];
|
||||
node.rate = node.fixedrate;
|
||||
node.status({fill:"blue",shape:"ring",text:0});
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.drop) {
|
||||
var m = RED.util.cloneMessage(msg);
|
||||
delete m.flush;
|
||||
delete m.lifo;
|
||||
if (Object.keys(m).length > 1) {
|
||||
if (node.intervalID !== -1) {
|
||||
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate)) && node.rate !== m.rate) {
|
||||
node.rate = m.rate;
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
|
||||
node.rate = msg.rate;
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||
}
|
||||
var max_msgs = maxKeptMsgsCount(node);
|
||||
if ((max_msgs > 0) && (node.buffer.length >= max_msgs)) {
|
||||
node.buffer = [];
|
||||
node.error(RED._("delay.errors.too-many"), m);
|
||||
node.error(RED._("delay.errors.too-many"), msg);
|
||||
} else if (msg.toFront === true) {
|
||||
node.buffer.unshift({msg: m, send: send, done: done});
|
||||
node.reportDepth();
|
||||
@@ -249,8 +263,8 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate))) {
|
||||
node.rate = m.rate;
|
||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
|
||||
node.rate = msg.rate;
|
||||
}
|
||||
send(m);
|
||||
node.reportDepth();
|
||||
@@ -268,8 +282,6 @@ module.exports = function(RED) {
|
||||
else {
|
||||
while (len > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
delete msgInfo.msg.flush;
|
||||
delete msgInfo.msg.reset;
|
||||
if (Object.keys(msgInfo.msg).length > 1) {
|
||||
node.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
@@ -323,21 +335,6 @@ module.exports = function(RED) {
|
||||
}
|
||||
done();
|
||||
}
|
||||
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (msg.flush === undefined) {
|
||||
if (node.intervalID !== -1 ) {
|
||||
clearInterval(node.intervalID);
|
||||
node.intervalID = -1;
|
||||
}
|
||||
delete node.lastSent;
|
||||
}
|
||||
node.buffer = [];
|
||||
node.rate = node.fixedrate;
|
||||
node.status({fill:"blue",shape:"ring",text:0});
|
||||
done();
|
||||
return;
|
||||
}
|
||||
});
|
||||
node.on("close", function() {
|
||||
clearInterval(node.intervalID);
|
||||
@@ -390,22 +387,6 @@ module.exports = function(RED) {
|
||||
node.buffer.push({msg, send, done}); // if not add to end of queue
|
||||
node.reportDepth();
|
||||
}
|
||||
if (msg.hasOwnProperty("flush")) {
|
||||
var len = node.buffer.length;
|
||||
if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush,len)); }
|
||||
while (len > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
delete msgInfo.msg.flush;
|
||||
delete msgInfo.msg.reset;
|
||||
if (Object.keys(msgInfo.msg).length > 2) {
|
||||
node.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
len = len - 1;
|
||||
}
|
||||
node.status({});
|
||||
done();
|
||||
}
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
while (node.buffer.length > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
@@ -416,6 +397,21 @@ module.exports = function(RED) {
|
||||
node.status({text:"reset"});
|
||||
done();
|
||||
}
|
||||
if (msg.hasOwnProperty("flush")) {
|
||||
var len = node.buffer.length;
|
||||
if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush,len)); }
|
||||
while (len > 0) {
|
||||
const msgInfo = node.buffer.shift();
|
||||
delete msgInfo.msg.flush;
|
||||
if (Object.keys(msgInfo.msg).length > 2) {
|
||||
node.send(msgInfo.msg);
|
||||
msgInfo.done();
|
||||
}
|
||||
len = len - 1;
|
||||
}
|
||||
node.status({});
|
||||
done();
|
||||
}
|
||||
});
|
||||
node.on("close", function() {
|
||||
clearInterval(node.intervalID);
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<select id="node-then-type" style="width:70%;">
|
||||
<option value="block" data-i18n="trigger.wait-reset"></option>
|
||||
<option value="wait" data-i18n="trigger.wait-for"></option>
|
||||
<option id="node-trigger-wait-loop" value="loop" data-i18n="trigger.wait-loop"></option>
|
||||
<option value="loop" data-i18n="trigger.wait-loop"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-type-duration">
|
||||
@@ -181,13 +181,6 @@
|
||||
$("#node-input-op2type").val('str');
|
||||
}
|
||||
|
||||
$("#node-input-op1").on("change", function() {
|
||||
if ($("#node-input-op1type").val() === "nul") {
|
||||
$("#node-trigger-wait-loop").hide();
|
||||
}
|
||||
else { $("#node-trigger-wait-loop").show(); }
|
||||
});
|
||||
|
||||
var optionNothing = {value:"nul",label:this._("trigger.output.nothing"),hasValue:false};
|
||||
var optionPayload = {value:"pay",label:this._("trigger.output.existing"),hasValue:false};
|
||||
var optionOriginalPayload = {value:"pay",label:this._("trigger.output.original"),hasValue:false};
|
||||
|
@@ -35,7 +35,11 @@ module.exports = function(RED) {
|
||||
}
|
||||
else { node.previous = {}; }
|
||||
}
|
||||
var value = RED.util.getMessageProperty(msg,node.property);
|
||||
var value;
|
||||
try {
|
||||
value = RED.util.getMessageProperty(msg,node.property);
|
||||
}
|
||||
catch(e) { }
|
||||
if (value !== undefined) {
|
||||
var t = "_no_topic";
|
||||
if (node.septopics) { t = topic || t; }
|
||||
|
@@ -697,7 +697,8 @@ module.exports = function(RED) {
|
||||
node.options.rejectUnauthorized = (node.verifyservercert == "true" || node.verifyservercert === true);
|
||||
}
|
||||
}
|
||||
|
||||
node.v5 = () => node.options && node.options.protocolVersion == 5
|
||||
node.subscriptionIdentifiersAvailable = () => node.v5() && node.serverProperties && node.serverProperties.subscriptionIdentifiersAvailable
|
||||
n.autoConnect = n.autoConnect === "false" || n.autoConnect === false ? false : true;
|
||||
node.setOptions(n, true);
|
||||
|
||||
@@ -920,7 +921,12 @@ module.exports = function(RED) {
|
||||
};
|
||||
node.subscriptions[topic][ref] = sub;
|
||||
if (node.connected) {
|
||||
const subIdsAvailable = node.subscriptionIdentifiersAvailable()
|
||||
node._clientOn('message',sub.handler);
|
||||
// if the broker doesn't support subscription identifiers (e.g. AWS core), then don't send them
|
||||
if (options.properties && options.properties.subscriptionIdentifier && subIdsAvailable !== true) {
|
||||
delete options.properties.subscriptionIdentifier
|
||||
}
|
||||
node.client.subscribe(topic, options);
|
||||
}
|
||||
};
|
||||
|
@@ -86,7 +86,7 @@ module.exports = function(RED) {
|
||||
this.topic = n.topic;
|
||||
this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/
|
||||
this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
|
||||
this.newline = (n.newline||"").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g,"\t");
|
||||
this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r").replace("\\t","\t");
|
||||
this.base64 = n.base64;
|
||||
this.trim = n.trim || false;
|
||||
this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
|
||||
|
@@ -19,9 +19,9 @@ module.exports = function(RED) {
|
||||
function CSVNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.template = (n.temp || "");
|
||||
this.sep = (n.sep || ',').replace(/\\t/g,"\t").replace(/\\n/g,"\n").replace(/\\r/g,"\r");
|
||||
this.sep = (n.sep || ',').replace("\\t","\t").replace("\\n","\n").replace("\\r","\r");
|
||||
this.quo = '"';
|
||||
this.ret = (n.ret || "\n").replace(/\\n/g,"\n").replace(/\\r/g,"\r");
|
||||
this.ret = (n.ret || "\n").replace("\\n","\n").replace("\\r","\r");
|
||||
this.winflag = (this.ret === "\r\n");
|
||||
this.lineend = "\n";
|
||||
this.multi = n.multi || "one";
|
||||
|
@@ -224,12 +224,7 @@
|
||||
outputs:1,
|
||||
icon: "join.svg",
|
||||
label: function() {
|
||||
var nam = this.name||this._("join.join");
|
||||
if (this.mode === "custom" && !isNaN(Number(this.count))) {
|
||||
nam += " "+this.count;
|
||||
if (this.accumulate === true) { nam+= "+"; }
|
||||
}
|
||||
return nam;
|
||||
return this.name||this._("join.join");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
|
@@ -478,7 +478,7 @@ module.exports = function(RED) {
|
||||
var completeSend = function(partId) {
|
||||
var group = inflight[partId];
|
||||
if (group.timeout) { clearTimeout(group.timeout); }
|
||||
if (node.mode === 'auto' || node.accumulate !== true || group.msg.hasOwnProperty("complete")) { delete inflight[partId]; }
|
||||
if ((node.accumulate !== true) || group.msg.hasOwnProperty("complete")) { delete inflight[partId]; }
|
||||
if (group.type === 'array' && group.arrayLen > 1) {
|
||||
var newArray = [];
|
||||
group.payload.forEach(function(n) {
|
||||
|
@@ -107,14 +107,7 @@
|
||||
outputs:1,
|
||||
icon: "batch.svg",
|
||||
label: function() {
|
||||
var nam = this.name||this._("batch.batch");
|
||||
if (this.mode === "count" && !isNaN(Number(this.count))) {
|
||||
nam += " "+this.count;
|
||||
}
|
||||
if (this.mode === "interval" && !isNaN(Number(this.interval))) {
|
||||
nam += " "+this.interval+"s";
|
||||
}
|
||||
return nam;
|
||||
return this.name||this._("batch.batch");;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
|
@@ -117,7 +117,9 @@ module.exports = function(RED) {
|
||||
}
|
||||
if (typeof data === "boolean") { data = data.toString(); }
|
||||
if (typeof data === "number") { data = data.toString(); }
|
||||
if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
|
||||
var aflg = true;
|
||||
if (msg.hasOwnProperty("parts") && msg.parts.type === "string" && (msg.parts.count === msg.parts.index + 1)) { aflg = false; }
|
||||
if ((node.appendNewline) && (!Buffer.isBuffer(data)) && aflg) { data += os.EOL; }
|
||||
var buf;
|
||||
if (node.encoding === "setbymsg") {
|
||||
buf = encode(data, msg.encoding || "none");
|
||||
@@ -314,7 +316,6 @@ module.exports = function(RED) {
|
||||
});
|
||||
filename = filename || "";
|
||||
var fullFilename = filename;
|
||||
var filePath = "";
|
||||
if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
|
||||
fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
|
||||
}
|
||||
|
@@ -1,3 +0,0 @@
|
||||
<script type="text/html" data-help-name="global-config">
|
||||
<p>A node for holding global configuration of flows.</p>
|
||||
</script>
|
@@ -34,14 +34,11 @@
|
||||
the range specified within the target range.</p>
|
||||
<p><i>Scale and wrap within the target range</i> means that the result will
|
||||
be wrapped within the target range.</p>
|
||||
<p><i>Scale, but drop if outside input range</i> means that the result will
|
||||
be scaled, but any inputs outside of the inout range will be dropped.</p>
|
||||
<p>For example an input 0 - 10 mapped to 0 - 100.</p>
|
||||
<table style="outline-width:#888 solid thin">
|
||||
<tr><th width="80px">mode</th><th width="80px">input</th><th width="80px">output</th></tr>
|
||||
<tr><td><center>scale</center></td><td><center>12</center></td><td><center>120</center></td></tr>
|
||||
<tr><td><center>limit</center></td><td><center>12</center></td><td><center>100</center></td></tr>
|
||||
<tr><td><center>wrap</center></td><td><center>12</center></td><td><center>20</center></td></tr>
|
||||
<tr><td><center>drop</center></td><td><center>12</center></td><td><center><i>(no output)</i></center></td></tr>
|
||||
</table>
|
||||
</script>
|
||||
|
@@ -820,8 +820,7 @@
|
||||
"scale": {
|
||||
"payload": "Scale the message property",
|
||||
"limit": "Scale and limit to the target range",
|
||||
"wrap": "Scale and wrap within the target range",
|
||||
"drop": "Scale, but drop msg if outside input range"
|
||||
"wrap": "Scale and wrap within the target range"
|
||||
},
|
||||
"tip": "Tip: This node ONLY works with numbers.",
|
||||
"errors": {
|
||||
@@ -1131,10 +1130,5 @@
|
||||
"warn": {
|
||||
"nonumber": "no number found in payload"
|
||||
}
|
||||
},
|
||||
"global-config": {
|
||||
"label": {
|
||||
"open-conf": "Open Configuration"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -47,6 +47,5 @@
|
||||
<p>If 'include null values' option is checked, null values will be returned in result, ie. middle value '"1",,3'.</p>
|
||||
<p>The node can accept a multi-part input as long as the <code>parts</code> property is set correctly, for example from a file-in node or split node.</p>
|
||||
<p>If outputting multiple messages they will have their <code>parts</code> property set and form a complete message sequence.</p>
|
||||
<p>If the node is set to only send column headers once, then setting <code>msg.reset</code> to any value will cause the node to resend the headers.</p>
|
||||
<p><b>Note:</b> the column template must be comma separated - even if a different separator is chosen for the data.</p>
|
||||
</script>
|
||||
|
@@ -1,3 +0,0 @@
|
||||
<script type="text/html" data-help-name="global-config">
|
||||
<p>大域的なフローの設定を保持するノード。大域的な環境変数の定義を含みます。</p>
|
||||
</script>p
|
@@ -784,8 +784,8 @@
|
||||
"change": "値の置換",
|
||||
"delete": "値の削除",
|
||||
"move": "値の移動",
|
||||
"toValue": "代入する値",
|
||||
"to": "移動先",
|
||||
"toValue": "対象の値",
|
||||
"to": "対象の値",
|
||||
"search": "検索する文字列",
|
||||
"replace": "置換後の文字列"
|
||||
},
|
||||
@@ -820,8 +820,7 @@
|
||||
"scale": {
|
||||
"payload": "msg.payloadの値を拡大/縮小",
|
||||
"limit": "入力値の範囲外の値を最小値/最大値とし拡大/縮小",
|
||||
"wrap": "入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小",
|
||||
"drop": "値を拡大/縮小(入力範囲外の時はメッセージを削除)"
|
||||
"wrap": "入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小"
|
||||
},
|
||||
"tip": "注釈: 本ノードは、数値のみ扱うことができます。",
|
||||
"errors": {
|
||||
@@ -1131,10 +1130,5 @@
|
||||
"warn": {
|
||||
"nonumber": "ペイロードに数値が含まれていません"
|
||||
}
|
||||
},
|
||||
"global-config": {
|
||||
"label": {
|
||||
"open-conf": "設定を開く"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,5 @@
|
||||
<p>「null値を含む」オプションがチェックされている場合、null値が結果に返されます。つまり「"1",,3」の真ん中の値がnullになります。</p>
|
||||
<p>file-inノードやsplitノードが出力するメッセージの様に、<code>parts</code>プロパティが正しく設定されている場合、メッセージ列を入力として受け付けます。</p>
|
||||
<p>CSVを複数のメッセージに変換して出力する場合、出力がメッセージ列となるよう<code>parts</code>プロパティを設定します。</p>
|
||||
<p>ヘッダを一度だけ送信するよう設定している場合、任意の値を持つ<code>msg.reset</code>を渡すと、再度ヘッダを含めて送信できるようになります。</p>
|
||||
<p><b>注:</b> カンマ以外の区切り文字を設定した場合であっても、「列名」はカンマ区切りとしてください。</p>
|
||||
</script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -15,12 +15,12 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.8.2",
|
||||
"acorn": "8.7.1",
|
||||
"acorn-walk": "8.2.0",
|
||||
"ajv": "8.12.0",
|
||||
"body-parser": "1.20.2",
|
||||
"ajv": "8.11.0",
|
||||
"body-parser": "1.20.0",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"content-type": "1.0.5",
|
||||
"content-type": "1.0.4",
|
||||
"cookie-parser": "1.4.6",
|
||||
"cookie": "0.5.0",
|
||||
"cors": "2.8.5",
|
||||
@@ -28,9 +28,9 @@
|
||||
"denque": "2.1.0",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "10.1.0",
|
||||
"got": "11.8.6",
|
||||
"got": "11.8.5",
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "1.2.0",
|
||||
"hpagent": "1.0.0",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "4.1.0",
|
||||
@@ -40,9 +40,9 @@
|
||||
"mustache": "4.2.0",
|
||||
"node-watch": "0.7.3",
|
||||
"on-headers": "1.0.2",
|
||||
"raw-body": "2.5.2",
|
||||
"tough-cookie": "4.1.2",
|
||||
"uuid": "9.0.0",
|
||||
"raw-body": "2.5.1",
|
||||
"tough-cookie": "4.0.0",
|
||||
"uuid": "8.3.2",
|
||||
"ws": "7.5.6",
|
||||
"xml2js": "0.4.23",
|
||||
"iconv-lite": "0.6.3"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.1.0-beta.1",
|
||||
"@node-red/util": "3.0.2",
|
||||
"clone": "2.1.2",
|
||||
"fs-extra": "10.1.0",
|
||||
"semver": "7.3.8",
|
||||
"tar": "6.1.13",
|
||||
"uglify-js": "3.17.4"
|
||||
"semver": "7.3.7",
|
||||
"tar": "6.1.11",
|
||||
"uglify-js": "3.16.3"
|
||||
}
|
||||
}
|
||||
|
@@ -89,16 +89,10 @@ var api = module.exports = {
|
||||
|
||||
if (!runtime.settings.disableEditor) {
|
||||
safeSettings.context = runtime.nodes.listContextStores();
|
||||
if (runtime.settings.editorTheme) {
|
||||
if (runtime.settings.editorTheme.codeEditor) {
|
||||
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
||||
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "monaco";
|
||||
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
||||
}
|
||||
if (runtime.settings.editorTheme.markdownEditor) {
|
||||
safeSettings.markdownEditor = runtime.settings.editorTheme.markdownEditor || {};
|
||||
safeSettings.markdownEditor.mermaid = safeSettings.markdownEditor.mermaid || { enabled: true };
|
||||
}
|
||||
if (runtime.settings.editorTheme && runtime.settings.editorTheme.codeEditor) {
|
||||
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
||||
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "monaco";
|
||||
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
||||
}
|
||||
safeSettings.libraries = runtime.library.getLibraries();
|
||||
if (util.isArray(runtime.settings.paletteCategories)) {
|
||||
|
@@ -818,6 +818,16 @@ function handlePreRoute(flow, sendEvent, reportError) {
|
||||
})
|
||||
}
|
||||
|
||||
function deliverMessageToDestination(sendEvent) {
|
||||
if (sendEvent?.destination?.node) {
|
||||
try {
|
||||
sendEvent.destination.node.receive(sendEvent.msg);
|
||||
} catch(err) {
|
||||
Log.error(`Error delivering message to node:${sendEvent.destination.node._path} [${sendEvent.destination.node.type}]`)
|
||||
Log.error(err.stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
function handlePreDeliver(flow,sendEvent, reportError) {
|
||||
// preDeliver - the local router has identified the node it is going to send to. At this point, the message has been cloned if needed.
|
||||
hooks.trigger("preDeliver",sendEvent,(err) => {
|
||||
@@ -827,15 +837,10 @@ function handlePreDeliver(flow,sendEvent, reportError) {
|
||||
} else if (err !== false) {
|
||||
if (asyncMessageDelivery) {
|
||||
setImmediate(function() {
|
||||
if (sendEvent.destination.node) {
|
||||
sendEvent.destination.node.receive(sendEvent.msg);
|
||||
}
|
||||
deliverMessageToDestination(sendEvent)
|
||||
})
|
||||
} else {
|
||||
if (sendEvent.destination.node) {
|
||||
sendEvent.destination.node.receive(sendEvent.msg);
|
||||
|
||||
}
|
||||
deliverMessageToDestination(sendEvent)
|
||||
}
|
||||
// postDeliver - the message has been dispatched to be delivered asynchronously (unless the sync delivery flag is set, in which case it would be continue as synchronous delivery)
|
||||
hooks.trigger("postDeliver", sendEvent, function(err) {
|
||||
|
@@ -785,16 +785,6 @@ const flowAPI = {
|
||||
}
|
||||
|
||||
|
||||
function getGlobalConfig() {
|
||||
let gconf = null;
|
||||
eachNode((n) => {
|
||||
if (n.type === "global-config") {
|
||||
gconf = n;
|
||||
}
|
||||
});
|
||||
return gconf;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
|
||||
@@ -808,9 +798,6 @@ module.exports = {
|
||||
get:getNode,
|
||||
eachNode: eachNode,
|
||||
|
||||
|
||||
getGlobalConfig: getGlobalConfig,
|
||||
|
||||
/**
|
||||
* Gets the current flow configuration
|
||||
*/
|
||||
|
@@ -18,9 +18,7 @@ var redUtil = require("@node-red/util").util;
|
||||
var Log = require("@node-red/util").log;
|
||||
var subflowInstanceRE = /^subflow:(.+)$/;
|
||||
var typeRegistry = require("@node-red/registry");
|
||||
const credentials = require("../nodes/credentials");
|
||||
|
||||
let _runtime = null;
|
||||
|
||||
var envVarExcludes = {};
|
||||
|
||||
@@ -201,7 +199,9 @@ function parseConfig(config) {
|
||||
if (subflowDetails) {
|
||||
var subflowType = subflowDetails[1]
|
||||
n.subflow = subflowType;
|
||||
flow.subflows[subflowType].instances.push(n)
|
||||
if (flow.subflows[subflowType]) {
|
||||
flow.subflows[subflowType].instances.push(n)
|
||||
}
|
||||
}
|
||||
if (container) {
|
||||
container.nodes[n.id] = n;
|
||||
@@ -267,55 +267,15 @@ function parseConfig(config) {
|
||||
return flow;
|
||||
}
|
||||
|
||||
function getGlobalEnv(name) {
|
||||
const nodes = _runtime.nodes;
|
||||
if (!nodes) {
|
||||
return null;
|
||||
}
|
||||
const gconf = nodes.getGlobalConfig();
|
||||
const env = gconf ? gconf.env : null;
|
||||
|
||||
if (env) {
|
||||
const cred = (gconf ? credentials.get(gconf.id) : null) || {
|
||||
map: {}
|
||||
};
|
||||
const map = cred.map;
|
||||
|
||||
for (let i = 0; i < env.length; i++) {
|
||||
const item = env[i];
|
||||
if (item.name === name) {
|
||||
if (item.type === "cred") {
|
||||
return {
|
||||
name: name,
|
||||
value: map[name],
|
||||
type: "cred"
|
||||
};
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
_runtime = runtime;
|
||||
envVarExcludes = {};
|
||||
if (runtime.settings.hasOwnProperty('envVarExcludes') && Array.isArray(runtime.settings.envVarExcludes)) {
|
||||
runtime.settings.envVarExcludes.forEach(v => envVarExcludes[v] = true);
|
||||
}
|
||||
},
|
||||
getEnvVar: function(k) {
|
||||
if (!envVarExcludes[k]) {
|
||||
const item = getGlobalEnv(k);
|
||||
if (item) {
|
||||
const val = redUtil.evaluateNodeProperty(item.value, item.type, null, null, null);
|
||||
return val;
|
||||
}
|
||||
return process.env[k];
|
||||
}
|
||||
return undefined;
|
||||
return !envVarExcludes[k]?process.env[k]:undefined
|
||||
},
|
||||
diffNodes: diffNodes,
|
||||
mapEnvVarProperties: mapEnvVarProperties,
|
||||
|
@@ -383,11 +383,6 @@ var api = module.exports = {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (nodeType === "global-config") {
|
||||
if (JSON.stringify(savedCredentials.map) !== JSON.stringify(newCreds.map)) {
|
||||
savedCredentials.map = newCreds.map;
|
||||
dirty = true;
|
||||
}
|
||||
} else {
|
||||
var dashedType = nodeType.replace(/\s+/g, '-');
|
||||
var definition = credentialsDef[dashedType];
|
||||
|
@@ -205,7 +205,6 @@ module.exports = {
|
||||
getNode: flows.get,
|
||||
eachNode: flows.eachNode,
|
||||
getContext: context.get,
|
||||
getGlobalConfig: flows.getGlobalConfig,
|
||||
|
||||
clearContext: context.clear,
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "3.1.0-beta.1",
|
||||
"@node-red/util": "3.1.0-beta.1",
|
||||
"async-mutex": "0.4.0",
|
||||
"@node-red/registry": "3.0.2",
|
||||
"@node-red/util": "3.0.2",
|
||||
"async-mutex": "0.3.2",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.18.2",
|
||||
"express": "4.18.1",
|
||||
"fs-extra": "10.1.0",
|
||||
"json-stringify-safe": "5.0.1"
|
||||
}
|
||||
|
12
packages/node_modules/@node-red/util/lib/util.js
vendored
@@ -696,19 +696,13 @@ function evaluateNodeProperty(value, type, node, msg, callback) {
|
||||
function prepareJSONataExpression(value,node) {
|
||||
var expr = jsonata(value);
|
||||
expr.assign('flowContext', function(val, store) {
|
||||
if (node) {
|
||||
return node.context().flow.get(val, store);
|
||||
}
|
||||
return "";
|
||||
return node.context().flow.get(val, store);
|
||||
});
|
||||
expr.assign('globalContext', function(val, store) {
|
||||
if (node) {
|
||||
return node.context().global.get(val, store);
|
||||
}
|
||||
return "";
|
||||
return node.context().global.get(val, store);
|
||||
});
|
||||
expr.assign('env', function(name) {
|
||||
var val = getSetting(node, name, node ? node._flow : null);
|
||||
var val = getSetting(node, name, node._flow);
|
||||
if (typeof val !== 'undefined') {
|
||||
return val;
|
||||
} else {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -16,11 +16,11 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"fs-extra": "10.1.0",
|
||||
"i18next": "21.10.0",
|
||||
"i18next": "21.8.16",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.6",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"moment": "2.29.4",
|
||||
"moment-timezone": "0.5.41"
|
||||
"moment-timezone": "0.5.34"
|
||||
}
|
||||
}
|
||||
|
8
packages/node_modules/node-red/lib/red.js
vendored
@@ -25,15 +25,9 @@ var api = require("@node-red/editor-api");
|
||||
var server = null;
|
||||
var apiEnabled = false;
|
||||
|
||||
const NODE_MAJOR_VERSION = process.versions.node.split('.')[0];
|
||||
if (NODE_MAJOR_VERSION > 14) {
|
||||
const dns = require('node:dns');
|
||||
dns.setDefaultResultOrder('ipv4first');
|
||||
}
|
||||
|
||||
function checkVersion(userSettings) {
|
||||
var semver = require('semver');
|
||||
if (!semver.satisfies(process.version,">=14.0.0")) {
|
||||
if (!semver.satisfies(process.version,">=8.9.0")) {
|
||||
// TODO: in the future, make this a hard error.
|
||||
// var e = new Error("Unsupported version of Node.js");
|
||||
// e.code = "unsupported_version";
|
||||
|
16
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.1.0-beta.1",
|
||||
"version": "3.0.2",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,20 +31,20 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "3.1.0-beta.1",
|
||||
"@node-red/runtime": "3.1.0-beta.1",
|
||||
"@node-red/util": "3.1.0-beta.1",
|
||||
"@node-red/nodes": "3.1.0-beta.1",
|
||||
"@node-red/editor-api": "3.0.2",
|
||||
"@node-red/runtime": "3.0.2",
|
||||
"@node-red/util": "3.0.2",
|
||||
"@node-red/nodes": "3.0.2",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.18.2",
|
||||
"express": "4.18.1",
|
||||
"fs-extra": "10.1.0",
|
||||
"node-red-admin": "^3.0.0",
|
||||
"nopt": "5.0.0",
|
||||
"semver": "7.3.8"
|
||||
"semver": "7.3.7"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "5.1.0"
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
2
packages/node_modules/node-red/red.js
vendored
@@ -458,7 +458,7 @@ httpsPromise.then(function(startupHttps) {
|
||||
RED.start().then(function() {
|
||||
if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) {
|
||||
server.on('error', function(err) {
|
||||
if (err.errno === "EADDRINUSE") {
|
||||
if (err.code === "EADDRINUSE") {
|
||||
RED.log.error(RED.log._("server.unable-to-listen", {listenpath:getListenPath()}));
|
||||
RED.log.error(RED.log._("server.port-in-use"));
|
||||
} else {
|
||||
|
13
packages/node_modules/node-red/settings.js
vendored
@@ -416,22 +416,13 @@ module.exports = {
|
||||
*/
|
||||
// theme: "vs",
|
||||
/** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc.
|
||||
* for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html
|
||||
* for the full list, see https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneEditorConstructionOptions.html
|
||||
*/
|
||||
//fontSize: 14,
|
||||
//fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace",
|
||||
//fontLigatures: true,
|
||||
}
|
||||
},
|
||||
|
||||
markdownEditor: {
|
||||
mermaid: {
|
||||
/** enable or disable mermaid diagram in markdown document
|
||||
*/
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
/*******************************************************************************
|
||||
|
@@ -854,7 +854,7 @@ describe('inject node', function() {
|
||||
});
|
||||
n1.on("call:error", function(err) {
|
||||
count++;
|
||||
if (count == 2) {
|
||||
if (count == 1) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|