Compare commits
1 Commits
enhance-cs
...
start-proj
Author | SHA1 | Date | |
---|---|---|---|
|
499d22daca |
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
/packages/node_modules/** linguist-generated=false
|
6
.github/ISSUE_TEMPLATE.md
vendored
@@ -8,9 +8,7 @@ If your issue is:
|
||||
- a feature request or suggestion for a change,
|
||||
- or problems with 3rd party (`node-red-contrib-`) nodes
|
||||
|
||||
please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
|
||||
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
|
||||
please use the [mailing list](https://groups.google.com/forum/#!forum/node-red), [slack team](https://nodered.org/slack) or ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
|
||||
|
||||
That way the whole Node-RED user community can help, rather than rely on the core development team.
|
||||
|
||||
@@ -28,7 +26,7 @@ To help us understand the issue, please fill-in as much of the following informa
|
||||
### Please tell us about your environment:
|
||||
|
||||
- [ ] Node-RED version:
|
||||
- [ ] Node.js version:
|
||||
- [ ] node.js version:
|
||||
- [ ] npm version:
|
||||
- [ ] Platform/OS:
|
||||
- [ ] Browser:
|
||||
|
39
.github/ISSUE_TEMPLATE/--bug_report.md
vendored
@@ -1,39 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Reproducible software issues in the core of Node-RED
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
This issue tracker is for problems with the Node-RED runtime, the editor or the core nodes.
|
||||
|
||||
If your issue is:
|
||||
- a general 'how-to' type question,
|
||||
- a feature request or suggestion for a change,
|
||||
- or problems with 3rd party (`node-red-contrib-`) nodes
|
||||
|
||||
please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
|
||||
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
|
||||
|
||||
That way the whole Node-RED user community can help, rather than rely on the core development team.
|
||||
|
||||
To help us understand the issue, please fill-in as much of the following information as you can:
|
||||
-->
|
||||
|
||||
### What are the steps to reproduce?
|
||||
|
||||
### What happens?
|
||||
|
||||
### What do you expect to happen?
|
||||
|
||||
### Please tell us about your environment:
|
||||
|
||||
- [ ] Node-RED version:
|
||||
- [ ] Node.js version:
|
||||
- [ ] npm version:
|
||||
- [ ] Platform/OS:
|
||||
- [ ] Browser:
|
17
.github/ISSUE_TEMPLATE/-anything-else.md
vendored
@@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Anything Else
|
||||
about: Something that is not a bug report
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please DO NOT raise an issue.
|
||||
|
||||
We DO NOT use the issue tracker for general support or feature requests. Only bug reports should be raised here using the 'Bug report' template.
|
||||
|
||||
For general support, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack). You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
|
||||
That way the whole Node-RED user community can help, rather than rely on the core development team.
|
||||
|
||||
For feature requests, please use the Node-RED Forum](https://discourse.nodered.org). Many ideas have already been discussed there and you should search that for your request before starting a new discussion.
|
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -16,7 +16,7 @@ Put an `x` in the boxes that apply
|
||||
<!--
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, it **may well get rejected** if it hasn't been discussed on
|
||||
the [forum](https://discourse.nodered.org) or
|
||||
the [mailing list](https://groups.google.com/forum/#!forum/node-red) or
|
||||
[slack team](https://nodered.org/slack) first.
|
||||
|
||||
-->
|
||||
@@ -29,6 +29,6 @@ the [forum](https://discourse.nodered.org) or
|
||||
<!-- Put an `x` in the boxes that apply -->
|
||||
|
||||
- [ ] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team.
|
||||
- [ ] For non-bugfix PRs, I have discussed this change on the mailing list/slack team.
|
||||
- [ ] I have run `grunt` to verify the unit tests pass
|
||||
- [ ] I have added suitable unit tests to cover the new/changed functionality
|
||||
|
6
.gitignore
vendored
@@ -17,9 +17,3 @@ node_modules
|
||||
public
|
||||
locales/zz-ZZ
|
||||
nodes/core/locales/zz-ZZ
|
||||
!packages/node_modules
|
||||
packages/node_modules/@node-red/editor-client/public
|
||||
!test/**/node_modules
|
||||
docs
|
||||
!packages/node_modules/**/docs
|
||||
.vscode
|
@@ -1,4 +1,5 @@
|
||||
/Gruntfile.js
|
||||
/.git/*
|
||||
/lib/*
|
||||
*.backup
|
||||
/public/*
|
||||
|
7
.npmignore
Normal file
@@ -0,0 +1,7 @@
|
||||
.settings
|
||||
.jshintignore
|
||||
.jshintrc
|
||||
.project
|
||||
.tern-project
|
||||
.travis.yml
|
||||
.git
|
27
.travis.yml
@@ -1,11 +1,20 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
matrix:
|
||||
include:
|
||||
- node_js: "12"
|
||||
- node_js: "10"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
|
||||
before_script:
|
||||
- npm install -g istanbul coveralls
|
||||
- node_js: "8"
|
||||
env:
|
||||
- CXX="g++-4.8"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
- gcc-4.8
|
||||
node_js:
|
||||
- "8"
|
||||
- "6"
|
||||
- "4"
|
||||
script:
|
||||
- istanbul cover ./node_modules/.bin/grunt --report lcovonly && istanbul report text && ( cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js || true ) && rm -rf coverage
|
||||
before_script:
|
||||
- npm install -g istanbul
|
||||
- npm install coveralls
|
||||
|
15
API.md
@@ -1,15 +0,0 @@
|
||||
Node-RED Modules
|
||||
---
|
||||
|
||||
Node-RED provides a set of node modules that implement different parts of the
|
||||
application.
|
||||
|
||||
Module | Description
|
||||
-------|-------
|
||||
[node-red](node-red.html) | the main module that pulls together all of the internal modules and provides the executable version of Node-RED
|
||||
[@node-red/editor-api](@node-red_editor-api.html) | an Express application that serves the Node-RED editor and provides the Admin HTTP API
|
||||
[@node-red/runtime](@node-red_runtime.html) | the core runtime of Node-RED
|
||||
[@node-red/util](@node-red_util.html) | common utilities for the Node-RED runtime and editor modules
|
||||
@node-red/registry | the internal node registry
|
||||
@node-red/nodes | the default set of core nodes
|
||||
@node-red/editor-client | the client-side resources of the Node-RED editor application
|
1071
CHANGELOG.md
@@ -26,17 +26,17 @@ relevant nodes, press Ctrl-E and copy the flow data from the Export dialog.
|
||||
At a minimum, please include:
|
||||
|
||||
- Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly.
|
||||
- Version of Node.js - what does `node -v` say?
|
||||
- Version of node.js - what does `node -v` say?
|
||||
|
||||
## Feature requests
|
||||
|
||||
For feature requests, please raise them on the [forum](https://discourse.nodered.org).
|
||||
For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red).
|
||||
|
||||
## Pull-Requests
|
||||
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, it may well get rejected if you haven't discussed it on
|
||||
the [forum](https://discourse.nodered.org) first.
|
||||
the [mailing list](https://groups.google.com/forum/#!forum/node-red) first.
|
||||
|
||||
All contributors need to sign the JS Foundation's Contributor License Agreement.
|
||||
It is an online process and quick to do. You can read the details of the agreement
|
||||
|
464
Gruntfile.js
@@ -15,8 +15,6 @@
|
||||
**/
|
||||
|
||||
var path = require("path");
|
||||
var fs = require("fs-extra");
|
||||
var sass = require("node-sass");
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
@@ -26,14 +24,6 @@ module.exports = function(grunt) {
|
||||
nodemonArgs.push(flowFile);
|
||||
}
|
||||
|
||||
var browserstack = grunt.option('browserstack');
|
||||
if (browserstack) {
|
||||
process.env.BROWSERSTACK = true;
|
||||
}
|
||||
var nonHeadless = grunt.option('non-headless');
|
||||
if (nonHeadless) {
|
||||
process.env.NODE_RED_NON_HEADLESS = true;
|
||||
}
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
paths: {
|
||||
@@ -48,7 +38,7 @@ module.exports = function(grunt) {
|
||||
reporter: 'spec'
|
||||
},
|
||||
all: { src: ['test/**/*_spec.js'] },
|
||||
core: { src: ["test/_spec.js","test/unit/**/*_spec.js"]},
|
||||
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
webdriver: {
|
||||
@@ -63,11 +53,10 @@ module.exports = function(grunt) {
|
||||
ignoreLeaks: false,
|
||||
ui: 'bdd',
|
||||
reportFormats: ['lcov','html'],
|
||||
print: 'both',
|
||||
istanbulOptions: ['--no-default-excludes', '-i','**/packages/node_modules/**']
|
||||
print: 'both'
|
||||
},
|
||||
all: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js","test/nodes/**/*_spec.js"] },
|
||||
core: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js"]},
|
||||
all: { src: ['test/**/*_spec.js'] },
|
||||
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
jshint: {
|
||||
@@ -84,20 +73,22 @@ module.exports = function(grunt) {
|
||||
//"loopfunc": true, // allow functions to be defined in loops
|
||||
//"sub": true // don't warn that foo['bar'] should be written as foo.bar
|
||||
},
|
||||
// all: [
|
||||
// 'Gruntfile.js',
|
||||
// 'red.js',
|
||||
// 'packages/**/*.js'
|
||||
// ],
|
||||
// core: {
|
||||
// files: {
|
||||
// src: [
|
||||
// 'Gruntfile.js',
|
||||
// 'red.js',
|
||||
// 'packages/**/*.js',
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
all: [
|
||||
'Gruntfile.js',
|
||||
'red.js',
|
||||
'red/**/*.js',
|
||||
'nodes/core/*/*.js',
|
||||
'editor/js/**/*.js'
|
||||
],
|
||||
core: {
|
||||
files: {
|
||||
src: [
|
||||
'Gruntfile.js',
|
||||
'red.js',
|
||||
'red/**/*.js'
|
||||
]
|
||||
}
|
||||
},
|
||||
nodes: {
|
||||
files: {
|
||||
src: [ 'nodes/core/*/*.js' ]
|
||||
@@ -105,7 +96,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
editor: {
|
||||
files: {
|
||||
src: [ 'packages/node_modules/@node-red/editor-client/src/js/**/*.js' ]
|
||||
src: [ 'editor/js/**/*.js' ]
|
||||
}
|
||||
},
|
||||
tests: {
|
||||
@@ -125,92 +116,78 @@ module.exports = function(grunt) {
|
||||
src: [
|
||||
// Ensure editor source files are concatenated in
|
||||
// the right order
|
||||
"packages/node_modules/@node-red/editor-client/src/js/jquery-addons.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/red.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/events.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/i18n.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/settings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/user.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/comms.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/bidi.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/format.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/state.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/nodes.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/validators.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",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/searchBox.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.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",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/sidebar.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tray.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/notifications.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/search.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/group.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js"
|
||||
"editor/js/red.js",
|
||||
"editor/js/events.js",
|
||||
"editor/js/i18n.js",
|
||||
"editor/js/settings.js",
|
||||
"editor/js/user.js",
|
||||
"editor/js/comms.js",
|
||||
"editor/js/text/bidi.js",
|
||||
"editor/js/text/format.js",
|
||||
"editor/js/ui/state.js",
|
||||
"editor/js/nodes.js",
|
||||
"editor/js/history.js",
|
||||
"editor/js/validators.js",
|
||||
"editor/js/ui/utils.js",
|
||||
"editor/js/ui/common/editableList.js",
|
||||
"editor/js/ui/common/checkboxSet.js",
|
||||
"editor/js/ui/common/menu.js",
|
||||
"editor/js/ui/common/panels.js",
|
||||
"editor/js/ui/common/popover.js",
|
||||
"editor/js/ui/common/searchBox.js",
|
||||
"editor/js/ui/common/tabs.js",
|
||||
"editor/js/ui/common/stack.js",
|
||||
"editor/js/ui/common/typedInput.js",
|
||||
"editor/js/ui/actions.js",
|
||||
"editor/js/ui/deploy.js",
|
||||
"editor/js/ui/diff.js",
|
||||
"editor/js/ui/keyboard.js",
|
||||
"editor/js/ui/workspaces.js",
|
||||
"editor/js/ui/view.js",
|
||||
"editor/js/ui/sidebar.js",
|
||||
"editor/js/ui/palette.js",
|
||||
"editor/js/ui/tab-info.js",
|
||||
"editor/js/ui/tab-config.js",
|
||||
"editor/js/ui/palette-editor.js",
|
||||
"editor/js/ui/editor.js",
|
||||
"editor/js/ui/tray.js",
|
||||
"editor/js/ui/clipboard.js",
|
||||
"editor/js/ui/library.js",
|
||||
"editor/js/ui/notifications.js",
|
||||
"editor/js/ui/search.js",
|
||||
"editor/js/ui/typeSearch.js",
|
||||
"editor/js/ui/subflow.js",
|
||||
"editor/js/ui/userSettings.js",
|
||||
"editor/js/ui/projects/projects.js",
|
||||
"editor/js/ui/projects/projectSettings.js",
|
||||
"editor/js/ui/projects/projectUserSettings.js",
|
||||
"editor/js/ui/projects/tab-versionControl.js",
|
||||
"editor/js/ui/touch/radialMenu.js"
|
||||
],
|
||||
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
|
||||
dest: "public/red/red.js"
|
||||
},
|
||||
vendor: {
|
||||
files: {
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.js": [
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-3.4.1.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.0.1.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
|
||||
"node_modules/marked/marked.min.js",
|
||||
"node_modules/dompurify/dist/purify.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js",
|
||||
"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",
|
||||
"public/vendor/vendor.js": [
|
||||
"editor/vendor/jquery/js/jquery-1.11.3.min.js",
|
||||
"editor/vendor/bootstrap/js/bootstrap.min.js",
|
||||
"editor/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js",
|
||||
"editor/vendor/jquery/js/jquery.ui.touch-punch.min.js",
|
||||
"editor/vendor/marked/marked.min.js",
|
||||
"editor/vendor/d3/d3.v3.min.js",
|
||||
"editor/vendor/i18next/i18next.min.js"
|
||||
],
|
||||
// "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
|
||||
// // TODO: resolve relative resource paths in
|
||||
// // bootstrap/FA/jquery
|
||||
// ],
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
|
||||
"public/vendor/vendor.css": [
|
||||
// TODO: resolve relative resource paths in
|
||||
// bootstrap/FA/jquery
|
||||
],
|
||||
"public/vendor/jsonata/jsonata.min.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
|
||||
"editor/vendor/jsonata/formatter.js"
|
||||
],
|
||||
"public/vendor/ace/worker-jsonata.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"editor/vendor/jsonata/worker-jsonata.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -218,60 +195,63 @@ module.exports = function(grunt) {
|
||||
uglify: {
|
||||
build: {
|
||||
files: {
|
||||
'packages/node_modules/@node-red/editor-client/public/red/red.min.js': 'packages/node_modules/@node-red/editor-client/public/red/red.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/red/main.min.js': 'packages/node_modules/@node-red/editor-client/public/red/main.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/vendor/ace/mode-jsonata.js': 'packages/node_modules/@node-red/editor-client/src/vendor/jsonata/mode-jsonata.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/vendor/ace/snippets/jsonata.js': 'packages/node_modules/@node-red/editor-client/src/vendor/jsonata/snippets-jsonata.js'
|
||||
'public/red/red.min.js': 'public/red/red.js',
|
||||
'public/red/main.min.js': 'public/red/main.js',
|
||||
'public/vendor/ace/mode-jsonata.js': 'editor/vendor/jsonata/mode-jsonata.js',
|
||||
'public/vendor/ace/snippets/jsonata.js': 'editor/vendor/jsonata/snippets-jsonata.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
sass: {
|
||||
build: {
|
||||
options: {
|
||||
implementation: sass,
|
||||
outputStyle: 'compressed'
|
||||
},
|
||||
files: [{
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/style.min.css',
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/sass/style.scss'
|
||||
dest: 'public/red/style.min.css',
|
||||
src: 'editor/sass/style.scss'
|
||||
},
|
||||
{
|
||||
dest: 'public/vendor/bootstrap/css/bootstrap.min.css',
|
||||
src: 'editor/vendor/bootstrap/css/bootstrap.css'
|
||||
}]
|
||||
}
|
||||
},
|
||||
jsonlint: {
|
||||
messages: {
|
||||
src: [
|
||||
'packages/node_modules/@node-red/nodes/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/editor-client/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/runtime/locales/**/*.json'
|
||||
'nodes/core/locales/en-US/messages.json',
|
||||
'red/api/locales/en-US/editor.json',
|
||||
'red/runtime/locales/en-US/runtime.json'
|
||||
]
|
||||
},
|
||||
keymaps: {
|
||||
src: [
|
||||
'packages/node_modules/@node-red/editor-client/src/js/keymap.json'
|
||||
'editor/js/keymap.json'
|
||||
]
|
||||
}
|
||||
},
|
||||
attachCopyright: {
|
||||
js: {
|
||||
src: [
|
||||
'packages/node_modules/@node-red/editor-client/public/red/red.min.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/red/main.min.js'
|
||||
'public/red/red.min.js',
|
||||
'public/red/main.min.js'
|
||||
]
|
||||
},
|
||||
css: {
|
||||
src: [
|
||||
'packages/node_modules/@node-red/editor-client/public/red/style.min.css'
|
||||
'public/red/style.min.css'
|
||||
]
|
||||
}
|
||||
},
|
||||
clean: {
|
||||
build: {
|
||||
src: [
|
||||
"packages/node_modules/@node-red/editor-client/public/red",
|
||||
"packages/node_modules/@node-red/editor-client/public/index.html",
|
||||
"packages/node_modules/@node-red/editor-client/public/favicon.ico",
|
||||
"packages/node_modules/@node-red/editor-client/public/icons",
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor"
|
||||
"public/red",
|
||||
"public/index.html",
|
||||
"public/favicon.ico",
|
||||
"public/icons",
|
||||
"public/vendor"
|
||||
]
|
||||
},
|
||||
release: {
|
||||
@@ -283,27 +263,27 @@ module.exports = function(grunt) {
|
||||
watch: {
|
||||
js: {
|
||||
files: [
|
||||
'packages/node_modules/@node-red/editor-client/src/js/**/*.js'
|
||||
'editor/js/**/*.js'
|
||||
],
|
||||
tasks: ['copy:build','concat',/*'uglify',*/ 'attachCopyright:js']
|
||||
tasks: ['copy:build','concat','uglify','attachCopyright:js']
|
||||
},
|
||||
sass: {
|
||||
files: [
|
||||
'packages/node_modules/@node-red/editor-client/src/sass/**/*.scss'
|
||||
'editor/sass/**/*.scss'
|
||||
],
|
||||
tasks: ['sass','attachCopyright:css']
|
||||
},
|
||||
json: {
|
||||
files: [
|
||||
'packages/node_modules/@node-red/nodes/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/editor-client/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/runtime/locales/**/*.json'
|
||||
'nodes/core/locales/en-US/messages.json',
|
||||
'red/api/locales/en-US/editor.json',
|
||||
'red/runtime/locales/en-US/runtime.json'
|
||||
],
|
||||
tasks: ['jsonlint:messages']
|
||||
},
|
||||
keymaps: {
|
||||
files: [
|
||||
'packages/node_modules/@node-red/editor-client/src/js/keymap.json'
|
||||
'editor/js/keymap.json'
|
||||
],
|
||||
tasks: ['jsonlint:keymaps','copy:build']
|
||||
},
|
||||
@@ -318,13 +298,12 @@ module.exports = function(grunt) {
|
||||
nodemon: {
|
||||
/* uses .nodemonignore */
|
||||
dev: {
|
||||
script: 'packages/node_modules/node-red/red.js',
|
||||
script: 'red.js',
|
||||
options: {
|
||||
args: nodemonArgs,
|
||||
ext: 'js,html,json',
|
||||
watch: [
|
||||
'packages/node_modules',
|
||||
'!packages/node_modules/@node-red/editor-client'
|
||||
'red','nodes'
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -343,56 +322,69 @@ module.exports = function(grunt) {
|
||||
build: {
|
||||
files:[
|
||||
{
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/js/main.js',
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/main.js'
|
||||
src: 'editor/js/main.js',
|
||||
dest: 'public/red/main.js'
|
||||
},
|
||||
{
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/js/keymap.json',
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/keymap.json'
|
||||
src: 'editor/js/keymap.json',
|
||||
dest: 'public/red/keymap.json'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/images',
|
||||
cwd: 'editor/images',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/images/'
|
||||
dest: 'public/red/images/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/vendor',
|
||||
cwd: 'editor/vendor',
|
||||
src: [
|
||||
'ace/**',
|
||||
'jquery/css/base/**',
|
||||
//'bootstrap/css/**',
|
||||
'bootstrap/img/**',
|
||||
'jquery/css/**',
|
||||
'font-awesome/**'
|
||||
],
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/'
|
||||
dest: 'public/vendor/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/icons',
|
||||
cwd: 'editor/icons',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/icons/'
|
||||
dest: 'public/icons/'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
src: ['packages/node_modules/@node-red/editor-client/src/index.html','packages/node_modules/@node-red/editor-client/src/favicon.ico'],
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/',
|
||||
src: ['editor/index.html','editor/favicon.ico'],
|
||||
dest: 'public/',
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
src: 'CHANGELOG.md',
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/about'
|
||||
},
|
||||
{
|
||||
src: 'CHANGELOG.md',
|
||||
dest: 'packages/node_modules/node-red/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/ace/bin/',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/'
|
||||
dest: 'public/red/about'
|
||||
}
|
||||
]
|
||||
},
|
||||
release: {
|
||||
files: [{
|
||||
mode: true,
|
||||
expand: true,
|
||||
src: [
|
||||
'*.md',
|
||||
'LICENSE',
|
||||
'package.json',
|
||||
'settings.js',
|
||||
'red.js',
|
||||
'lib/.gitignore',
|
||||
'nodes/*.demo',
|
||||
'nodes/core/**',
|
||||
'red/**',
|
||||
'public/**',
|
||||
'editor/templates/**',
|
||||
'bin/**'
|
||||
],
|
||||
dest: path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>')
|
||||
}]
|
||||
}
|
||||
},
|
||||
chmod: {
|
||||
@@ -401,92 +393,19 @@ module.exports = function(grunt) {
|
||||
},
|
||||
release: {
|
||||
src: [
|
||||
"packages/node_modules/@node-red/nodes/core/hardware/nrgpio",
|
||||
"packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/node-red-*sh"
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*'),
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/red/runtime/storage/localfilesystem/projects/git/node-red-*sh')
|
||||
]
|
||||
}
|
||||
},
|
||||
'npm-command': {
|
||||
options: {
|
||||
cmd: "pack",
|
||||
cwd: "<%= paths.dist %>/modules"
|
||||
},
|
||||
'node-red': { options: { args: [__dirname+'/packages/node_modules/node-red'] } },
|
||||
'@node-red/editor-api': { options: { args: [__dirname+'/packages/node_modules/@node-red/editor-api'] } },
|
||||
'@node-red/editor-client': { options: { args: [__dirname+'/packages/node_modules/@node-red/editor-client'] } },
|
||||
'@node-red/nodes': { options: { args: [__dirname+'/packages/node_modules/@node-red/nodes'] } },
|
||||
'@node-red/registry': { options: { args: [__dirname+'/packages/node_modules/@node-red/registry'] } },
|
||||
'@node-red/runtime': { options: { args: [__dirname+'/packages/node_modules/@node-red/runtime'] } },
|
||||
'@node-red/util': { options: { args: [__dirname+'/packages/node_modules/@node-red/util'] } }
|
||||
|
||||
|
||||
},
|
||||
mkdir: {
|
||||
release: {
|
||||
options: {
|
||||
create: ['<%= paths.dist %>/modules']
|
||||
},
|
||||
},
|
||||
},
|
||||
compress: {
|
||||
release: {
|
||||
options: {
|
||||
archive: '<%= paths.dist %>/node-red-<%= pkg.version %>.zip'
|
||||
},
|
||||
expand: true,
|
||||
cwd: 'packages/node_modules/',
|
||||
src: [
|
||||
'**',
|
||||
'!@node-red/editor-client/src/**'
|
||||
]
|
||||
}
|
||||
},
|
||||
jsdoc : {
|
||||
modules: {
|
||||
src: [
|
||||
'API.md',
|
||||
'packages/node_modules/node-red/lib/red.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/index.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/api/*.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/events.js',
|
||||
'packages/node_modules/@node-red/util/**/*.js',
|
||||
'packages/node_modules/@node-red/editor-api/lib/index.js',
|
||||
'packages/node_modules/@node-red/editor-api/lib/auth/index.js'
|
||||
],
|
||||
options: {
|
||||
destination: 'docs',
|
||||
configure: './jsdoc.json'
|
||||
}
|
||||
},
|
||||
_editor: {
|
||||
src: [
|
||||
'packages/node_modules/@node-red/editor-client/src/js'
|
||||
],
|
||||
options: {
|
||||
destination: 'packages/node_modules/@node-red/editor-client/docs',
|
||||
configure: './jsdoc.json'
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
jsdoc2md: {
|
||||
runtimeAPI: {
|
||||
options: {
|
||||
separators: true
|
||||
},
|
||||
src: [
|
||||
'packages/node_modules/@node-red/runtime/lib/index.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/api/*.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/events.js'
|
||||
],
|
||||
dest: 'packages/node_modules/@node-red/runtime/docs/api.md'
|
||||
},
|
||||
nodeREDUtil: {
|
||||
options: {
|
||||
separators: true
|
||||
},
|
||||
src: 'packages/node_modules/@node-red/util/**/*.js',
|
||||
dest: 'packages/node_modules/@node-red/util/docs/api.md'
|
||||
cwd: '<%= paths.dist %>/',
|
||||
src: ['node-red-<%= pkg.version %>/**']
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -505,13 +424,7 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-chmod');
|
||||
grunt.loadNpmTasks('grunt-jsonlint');
|
||||
grunt.loadNpmTasks('grunt-mocha-istanbul');
|
||||
if (fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
|
||||
grunt.loadNpmTasks('grunt-webdriver');
|
||||
}
|
||||
grunt.loadNpmTasks('grunt-jsdoc');
|
||||
grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
|
||||
grunt.loadNpmTasks('grunt-npm-command');
|
||||
grunt.loadNpmTasks('grunt-mkdir');
|
||||
grunt.loadNpmTasks('grunt-webdriver');
|
||||
|
||||
grunt.registerMultiTask('attachCopyright', function() {
|
||||
var files = this.data.src;
|
||||
@@ -553,38 +466,6 @@ module.exports = function(grunt) {
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('verifyPackageDependencies', function() {
|
||||
var done = this.async();
|
||||
var verifyDependencies = require("./scripts/verify-package-dependencies.js");
|
||||
verifyDependencies().then(function(failures) {
|
||||
if (failures.length > 0) {
|
||||
failures.forEach(f => grunt.log.error(f));
|
||||
grunt.fail.fatal("Failed to verify package dependencies");
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
grunt.registerTask('verifyUiTestDependencies', function() {
|
||||
if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
|
||||
grunt.fail.fatal('You need to install the UI test dependencies first.\nUse the script in "scripts/install-ui-test-dependencies.sh"');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
grunt.registerTask('generatePublishScript',
|
||||
'Generates a script to publish build output to npm',
|
||||
function () {
|
||||
const done = this.async();
|
||||
const generatePublishScript = require("./scripts/generate-publish-script.js");
|
||||
generatePublishScript().then(function(output) {
|
||||
grunt.log.writeln(output);
|
||||
|
||||
const filePath = path.join(grunt.config.get('paths.dist'),"modules","publish.sh");
|
||||
grunt.file.write(filePath,output);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
grunt.registerTask('setDevEnv',
|
||||
'Sets NODE_ENV=development so non-minified assets are used',
|
||||
function () {
|
||||
@@ -593,7 +474,7 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('default',
|
||||
'Builds editor content then runs code style checks and unit tests on all components',
|
||||
['build','verifyPackageDependencies','jshint:editor','mocha_istanbul:all']);
|
||||
['build','test-core','test-editor','test-nodes']);
|
||||
|
||||
grunt.registerTask('test-core',
|
||||
'Runs code style check and unit tests on core runtime code',
|
||||
@@ -603,15 +484,9 @@ module.exports = function(grunt) {
|
||||
'Runs code style check on editor code',
|
||||
['jshint:editor']);
|
||||
|
||||
if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
|
||||
grunt.registerTask('test-ui',
|
||||
'Builds editor content then runs unit tests on editor ui',
|
||||
['verifyUiTestDependencies']);
|
||||
} else {
|
||||
grunt.registerTask('test-ui',
|
||||
'Builds editor content then runs unit tests on editor ui',
|
||||
['verifyUiTestDependencies','build','jshint:editor','webdriver:all']);
|
||||
}
|
||||
grunt.registerTask('test-ui',
|
||||
'Builds editor content then runs unit tests on editor ui',
|
||||
['build','jshint:editor','webdriver:all']);
|
||||
|
||||
grunt.registerTask('test-nodes',
|
||||
'Runs unit tests on core nodes',
|
||||
@@ -627,18 +502,9 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('release',
|
||||
'Create distribution zip file',
|
||||
['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules','generatePublishScript']);
|
||||
|
||||
grunt.registerTask('pack-modules',
|
||||
'Create module pack files for release',
|
||||
['mkdir:release','npm-command']);
|
||||
|
||||
['build','clean:release','copy:release','chmod:release','compress:release']);
|
||||
|
||||
grunt.registerTask('coverage',
|
||||
'Run Istanbul code test coverage task',
|
||||
['build','mocha_istanbul:all']);
|
||||
|
||||
grunt.registerTask('docs',
|
||||
'Generates API documentation',
|
||||
['jsdoc']);
|
||||
};
|
||||
|
16
README.md
@@ -2,12 +2,12 @@
|
||||
|
||||
http://nodered.org
|
||||
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](https://coveralls.io/r/node-red/node-red?branch=master)
|
||||
|
||||
Low-code programming for event-driven applications.
|
||||
A visual tool for wiring the Internet of Things.
|
||||
|
||||

|
||||

|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -22,7 +22,8 @@ started.
|
||||
|
||||
More documentation can be found [here](http://nodered.org/docs).
|
||||
|
||||
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
For further help, or general discussion, please use the
|
||||
[mailing list](https://groups.google.com/forum/#!forum/node-red).
|
||||
|
||||
## Developers
|
||||
|
||||
@@ -44,6 +45,9 @@ If you want to run the latest code from git, here's how to get started:
|
||||
4. Run
|
||||
|
||||
npm start
|
||||
or
|
||||
|
||||
node red.js
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -56,7 +60,7 @@ This project adheres to the [Contributor Covenant 1.4](http://contributor-covena
|
||||
|
||||
## Authors
|
||||
|
||||
Node-RED is a project of the [OpenJS Foundation](https://openjsf.org).
|
||||
Node-RED is a project of the [JS Foundation](http://js.foundation).
|
||||
|
||||
It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-technology/).
|
||||
|
||||
@@ -67,4 +71,4 @@ It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-t
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Copyright JS Foundation and other contributors, https://openjsf.org under [the Apache 2.0 license](LICENSE).
|
||||
Copyright JS Foundation and other contributors, http://js.foundation under [the Apache 2.0 license](LICENSE).
|
||||
|
13
SECURITY.md
@@ -1,13 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.0.0 | :white_check_mark: |
|
||||
| 0.20.x | :white_check_mark: |
|
||||
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report any potential security issues to `team@nodered.org`. This will notify the core project team who will respond accordingly.
|
@@ -31,7 +31,7 @@ done
|
||||
# Find the real location of this script
|
||||
CURRENT_PATH=`pwd`
|
||||
SCRIPT_PATH="${BASH_SOURCE[0]}";
|
||||
while [ -h "${SCRIPT_PATH}" ]; do
|
||||
while([ -h "${SCRIPT_PATH}" ]); do
|
||||
cd "`dirname "${SCRIPT_PATH}"`"
|
||||
SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")";
|
||||
done
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
BIN
editor/icons/alert.png
Normal file
After Width: | Height: | Size: 308 B |
Before Width: | Height: | Size: 603 B After Width: | Height: | Size: 603 B |
Before Width: | Height: | Size: 393 B After Width: | Height: | Size: 393 B |
BIN
editor/icons/batch.png
Normal file
After Width: | Height: | Size: 712 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
BIN
editor/icons/bridge-dash.png
Normal file
After Width: | Height: | Size: 508 B |
BIN
editor/icons/bridge.png
Normal file
After Width: | Height: | Size: 575 B |
BIN
editor/icons/cog.png
Normal file
After Width: | Height: | Size: 493 B |
BIN
editor/icons/comment.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
editor/icons/db.png
Normal file
After Width: | Height: | Size: 459 B |
BIN
editor/icons/debug.png
Normal file
After Width: | Height: | Size: 218 B |
BIN
editor/icons/envelope.png
Normal file
After Width: | Height: | Size: 324 B |
BIN
editor/icons/feed.png
Normal file
After Width: | Height: | Size: 378 B |
BIN
editor/icons/file.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
editor/icons/function.png
Normal file
After Width: | Height: | Size: 457 B |
BIN
editor/icons/hash.png
Normal file
After Width: | Height: | Size: 502 B |
BIN
editor/icons/inject.png
Normal file
After Width: | Height: | Size: 449 B |
BIN
editor/icons/join.png
Normal file
After Width: | Height: | Size: 253 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
editor/icons/light.png
Normal file
After Width: | Height: | Size: 639 B |
BIN
editor/icons/link-out.png
Normal file
After Width: | Height: | Size: 402 B |
Before Width: | Height: | Size: 414 B After Width: | Height: | Size: 414 B |
Before Width: | Height: | Size: 671 B After Width: | Height: | Size: 671 B |
BIN
editor/icons/node-changed.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
editor/icons/node-error.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
editor/icons/parser-csv.png
Normal file
After Width: | Height: | Size: 413 B |
BIN
editor/icons/parser-html.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
editor/icons/parser-json.png
Normal file
After Width: | Height: | Size: 467 B |
BIN
editor/icons/parser-xml.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
editor/icons/parser-yaml.png
Normal file
After Width: | Height: | Size: 423 B |
BIN
editor/icons/range.png
Normal file
After Width: | Height: | Size: 360 B |
Before Width: | Height: | Size: 736 B After Width: | Height: | Size: 736 B |
BIN
editor/icons/rpi.png
Normal file
After Width: | Height: | Size: 482 B |
BIN
editor/icons/serial.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
editor/icons/sort.png
Normal file
After Width: | Height: | Size: 793 B |
BIN
editor/icons/split.png
Normal file
After Width: | Height: | Size: 256 B |
BIN
editor/icons/subflow.png
Normal file
After Width: | Height: | Size: 439 B |
BIN
editor/icons/swap.png
Normal file
After Width: | Height: | Size: 592 B |
BIN
editor/icons/switch.png
Normal file
After Width: | Height: | Size: 509 B |
BIN
editor/icons/template.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
editor/icons/timer.png
Normal file
After Width: | Height: | Size: 628 B |
BIN
editor/icons/trigger.png
Normal file
After Width: | Height: | Size: 258 B |
BIN
editor/icons/twitter.png
Normal file
After Width: | Height: | Size: 404 B |
BIN
editor/icons/watch.png
Normal file
After Width: | Height: | Size: 591 B |
BIN
editor/icons/white-globe.png
Normal file
After Width: | Height: | Size: 707 B |
BIN
editor/images/deploy-flows-o.png
Normal file
After Width: | Height: | Size: 291 B |
BIN
editor/images/deploy-flows.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
editor/images/deploy-full-o.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
editor/images/deploy-full.png
Normal file
After Width: | Height: | Size: 368 B |
BIN
editor/images/deploy-nodes-o.png
Normal file
After Width: | Height: | Size: 290 B |
BIN
editor/images/deploy-nodes.png
Normal file
After Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
editor/images/node-red.png
Normal file
After Width: | Height: | Size: 1019 B |
BIN
editor/images/pw_maze_white.png
Normal file
After Width: | Height: | Size: 600 B |
BIN
editor/images/subflow_tab.png
Normal file
After Width: | Height: | Size: 410 B |
BIN
editor/images/typedInput/09.png
Normal file
After Width: | Height: | Size: 638 B |
BIN
editor/images/typedInput/az.png
Normal file
After Width: | Height: | Size: 546 B |
BIN
editor/images/typedInput/bin.png
Normal file
After Width: | Height: | Size: 638 B |
BIN
editor/images/typedInput/bool.png
Normal file
After Width: | Height: | Size: 646 B |
BIN
editor/images/typedInput/expr.png
Normal file
After Width: | Height: | Size: 563 B |
BIN
editor/images/typedInput/json.png
Normal file
After Width: | Height: | Size: 588 B |
BIN
editor/images/typedInput/re.png
Normal file
After Width: | Height: | Size: 502 B |
@@ -28,24 +28,14 @@ RED.comms = (function() {
|
||||
|
||||
function connectWS() {
|
||||
active = true;
|
||||
var wspath;
|
||||
|
||||
if (RED.settings.apiRootUrl) {
|
||||
var m = /^(https?):\/\/(.*)$/.exec(RED.settings.apiRootUrl);
|
||||
if (m) {
|
||||
console.log(m);
|
||||
wspath = "ws"+(m[1]==="https"?"s":"")+"://"+m[2]+"comms";
|
||||
}
|
||||
} else {
|
||||
var path = location.hostname;
|
||||
var port = location.port;
|
||||
if (port.length !== 0) {
|
||||
path = path+":"+port;
|
||||
}
|
||||
path = path+document.location.pathname;
|
||||
path = path+(path.slice(-1) == "/"?"":"/")+"comms";
|
||||
wspath = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path;
|
||||
var path = location.hostname;
|
||||
var port = location.port;
|
||||
if (port.length !== 0) {
|
||||
path = path+":"+port;
|
||||
}
|
||||
path = path+document.location.pathname;
|
||||
path = path+(path.slice(-1) == "/"?"":"/")+"comms";
|
||||
path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path;
|
||||
|
||||
var auth_tokens = RED.settings.get("auth-tokens");
|
||||
pendingAuth = (auth_tokens!=null);
|
||||
@@ -58,7 +48,7 @@ RED.comms = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
ws = new WebSocket(wspath);
|
||||
ws = new WebSocket(path);
|
||||
ws.onopen = function() {
|
||||
reconnectAttempts = 0;
|
||||
if (errornotification) {
|
||||
@@ -75,39 +65,29 @@ RED.comms = (function() {
|
||||
}
|
||||
ws.onmessage = function(event) {
|
||||
var message = JSON.parse(event.data);
|
||||
if (message.auth) {
|
||||
if (pendingAuth) {
|
||||
if (message.auth === "ok") {
|
||||
for (var m = 0; m < message.length; m++) {
|
||||
var msg = message[m];
|
||||
if (pendingAuth && msg.auth) {
|
||||
if (msg.auth === "ok") {
|
||||
pendingAuth = false;
|
||||
completeConnection();
|
||||
} else if (message.auth === "fail") {
|
||||
} else if (msg.auth === "fail") {
|
||||
// anything else is an error...
|
||||
active = false;
|
||||
RED.user.login({updateMenu:true},function() {
|
||||
connectWS();
|
||||
})
|
||||
}
|
||||
} else if (message.auth === "fail") {
|
||||
// Our current session has expired
|
||||
active = false;
|
||||
RED.user.login({updateMenu:true},function() {
|
||||
connectWS();
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Otherwise, 'message' is an array of actual comms messages
|
||||
for (var m = 0; m < message.length; m++) {
|
||||
var msg = message[m];
|
||||
if (msg.topic) {
|
||||
for (var t in subscriptions) {
|
||||
if (subscriptions.hasOwnProperty(t)) {
|
||||
var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
|
||||
if (re.test(msg.topic)) {
|
||||
var subscribers = subscriptions[t];
|
||||
if (subscribers) {
|
||||
for (var i=0;i<subscribers.length;i++) {
|
||||
subscribers[i](msg.topic,msg.data);
|
||||
}
|
||||
else if (msg.topic) {
|
||||
for (var t in subscriptions) {
|
||||
if (subscriptions.hasOwnProperty(t)) {
|
||||
var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
|
||||
if (re.test(msg.topic)) {
|
||||
var subscribers = subscriptions[t];
|
||||
if (subscribers) {
|
||||
for (var i=0;i<subscribers.length;i++) {
|
||||
subscribers[i](msg.topic,msg.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,10 +122,10 @@ RED.comms = (function() {
|
||||
connectWS();
|
||||
} else {
|
||||
var msg = RED._("notification.errors.lostConnectionReconnect",{time: connectCountdown})+' <a href="#">'+ RED._("notification.errors.lostConnectionTry")+'</a>';
|
||||
errornotification.update(msg,{silent:true});
|
||||
$(errornotification).find("a").on("click", function(e) {
|
||||
errornotification.update(msg);
|
||||
$(errornotification).find("a").click(function(e) {
|
||||
e.preventDefault();
|
||||
errornotification.update(RED._("notification.errors.lostConnection"),{silent:true});
|
||||
errornotification.update(RED._("notification.errors.lostConnection"));
|
||||
clearInterval(connectCountdownTimer);
|
||||
connectWS();
|
||||
})
|
332
editor/js/history.js
Normal file
@@ -0,0 +1,332 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.history = (function() {
|
||||
var undo_history = [];
|
||||
|
||||
function undoEvent(ev) {
|
||||
var i;
|
||||
var len;
|
||||
var node;
|
||||
var subflow;
|
||||
var modifiedTabs = {};
|
||||
if (ev) {
|
||||
if (ev.t == 'multi') {
|
||||
len = ev.events.length;
|
||||
for (i=len-1;i>=0;i--) {
|
||||
undoEvent(ev.events[i]);
|
||||
}
|
||||
} else if (ev.t == 'replace') {
|
||||
RED.nodes.clear();
|
||||
var imported = RED.nodes.import(ev.config);
|
||||
imported[0].forEach(function(n) {
|
||||
if (ev.changed[n.id]) {
|
||||
n.changed = true;
|
||||
}
|
||||
})
|
||||
|
||||
RED.nodes.version(ev.rev);
|
||||
} else if (ev.t == 'add') {
|
||||
if (ev.nodes) {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
node = RED.nodes.node(ev.nodes[i]);
|
||||
if (node.z) {
|
||||
modifiedTabs[node.z] = true;
|
||||
}
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.workspaces) {
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
RED.nodes.removeWorkspace(ev.workspaces[i].id);
|
||||
RED.workspaces.remove(ev.workspaces[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflows) {
|
||||
for (i=0;i<ev.subflows.length;i++) {
|
||||
RED.nodes.removeSubflow(ev.subflows[i]);
|
||||
RED.workspaces.remove(ev.subflows[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflow) {
|
||||
if (ev.subflow.instances) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('changed')) {
|
||||
subflow = RED.nodes.subflow(ev.subflow.id);
|
||||
if (subflow) {
|
||||
subflow.changed = ev.subflow.changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (ev.t == "delete") {
|
||||
if (ev.workspaces) {
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
RED.nodes.addWorkspace(ev.workspaces[i]);
|
||||
RED.workspaces.add(ev.workspaces[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflow && ev.subflow.subflow) {
|
||||
RED.nodes.addSubflow(ev.subflow.subflow);
|
||||
}
|
||||
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
|
||||
subflow = RED.nodes.subflow(ev.subflowInputs[0].z);
|
||||
subflow.in.push(ev.subflowInputs[0]);
|
||||
subflow.in[0].dirty = true;
|
||||
}
|
||||
if (ev.subflowOutputs && ev.subflowOutputs.length > 0) {
|
||||
subflow = RED.nodes.subflow(ev.subflowOutputs[0].z);
|
||||
ev.subflowOutputs.sort(function(a,b) { return a.i-b.i});
|
||||
for (i=0;i<ev.subflowOutputs.length;i++) {
|
||||
var output = ev.subflowOutputs[i];
|
||||
subflow.out.splice(output.i,0,output);
|
||||
for (var j=output.i+1;j<subflow.out.length;j++) {
|
||||
subflow.out[j].i++;
|
||||
subflow.out[j].dirty = true;
|
||||
}
|
||||
RED.nodes.eachLink(function(l) {
|
||||
if (l.source.type == "subflow:"+subflow.id) {
|
||||
if (l.sourcePort >= output.i) {
|
||||
l.sourcePort++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (ev.subflow && ev.subflow.hasOwnProperty('instances')) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (subflow) {
|
||||
RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) {
|
||||
n.inputs = subflow.in.length;
|
||||
n.outputs = subflow.out.length;
|
||||
while (n.outputs > n.ports.length) {
|
||||
n.ports.push(n.ports.length);
|
||||
}
|
||||
n.resize = true;
|
||||
n.dirty = true;
|
||||
});
|
||||
}
|
||||
if (ev.nodes) {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
RED.nodes.add(ev.nodes[i]);
|
||||
modifiedTabs[ev.nodes[i].z] = true;
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.addLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.changes) {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
node = RED.nodes.node(i);
|
||||
if (node) {
|
||||
for (var d in ev.changes[i]) {
|
||||
if (ev.changes[i].hasOwnProperty(d)) {
|
||||
node[d] = ev.changes[i][d];
|
||||
}
|
||||
}
|
||||
node.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (ev.t == "move") {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
var n = ev.nodes[i];
|
||||
n.n.x = n.ox;
|
||||
n.n.y = n.oy;
|
||||
n.n.dirty = true;
|
||||
n.n.moved = n.moved;
|
||||
}
|
||||
// A move could have caused a link splice
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "edit") {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
if (ev.node._def.defaults && ev.node._def.defaults[i] && ev.node._def.defaults[i].type) {
|
||||
// This is a config node property
|
||||
var currentConfigNode = RED.nodes.node(ev.node[i]);
|
||||
if (currentConfigNode) {
|
||||
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
|
||||
}
|
||||
var newConfigNode = RED.nodes.node(ev.changes[i]);
|
||||
if (newConfigNode) {
|
||||
newConfigNode.users.push(ev.node);
|
||||
}
|
||||
}
|
||||
ev.node[i] = ev.changes[i];
|
||||
}
|
||||
}
|
||||
if (ev.subflow) {
|
||||
if (ev.subflow.hasOwnProperty('inputCount')) {
|
||||
if (ev.node.in.length > ev.subflow.inputCount) {
|
||||
ev.node.in.splice(ev.subflow.inputCount);
|
||||
} else if (ev.subflow.inputs.length > 0) {
|
||||
ev.node.in = ev.node.in.concat(ev.subflow.inputs);
|
||||
}
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('outputCount')) {
|
||||
if (ev.node.out.length > ev.subflow.outputCount) {
|
||||
ev.node.out.splice(ev.subflow.outputCount);
|
||||
} else if (ev.subflow.outputs.length > 0) {
|
||||
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
|
||||
}
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('instances')) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.editor.validateNode(ev.node);
|
||||
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
||||
n.inputs = ev.node.in.length;
|
||||
n.outputs = ev.node.out.length;
|
||||
RED.editor.updateNodeProperties(n);
|
||||
RED.editor.validateNode(n);
|
||||
});
|
||||
} else {
|
||||
var outputMap;
|
||||
if (ev.outputMap) {
|
||||
outputMap = {};
|
||||
for (var port in ev.outputMap) {
|
||||
if (ev.outputMap.hasOwnProperty(port) && ev.outputMap[port] !== "-1") {
|
||||
outputMap[ev.outputMap[port]] = port;
|
||||
}
|
||||
}
|
||||
}
|
||||
RED.editor.updateNodeProperties(ev.node,outputMap);
|
||||
RED.editor.validateNode(ev.node);
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.addLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
ev.node.dirty = true;
|
||||
ev.node.changed = ev.changed;
|
||||
} else if (ev.t == "createSubflow") {
|
||||
if (ev.nodes) {
|
||||
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
|
||||
n.z = ev.activeWorkspace;
|
||||
n.dirty = true;
|
||||
});
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.removeSubflow(ev.subflow.subflow);
|
||||
RED.workspaces.remove(ev.subflow.subflow);
|
||||
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "reorder") {
|
||||
if (ev.order) {
|
||||
RED.workspaces.order(ev.order);
|
||||
}
|
||||
}
|
||||
Object.keys(modifiedTabs).forEach(function(id) {
|
||||
var subflow = RED.nodes.subflow(id);
|
||||
if (subflow) {
|
||||
RED.editor.validateNode(subflow);
|
||||
}
|
||||
});
|
||||
|
||||
RED.nodes.dirty(ev.dirty);
|
||||
RED.view.redraw(true);
|
||||
RED.palette.refresh();
|
||||
RED.workspaces.refresh();
|
||||
RED.sidebar.config.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
//TODO: this function is a placeholder until there is a 'save' event that can be listened to
|
||||
markAllDirty: function() {
|
||||
for (var i=0;i<undo_history.length;i++) {
|
||||
undo_history[i].dirty = true;
|
||||
}
|
||||
},
|
||||
list: function() {
|
||||
return undo_history
|
||||
},
|
||||
depth: function() {
|
||||
return undo_history.length;
|
||||
},
|
||||
push: function(ev) {
|
||||
undo_history.push(ev);
|
||||
},
|
||||
pop: function() {
|
||||
var ev = undo_history.pop();
|
||||
undoEvent(ev);
|
||||
},
|
||||
peek: function() {
|
||||
return undo_history[undo_history.length-1];
|
||||
},
|
||||
clear: function() {
|
||||
undo_history = [];
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@@ -16,14 +16,10 @@
|
||||
|
||||
RED.i18n = (function() {
|
||||
|
||||
var apiRootUrl;
|
||||
|
||||
return {
|
||||
init: function(options, done) {
|
||||
apiRootUrl = options.apiRootUrl||"";
|
||||
var preferredLanguage = localStorage.getItem("editor-language");
|
||||
var opts = {
|
||||
resGetPath: apiRootUrl+'locales/__ns__?lng=__lng__',
|
||||
init: function(done) {
|
||||
i18n.init({
|
||||
resGetPath: 'locales/__ns__?lng=__lng__',
|
||||
dynamicLoad: false,
|
||||
load:'current',
|
||||
ns: {
|
||||
@@ -31,40 +27,17 @@ RED.i18n = (function() {
|
||||
defaultNs: "editor"
|
||||
},
|
||||
fallbackLng: ['en-US'],
|
||||
useCookie: false,
|
||||
returnObjectTrees: true
|
||||
};
|
||||
if (preferredLanguage) {
|
||||
opts.lng = preferredLanguage;
|
||||
}
|
||||
i18n.init(opts,function() {
|
||||
useCookie: false
|
||||
},function() {
|
||||
done();
|
||||
});
|
||||
RED["_"] = function() {
|
||||
var v = i18n.t.apply(null,arguments);
|
||||
if (typeof v === 'string') {
|
||||
return v;
|
||||
} else {
|
||||
return arguments[0];
|
||||
}
|
||||
return i18n.t.apply(null,arguments);
|
||||
}
|
||||
|
||||
},
|
||||
lang: function() {
|
||||
// Gets the active message catalog language. This is based on what
|
||||
// locale the editor is using and what languages are available.
|
||||
//
|
||||
var preferredLangs = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var knownLangs = RED.settings.theme("languages")||["en-US"];
|
||||
for (var i=0;i<preferredLangs.length;i++) {
|
||||
if (knownLangs.indexOf(preferredLangs[i]) > -1) {
|
||||
return preferredLangs[i]
|
||||
}
|
||||
}
|
||||
return 'end-US'
|
||||
},
|
||||
loadNodeCatalog: function(namespace,done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
loadCatalog: function(namespace,done) {
|
||||
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
|
||||
var toLoad = languageList.length;
|
||||
languageList.forEach(function(lang) {
|
||||
$.ajax({
|
||||
@@ -72,7 +45,7 @@ RED.i18n = (function() {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: apiRootUrl+'nodes/'+namespace+'/messages?lng='+lang,
|
||||
url: 'locales/'+namespace+'?lng='+lang,
|
||||
success: function(data) {
|
||||
i18n.addResourceBundle(lang,namespace,data);
|
||||
toLoad--;
|
||||
@@ -86,7 +59,7 @@ RED.i18n = (function() {
|
||||
},
|
||||
|
||||
loadNodeCatalogs: function(done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
|
||||
var toLoad = languageList.length;
|
||||
|
||||
languageList.forEach(function(lang) {
|
||||
@@ -95,7 +68,7 @@ RED.i18n = (function() {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: apiRootUrl+'nodes/messages?lng='+lang,
|
||||
url: 'locales/nodes?lng='+lang,
|
||||
success: function(data) {
|
||||
var namespaces = Object.keys(data);
|
||||
namespaces.forEach(function(ns) {
|
@@ -1,39 +1,25 @@
|
||||
{
|
||||
"*": {
|
||||
"alt-shift-p":"core:manage-palette",
|
||||
"ctrl-shift-p":"core:manage-palette",
|
||||
"ctrl-f": "core:search",
|
||||
"ctrl-shift-f": "core:list-flows",
|
||||
"ctrl-=": "core:zoom-in",
|
||||
"ctrl--": "core:zoom-out",
|
||||
"ctrl-0": "core:zoom-reset",
|
||||
"ctrl-enter": "core:confirm-edit-tray",
|
||||
"ctrl-escape": "core:cancel-edit-tray",
|
||||
"ctrl-d": "core:deploy-flows",
|
||||
"ctrl-g i": "core:show-info-tab",
|
||||
"ctrl-g d": "core:show-debug-tab",
|
||||
"ctrl-g c": "core:show-config-tab",
|
||||
"ctrl-g x": "core:show-context-tab",
|
||||
"ctrl-e": "core:show-export-dialog",
|
||||
"ctrl-i": "core:show-import-dialog",
|
||||
"ctrl-space": "core:toggle-sidebar",
|
||||
"ctrl-p": "core:toggle-palette",
|
||||
"ctrl-,": "core:show-user-settings",
|
||||
"ctrl-alt-l": "core:clear-debug-messages",
|
||||
"ctrl-alt-r": "core:show-remote-diff",
|
||||
"ctrl-alt-n": "core:new-project",
|
||||
"ctrl-alt-o": "core:open-project",
|
||||
"ctrl-g v": "core:show-version-control-tab",
|
||||
"ctrl-shift-l": "core:show-event-log",
|
||||
"ctrl-shift-p":"core:show-action-list"
|
||||
"ctrl-g v": "core:show-version-control-tab"
|
||||
},
|
||||
"red-ui-sidebar-node-config": {
|
||||
"backspace": "core:delete-config-selection",
|
||||
"delete": "core:delete-config-selection",
|
||||
"ctrl-a": "core:select-all-config-nodes",
|
||||
"ctrl-z": "core:undo",
|
||||
"ctrl-y": "core:redo"
|
||||
},
|
||||
"red-ui-workspace": {
|
||||
"workspace": {
|
||||
"backspace": "core:delete-selection",
|
||||
"delete": "core:delete-selection",
|
||||
"enter": "core:edit-selected-node",
|
||||
@@ -41,17 +27,8 @@
|
||||
"ctrl-x": "core:cut-selection-to-internal-clipboard",
|
||||
"ctrl-v": "core:paste-from-internal-clipboard",
|
||||
"ctrl-z": "core:undo",
|
||||
"ctrl-y": "core:redo",
|
||||
"ctrl-a": "core:select-all-nodes",
|
||||
"shift-?": "core:show-help",
|
||||
"w": "core:scroll-view-up",
|
||||
"d": "core:scroll-view-right",
|
||||
"s": "core:scroll-view-down",
|
||||
"a": "core:scroll-view-left",
|
||||
"shift-w": "core:step-view-up",
|
||||
"shift-d": "core:step-view-right",
|
||||
"shift-s": "core:step-view-down",
|
||||
"shift-a": "core:step-view-left",
|
||||
"up": "core:move-selection-up",
|
||||
"right": "core:move-selection-right",
|
||||
"down": "core:move-selection-down",
|
||||
@@ -61,10 +38,6 @@
|
||||
"shift-down": "core:step-selection-down",
|
||||
"shift-left": "core:step-selection-left",
|
||||
"ctrl-shift-j": "core:show-previous-tab",
|
||||
"ctrl-shift-k": "core:show-next-tab",
|
||||
"ctrl-shift-g": "core:group-selection",
|
||||
"ctrl-shift-u": "core:ungroup-selection",
|
||||
"ctrl-shift-c": "core:copy-group-style",
|
||||
"ctrl-shift-v": "core:paste-group-style"
|
||||
"ctrl-shift-k": "core:show-next-tab"
|
||||
}
|
||||
}
|
@@ -13,66 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
var RED = (function() {
|
||||
|
||||
function appendNodeConfig(nodeConfig,done) {
|
||||
done = done || function(){};
|
||||
var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim());
|
||||
var moduleId;
|
||||
if (m) {
|
||||
moduleId = m[1];
|
||||
} else {
|
||||
moduleId = "unknown";
|
||||
}
|
||||
try {
|
||||
var hasDeferred = false;
|
||||
|
||||
var nodeConfigEls = $("<div>"+nodeConfig+"</div>");
|
||||
var scripts = nodeConfigEls.find("script");
|
||||
var scriptCount = scripts.length;
|
||||
scripts.each(function(i,el) {
|
||||
var srcUrl = $(el).attr('src');
|
||||
if (srcUrl && !/^\s*(https?:|\/|\.)/.test(srcUrl)) {
|
||||
$(el).remove();
|
||||
var newScript = document.createElement("script");
|
||||
newScript.onload = function() {
|
||||
scriptCount--;
|
||||
if (scriptCount === 0) {
|
||||
$("#red-ui-editor-node-configs").append(nodeConfigEls);
|
||||
done()
|
||||
}
|
||||
}
|
||||
if ($(el).attr('type') === "module") {
|
||||
newScript.type = "module";
|
||||
}
|
||||
$("#red-ui-editor-node-configs").append(newScript);
|
||||
newScript.src = RED.settings.apiRootUrl+srcUrl;
|
||||
hasDeferred = true;
|
||||
} else {
|
||||
if (/\/ace.js$/.test(srcUrl) || /\/ext-language_tools.js$/.test(srcUrl)) {
|
||||
// Block any attempts to load ace.js from a CDN - this will
|
||||
// break the version of ace included in the editor.
|
||||
// At the time of commit, the contrib-python nodes did this.
|
||||
// This is a crude fix until the python nodes are fixed.
|
||||
console.warn("Blocked attempt to load",srcUrl,"by",moduleId)
|
||||
$(el).remove();
|
||||
}
|
||||
scriptCount--;
|
||||
}
|
||||
})
|
||||
if (!hasDeferred) {
|
||||
$("#red-ui-editor-node-configs").append(nodeConfigEls);
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
RED.notify(RED._("notification.errors.failedToAppendNode",{module:moduleId, error:err.toString()}),{
|
||||
type: "error",
|
||||
timeout: 10000
|
||||
});
|
||||
console.log("["+moduleId+"] "+err.toString());
|
||||
done();
|
||||
}
|
||||
}
|
||||
(function() {
|
||||
|
||||
function loadNodeList() {
|
||||
$.ajax({
|
||||
@@ -107,51 +48,40 @@ var RED = (function() {
|
||||
}
|
||||
|
||||
function loadNodes() {
|
||||
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
|
||||
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"text/html",
|
||||
"Accept-Language": lang
|
||||
"Accept":"text/html"
|
||||
},
|
||||
cache: false,
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
var configs = data.trim().split(/(?=<!-- --- \[red-module:\S+\] --- -->)/);
|
||||
var stepConfig = function() {
|
||||
if (configs.length === 0) {
|
||||
$("#red-ui-editor").i18n();
|
||||
$("#red-ui-palette > .red-ui-palette-spinner").hide();
|
||||
$(".red-ui-palette-scroll").removeClass("hide");
|
||||
$("#red-ui-palette-search").removeClass("hide");
|
||||
loadFlows(function() {
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
RED.projects.refresh(function(activeProject) {
|
||||
RED.sidebar.info.refresh()
|
||||
if (!activeProject) {
|
||||
// Projects enabled but no active project
|
||||
RED.menu.setDisabled('menu-item-projects-open',true);
|
||||
RED.menu.setDisabled('menu-item-projects-settings',true);
|
||||
if (activeProject === false) {
|
||||
// User previously decline the migration to projects.
|
||||
} else { // null/undefined
|
||||
RED.projects.showStartup();
|
||||
}
|
||||
}
|
||||
completeLoad();
|
||||
});
|
||||
} else {
|
||||
// Projects disabled by the user
|
||||
RED.sidebar.info.refresh()
|
||||
completeLoad();
|
||||
$("body").append(data);
|
||||
$("body").i18n();
|
||||
$("#palette > .palette-spinner").hide();
|
||||
$(".palette-scroll").removeClass("hide");
|
||||
$("#palette-search").removeClass("hide");
|
||||
loadFlows(function() {
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
RED.projects.refresh(function(activeProject) {
|
||||
RED.sidebar.info.refresh()
|
||||
if (!activeProject) {
|
||||
// Projects enabled but no active project
|
||||
RED.menu.setDisabled('menu-item-projects-open',true);
|
||||
RED.menu.setDisabled('menu-item-projects-settings',true);
|
||||
if (activeProject === false) {
|
||||
// User previously decline the migration to projects.
|
||||
} else { // null/undefined
|
||||
RED.projects.showStartup();
|
||||
}
|
||||
}
|
||||
completeLoad();
|
||||
});
|
||||
} else {
|
||||
var config = configs.shift();
|
||||
appendNodeConfig(config,stepConfig);
|
||||
// Projects disabled by the user
|
||||
RED.sidebar.info.refresh()
|
||||
completeLoad();
|
||||
}
|
||||
}
|
||||
stepConfig();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -200,13 +130,13 @@ var RED = (function() {
|
||||
loadFlows(function() {
|
||||
var project = RED.projects.getActiveProject();
|
||||
var message = {
|
||||
"change-branch": RED._("notification.project.change-branch", {project: project.git.branches.local}),
|
||||
"merge-abort": RED._("notification.project.merge-abort"),
|
||||
"loaded": RED._("notification.project.loaded", {project: msg.project}),
|
||||
"updated": RED._("notification.project.updated", {project: msg.project}),
|
||||
"pull": RED._("notification.project.pull", {project: msg.project}),
|
||||
"revert": RED._("notification.project.revert", {project: msg.project}),
|
||||
"merge-complete": RED._("notification.project.merge-complete")
|
||||
"change-branch":"Change to local branch '"+project.git.branches.local+"'",
|
||||
"merge-abort":"Git merge aborted",
|
||||
"loaded":"Project '"+msg.project+"' loaded",
|
||||
"updated":"Project '"+msg.project+"' updated",
|
||||
"pull":"Project '"+msg.project+"' reloaded",
|
||||
"revert": "Project '"+msg.project+"' reloaded",
|
||||
"merge-complete":"Git merge completed"
|
||||
}[msg.action];
|
||||
RED.notify("<p>"+message+"</p>");
|
||||
RED.sidebar.info.refresh()
|
||||
@@ -225,32 +155,23 @@ var RED = (function() {
|
||||
id: notificationId
|
||||
}
|
||||
if (notificationId === "runtime-state") {
|
||||
if (msg.error === "safe-mode") {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
}
|
||||
]
|
||||
} else if (msg.error === "missing-types") {
|
||||
text+="<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||
if (msg.error === "missing-types") {
|
||||
text+="<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
if (!!RED.projects.getActiveProject()) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.manage-project-dep"),
|
||||
text: "Manage project dependencies",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.settings.show('deps');
|
||||
}
|
||||
}
|
||||
]
|
||||
// } else if (RED.settings.theme('palette.editable') !== false) {
|
||||
// } else if (RED.settings.theme('palette.editable') !== false) {
|
||||
} else {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
text: "Close",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
@@ -258,25 +179,13 @@ var RED = (function() {
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "credentials_load_failed") {
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
// projects enabled
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.project.setupCredentials"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.showCredentialsPrompt();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
text: "Setup credentials",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.showCredentialsPrompt();
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -285,19 +194,7 @@ var RED = (function() {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.project.setupProjectFiles"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.showFilesPrompt();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "missing_package_file") {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.project.setupProjectFiles"),
|
||||
text: "Setup project files",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.showFilesPrompt();
|
||||
@@ -309,13 +206,13 @@ var RED = (function() {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.project.no"),
|
||||
text: "No thanks",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("notification.project.createDefault"),
|
||||
text: "Create default project files",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.createDefaultFileSet();
|
||||
@@ -329,7 +226,7 @@ var RED = (function() {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.project.mergeConflict"),
|
||||
text: "Show merge conflicts",
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.sidebar.versionControl.showLocalChanges();
|
||||
@@ -353,11 +250,12 @@ var RED = (function() {
|
||||
var parts = topic.split("/");
|
||||
var node = RED.nodes.node(parts[1]);
|
||||
if (node) {
|
||||
if (msg.hasOwnProperty("text") && /^[a-zA-Z]/.test(msg.text)) {
|
||||
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
|
||||
if (msg.hasOwnProperty("text")) {
|
||||
if (msg.text[0] !== ".") {
|
||||
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
|
||||
}
|
||||
}
|
||||
node.status = msg;
|
||||
node.dirtyStatus = true;
|
||||
node.dirty = true;
|
||||
RED.view.redraw();
|
||||
}
|
||||
@@ -372,9 +270,9 @@ var RED = (function() {
|
||||
var id = m.id;
|
||||
RED.nodes.addNodeSet(m);
|
||||
addedTypes = addedTypes.concat(m.types);
|
||||
RED.i18n.loadNodeCatalog(id, function() {
|
||||
RED.i18n.loadCatalog(id, function() {
|
||||
$.get('nodes/'+id, function(data) {
|
||||
appendNodeConfig(data);
|
||||
$("body").append(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -402,7 +300,7 @@ var RED = (function() {
|
||||
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
|
||||
} else {
|
||||
$.get('nodes/'+msg.id, function(data) {
|
||||
appendNodeConfig(data);
|
||||
$("body").append(data);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
|
||||
});
|
||||
@@ -414,51 +312,61 @@ var RED = (function() {
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success");
|
||||
}
|
||||
} else if (topic == "notification/node/upgraded") {
|
||||
} else if (topic == "node/upgraded") {
|
||||
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
|
||||
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version);
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("event-log/#", function(topic,payload) {
|
||||
var id = topic.substring(9);
|
||||
RED.eventLog.log(id,payload);
|
||||
// Refresh flow library to ensure any examples are updated
|
||||
RED.library.loadFlowLibrary();
|
||||
});
|
||||
}
|
||||
|
||||
function showAbout() {
|
||||
$.get('red/about', function(data) {
|
||||
var aboutHeader = '<div style="text-align:center;">'+
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
|
||||
RED.sidebar.info.set(aboutHeader+RED.utils.renderMarkdown(data));
|
||||
RED.sidebar.info.set(aboutHeader+marked(data));
|
||||
RED.sidebar.info.show();
|
||||
});
|
||||
}
|
||||
|
||||
function buildMainMenu() {
|
||||
function loadEditor() {
|
||||
var menuOptions = [];
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
menuOptions.push({id:"menu-item-projects-menu",label:RED._("menu.label.projects"),options:[
|
||||
{id:"menu-item-projects-new",label:RED._("menu.label.projects-new"),disabled:false,onselect:"core:new-project"},
|
||||
{id:"menu-item-projects-open",label:RED._("menu.label.projects-open"),disabled:false,onselect:"core:open-project"},
|
||||
{id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"}
|
||||
menuOptions.push({id:"menu-item-projects-menu",label:"Projects",options:[
|
||||
{id:"menu-item-projects-new",label:"New",disabled:false,onselect:"core:new-project"},
|
||||
{id:"menu-item-projects-open",label:"Open",disabled:false,onselect:"core:open-project"},
|
||||
{id:"menu-item-projects-settings",label:"Project Settings",disabled:false,onselect:"core:show-project-settings"}
|
||||
]});
|
||||
}
|
||||
|
||||
|
||||
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
|
||||
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
|
||||
// {id:"menu-item-view-show-grid",setting:"view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
|
||||
// {id:"menu-item-view-snap-grid",setting:"view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
|
||||
// {id:"menu-item-status",setting:"node-show-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true},
|
||||
//null,
|
||||
// {id:"menu-item-bidi",label:RED._("menu.label.view.textDir"),options:[
|
||||
// {id:"menu-item-bidi-default",toggle:"text-direction",label:RED._("menu.label.view.defaultDir"),selected: true, onselect:function(s) { if(s){RED.text.bidi.setTextDirection("")}}},
|
||||
// {id:"menu-item-bidi-ltr",toggle:"text-direction",label:RED._("menu.label.view.ltr"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("ltr")}}},
|
||||
// {id:"menu-item-bidi-rtl",toggle:"text-direction",label:RED._("menu.label.view.rtl"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("rtl")}}},
|
||||
// {id:"menu-item-bidi-auto",toggle:"text-direction",label:RED._("menu.label.view.auto"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("auto")}}}
|
||||
// ]},
|
||||
// null,
|
||||
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
|
||||
{id:"menu-item-event-log",label:RED._("eventLog.title"),onselect:"core:show-event-log"},
|
||||
{id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"},
|
||||
null
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
if (RED.settings.theme("menu.menu-item-import-library", true)) {
|
||||
menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"});
|
||||
}
|
||||
if (RED.settings.theme("menu.menu-item-export-library", true)) {
|
||||
menuOptions.push({id: "menu-item-export", label: RED._("menu.label.export"), onselect: "core:show-export-dialog"});
|
||||
}
|
||||
menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[
|
||||
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-import-dialog"},
|
||||
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[
|
||||
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:"core:show-export-dialog"},
|
||||
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"}
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"});
|
||||
menuOptions.push(null);
|
||||
@@ -472,14 +380,6 @@ var RED = (function() {
|
||||
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"},
|
||||
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"},
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-group",label:RED._("menu.label.groups"), options: [
|
||||
{id:"menu-item-group-group",label:RED._("menu.label.groupSelection"),disabled:true,onselect:"core:group-selection"},
|
||||
{id:"menu-item-group-ungroup",label:RED._("menu.label.ungroupSelection"),disabled:true,onselect:"core:ungroup-selection"},
|
||||
null,
|
||||
{id:"menu-item-group-merge",label:RED._("menu.label.groupMergeSelection"),disabled:true,onselect:"core:merge-selection-to-group"},
|
||||
{id:"menu-item-group-remove",label:RED._("menu.label.groupRemoveSelection"),disabled:true,onselect:"core:remove-selection-from-group"}
|
||||
]});
|
||||
|
||||
menuOptions.push(null);
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
|
||||
@@ -489,9 +389,7 @@ var RED = (function() {
|
||||
menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.settings"),onselect:"core:show-user-settings"});
|
||||
menuOptions.push(null);
|
||||
|
||||
if (RED.settings.theme("menu.menu-item-keyboard-shortcuts", true)) {
|
||||
menuOptions.push({id: "menu-item-keyboard-shortcuts", label: RED._("menu.label.keyboardShortcuts"), onselect: "core:show-help"});
|
||||
}
|
||||
menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"});
|
||||
menuOptions.push({id:"menu-item-help",
|
||||
label: RED.settings.theme("menu.menu-item-help.label",RED._("menu.label.help")),
|
||||
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
|
||||
@@ -499,24 +397,12 @@ var RED = (function() {
|
||||
menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" });
|
||||
|
||||
|
||||
$('<li><a id="red-ui-header-button-sidemenu" class="button" href="#"><i class="fa fa-bars"></i></a></li>').appendTo(".red-ui-header-toolbar")
|
||||
RED.menu.init({id:"red-ui-header-button-sidemenu",options: menuOptions});
|
||||
|
||||
}
|
||||
|
||||
function loadEditor() {
|
||||
|
||||
RED.workspaces.init();
|
||||
RED.statusBar.init();
|
||||
RED.view.init();
|
||||
RED.userSettings.init();
|
||||
RED.user.init();
|
||||
RED.notifications.init();
|
||||
RED.library.init();
|
||||
RED.keyboard.init();
|
||||
RED.palette.init();
|
||||
RED.eventLog.init();
|
||||
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
RED.palette.editor.init();
|
||||
} else {
|
||||
@@ -532,81 +418,37 @@ var RED = (function() {
|
||||
}
|
||||
|
||||
RED.subflow.init();
|
||||
RED.group.init();
|
||||
RED.workspaces.init();
|
||||
RED.clipboard.init();
|
||||
RED.search.init();
|
||||
RED.actionList.init();
|
||||
RED.editor.init();
|
||||
RED.diff.init();
|
||||
|
||||
RED.menu.init({id:"btn-sidemenu",options: menuOptions});
|
||||
|
||||
RED.deploy.init(RED.settings.theme("deployButton",null));
|
||||
RED.notifications.init();
|
||||
|
||||
buildMainMenu();
|
||||
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
RED.nodes.init();
|
||||
RED.comms.connect();
|
||||
|
||||
$("#red-ui-main-container").show();
|
||||
$(".red-ui-header-toolbar").show();
|
||||
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
$("#main-container").show();
|
||||
$(".header-toolbar").show();
|
||||
|
||||
loadNodeList();
|
||||
}
|
||||
|
||||
function buildEditor(options) {
|
||||
var header = $('<div id="red-ui-header"></div>').appendTo(options.target);
|
||||
var logo = $('<span class="red-ui-header-logo"></span>').appendTo(header);
|
||||
$('<ul class="red-ui-header-toolbar hide"></ul>').appendTo(header);
|
||||
$('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header);
|
||||
$('<div id="red-ui-main-container" class="red-ui-sidebar-closed hide">'+
|
||||
'<div id="red-ui-workspace"></div>'+
|
||||
'<div id="red-ui-editor-stack"></div>'+
|
||||
'<div id="red-ui-palette"></div>'+
|
||||
'<div id="red-ui-sidebar"></div>'+
|
||||
'<div id="red-ui-sidebar-separator"></div>'+
|
||||
'</div>').appendTo(options.target);
|
||||
$('<div id="red-ui-editor-node-configs"></div>').appendTo(options.target);
|
||||
$('<div id="red-ui-full-shade" class="hide"></div>').appendTo(options.target);
|
||||
$.getJSON(options.apiRootUrl+"theme", function(theme) {
|
||||
if (theme.header) {
|
||||
if (theme.header.url) {
|
||||
logo = $("<a>",{href:theme.header.url}).appendTo(logo);
|
||||
}
|
||||
if (theme.header.image) {
|
||||
$('<img>',{src:theme.header.image}).appendTo(logo);
|
||||
}
|
||||
if (theme.header.title) {
|
||||
$('<span>').html(theme.header.title).appendTo(logo);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$(function() {
|
||||
|
||||
var initialised = false;
|
||||
|
||||
function init(options) {
|
||||
if (initialised) {
|
||||
throw new Error("RED already initialised");
|
||||
if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) {
|
||||
document.title = document.title+" : "+window.location.hostname;
|
||||
}
|
||||
initialised = true;
|
||||
|
||||
ace.require("ace/ext/language_tools");
|
||||
options = options || {};
|
||||
options.apiRootUrl = options.apiRootUrl || "";
|
||||
if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) {
|
||||
options.apiRootUrl = options.apiRootUrl+"/";
|
||||
}
|
||||
options.target = $("#red-ui-editor");
|
||||
options.target.addClass("red-ui-editor");
|
||||
|
||||
buildEditor(options);
|
||||
RED.i18n.init(options, function() {
|
||||
RED.settings.init(options, loadEditor);
|
||||
RED.i18n.init(function() {
|
||||
RED.settings.init(loadEditor);
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
init: init
|
||||
}
|
||||
});
|
||||
})();
|
@@ -17,8 +17,6 @@ RED.nodes = (function() {
|
||||
|
||||
var node_defs = {};
|
||||
var nodes = [];
|
||||
var nodeTabMap = {};
|
||||
|
||||
var configNodes = {};
|
||||
var links = [];
|
||||
var defaultWorkspace;
|
||||
@@ -27,9 +25,6 @@ RED.nodes = (function() {
|
||||
var subflows = {};
|
||||
var loadedFlowVersion = null;
|
||||
|
||||
var groups = {};
|
||||
var groupsByZ = {};
|
||||
|
||||
var initialLoad;
|
||||
|
||||
var dirty = false;
|
||||
@@ -138,7 +133,7 @@ RED.nodes = (function() {
|
||||
registerNodeType: function(nt,def) {
|
||||
nodeDefinitions[nt] = def;
|
||||
def.type = nt;
|
||||
if (nt.substring(0,8) != "subflow:") {
|
||||
if (def.category != "subflows") {
|
||||
def.set = nodeSets[typeToId[nt]];
|
||||
nodeSets[typeToId[nt]].added = true;
|
||||
nodeSets[typeToId[nt]].enabled = true;
|
||||
@@ -179,7 +174,6 @@ RED.nodes = (function() {
|
||||
},
|
||||
setIconSets: function(sets) {
|
||||
iconSets = sets;
|
||||
iconSets["font-awesome"] = RED.nodes.fontAwesome.getIconList();
|
||||
},
|
||||
getIconSets: function() {
|
||||
return iconSets;
|
||||
@@ -218,11 +212,6 @@ RED.nodes = (function() {
|
||||
n.i = nextId+1;
|
||||
}
|
||||
nodes.push(n);
|
||||
if (nodeTabMap[n.z]) {
|
||||
nodeTabMap[n.z][n.id] = n;
|
||||
} else {
|
||||
console.warn("Node added to unknown tab/subflow:",n);
|
||||
}
|
||||
}
|
||||
RED.events.emit('nodes:add',n);
|
||||
}
|
||||
@@ -256,9 +245,6 @@ RED.nodes = (function() {
|
||||
node = getNode(id);
|
||||
if (node) {
|
||||
nodes.splice(nodes.indexOf(node),1);
|
||||
if (nodeTabMap[node.z]) {
|
||||
delete nodeTabMap[node.z][node.id];
|
||||
}
|
||||
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
|
||||
removedLinks.forEach(function(l) {links.splice(links.indexOf(l), 1); });
|
||||
var updatedConfigNode = false;
|
||||
@@ -304,28 +290,6 @@ RED.nodes = (function() {
|
||||
return {links:removedLinks,nodes:removedNodes};
|
||||
}
|
||||
|
||||
function moveNodeToTab(node, z) {
|
||||
if (node.type === "group") {
|
||||
moveGroupToTab(node,z);
|
||||
return;
|
||||
}
|
||||
if (nodeTabMap[node.z]) {
|
||||
delete nodeTabMap[node.z][node.id];
|
||||
}
|
||||
if (!nodeTabMap[z]) {
|
||||
nodeTabMap[z] = {};
|
||||
}
|
||||
nodeTabMap[z][node.id] = node;
|
||||
node.z = z;
|
||||
}
|
||||
function moveGroupToTab(group, z) {
|
||||
var index = groupsByZ[group.z].indexOf(group);
|
||||
groupsByZ[group.z].splice(index,1);
|
||||
groupsByZ[z] = groupsByZ[z] || [];
|
||||
groupsByZ[z].push(group);
|
||||
group.z = z;
|
||||
}
|
||||
|
||||
function removeLink(l) {
|
||||
var index = links.indexOf(l);
|
||||
if (index != -1) {
|
||||
@@ -333,28 +297,20 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function addWorkspace(ws,targetIndex) {
|
||||
function addWorkspace(ws) {
|
||||
workspaces[ws.id] = ws;
|
||||
nodeTabMap[ws.id] = {};
|
||||
|
||||
ws._def = RED.nodes.getType('tab');
|
||||
if (targetIndex === undefined) {
|
||||
workspacesOrder.push(ws.id);
|
||||
} else {
|
||||
workspacesOrder.splice(targetIndex,0,ws.id);
|
||||
}
|
||||
workspacesOrder.push(ws.id);
|
||||
}
|
||||
function getWorkspace(id) {
|
||||
return workspaces[id];
|
||||
}
|
||||
function removeWorkspace(id) {
|
||||
delete workspaces[id];
|
||||
delete nodeTabMap[id];
|
||||
workspacesOrder.splice(workspacesOrder.indexOf(id),1);
|
||||
|
||||
var removedNodes = [];
|
||||
var removedLinks = [];
|
||||
var removedGroups = [];
|
||||
var n;
|
||||
var node;
|
||||
for (n=0;n<nodes.length;n++) {
|
||||
@@ -371,17 +327,11 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
removedGroups = groupsByZ[id] || [];
|
||||
removedGroups.forEach(function(g) {
|
||||
delete groups[g.id]
|
||||
})
|
||||
delete groupsByZ[id];
|
||||
|
||||
for (n=0;n<removedNodes.length;n++) {
|
||||
var result = removeNode(removedNodes[n].id);
|
||||
removedLinks = removedLinks.concat(result.links);
|
||||
}
|
||||
return {nodes:removedNodes,links:removedLinks, groups: removedGroups};
|
||||
return {nodes:removedNodes,links:removedLinks};
|
||||
}
|
||||
|
||||
function addSubflow(sf, createNewIds) {
|
||||
@@ -402,37 +352,19 @@ RED.nodes = (function() {
|
||||
sf.name = subflowName;
|
||||
}
|
||||
subflows[sf.id] = sf;
|
||||
nodeTabMap[sf.id] = {};
|
||||
|
||||
RED.nodes.registerType("subflow:"+sf.id, {
|
||||
defaults:{
|
||||
name:{value:""},
|
||||
env:{value:[]}
|
||||
},
|
||||
icon: function() { return sf.icon||"subflow.svg" },
|
||||
category: sf.category || "subflows",
|
||||
defaults:{name:{value:""}},
|
||||
info: sf.info,
|
||||
icon: function() { return sf.icon||"subflow.png" },
|
||||
category: "subflows",
|
||||
inputs: sf.in.length,
|
||||
outputs: sf.out.length,
|
||||
color: sf.color || "#DDAA99",
|
||||
color: "#da9",
|
||||
label: function() { return this.name||RED.nodes.subflow(sf.id).name },
|
||||
labelStyle: function() { return this.name?"red-ui-flow-node-label-italic":""; },
|
||||
labelStyle: function() { return this.name?"node_label_italic":""; },
|
||||
paletteLabel: function() { return RED.nodes.subflow(sf.id).name },
|
||||
inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null },
|
||||
outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null },
|
||||
oneditprepare: function() {
|
||||
RED.subflow.buildEditForm("subflow",this);
|
||||
RED.subflow.buildPropertiesForm(this);
|
||||
},
|
||||
oneditresize: function(size) {
|
||||
// var rows = $(".dialog-form>div:not(.node-input-env-container-row)");
|
||||
var height = size.height;
|
||||
// for (var i=0; i<rows.size(); i++) {
|
||||
// height -= $(rows[i]).outerHeight(true);
|
||||
// }
|
||||
// var editorRow = $("#dialog-form>div.node-input-env-container-row");
|
||||
// height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("ol.red-ui-editor-subflow-env-list").editableList('height',height);
|
||||
},
|
||||
set:{
|
||||
module: "node-red"
|
||||
}
|
||||
@@ -444,7 +376,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
function removeSubflow(sf) {
|
||||
delete subflows[sf.id];
|
||||
delete nodeTabMap[sf.id];
|
||||
registry.removeNodeType("subflow:"+sf.id);
|
||||
}
|
||||
|
||||
@@ -515,12 +446,7 @@ RED.nodes = (function() {
|
||||
node.id = n.id;
|
||||
node.type = n.type;
|
||||
node.z = n.z;
|
||||
if (n.d === true) {
|
||||
node.d = true;
|
||||
}
|
||||
if (n.g) {
|
||||
node.g = n.g;
|
||||
}
|
||||
|
||||
if (node.type == "unknown") {
|
||||
for (var p in n._orig) {
|
||||
if (n._orig.hasOwnProperty(p)) {
|
||||
@@ -533,33 +459,19 @@ RED.nodes = (function() {
|
||||
node[d] = n[d];
|
||||
}
|
||||
}
|
||||
if (exportCreds) {
|
||||
if(exportCreds && n.credentials) {
|
||||
var credentialSet = {};
|
||||
if (/^subflow:/.test(node.type) && n.credentials) {
|
||||
// A subflow instance node can have arbitrary creds
|
||||
for (var sfCred in n.credentials) {
|
||||
if (n.credentials.hasOwnProperty(sfCred)) {
|
||||
node.credentials = {};
|
||||
for (var cred in n._def.credentials) {
|
||||
if (n._def.credentials.hasOwnProperty(cred)) {
|
||||
if (n._def.credentials[cred].type == 'password') {
|
||||
if (!n.credentials._ ||
|
||||
n.credentials["has_"+sfCred] != n.credentials._["has_"+sfCred] ||
|
||||
(n.credentials["has_"+sfCred] && n.credentials[sfCred])) {
|
||||
credentialSet[sfCred] = n.credentials[sfCred];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (n.credentials) {
|
||||
node.credentials = {};
|
||||
// All other nodes have a well-defined list of possible credentials
|
||||
for (var cred in n._def.credentials) {
|
||||
if (n._def.credentials.hasOwnProperty(cred)) {
|
||||
if (n._def.credentials[cred].type == 'password') {
|
||||
if (!n.credentials._ ||
|
||||
n.credentials["has_"+cred] != n.credentials._["has_"+cred] ||
|
||||
(n.credentials["has_"+cred] && n.credentials[cred])) {
|
||||
credentialSet[cred] = n.credentials[cred];
|
||||
}
|
||||
} else if (n.credentials[cred] != null && (!n.credentials._ || n.credentials[cred] != n.credentials._[cred])) {
|
||||
n.credentials["has_"+cred] != n.credentials._["has_"+cred] ||
|
||||
(n.credentials["has_"+cred] && n.credentials[cred])) {
|
||||
credentialSet[cred] = n.credentials[cred];
|
||||
}
|
||||
} else if (n.credentials[cred] != null && (!n.credentials._ || n.credentials[cred] != n.credentials._[cred])) {
|
||||
credentialSet[cred] = n.credentials[cred];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -568,13 +480,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n.type === "group") {
|
||||
node.x = n.x;
|
||||
node.y = n.y;
|
||||
node.w = n.w;
|
||||
node.h = n.h;
|
||||
node.nodes = node.nodes.map(function(n) { return n.id });
|
||||
}
|
||||
if (n._def.category != "config") {
|
||||
node.x = n.x;
|
||||
node.y = n.y;
|
||||
@@ -586,9 +491,7 @@ RED.nodes = (function() {
|
||||
for (var j=0;j<wires.length;j++) {
|
||||
var w = wires[j];
|
||||
if (w.target.type != "subflow") {
|
||||
if (w.sourcePort < node.wires.length) {
|
||||
node.wires[w.sourcePort].push(w.target.id);
|
||||
}
|
||||
node.wires[w.sourcePort].push(w.target.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,48 +507,18 @@ RED.nodes = (function() {
|
||||
node.icon = n.icon;
|
||||
}
|
||||
}
|
||||
if ((!n._def.defaults || !n._def.defaults.hasOwnProperty("l")) && n.hasOwnProperty('l')) {
|
||||
var isLink = /^link (in|out)$/.test(node.type);
|
||||
if (isLink == n.l) {
|
||||
node.l = n.l;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n.info) {
|
||||
node.info = n.info;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function convertSubflow(n, exportCreds) {
|
||||
function convertSubflow(n) {
|
||||
var node = {};
|
||||
node.id = n.id;
|
||||
node.type = n.type;
|
||||
node.name = n.name;
|
||||
node.info = n.info;
|
||||
node.category = n.category;
|
||||
node.in = [];
|
||||
node.out = [];
|
||||
node.env = n.env;
|
||||
|
||||
if (exportCreds) {
|
||||
var credentialSet = {};
|
||||
// A subflow node can have arbitrary creds
|
||||
for (var sfCred in n.credentials) {
|
||||
if (n.credentials.hasOwnProperty(sfCred)) {
|
||||
if (!n.credentials._ ||
|
||||
n.credentials["has_"+sfCred] != n.credentials._["has_"+sfCred] ||
|
||||
(n.credentials["has_"+sfCred] && n.credentials[sfCred])) {
|
||||
credentialSet[sfCred] = n.credentials[sfCred];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(credentialSet).length > 0) {
|
||||
node.credentials = credentialSet;
|
||||
}
|
||||
}
|
||||
|
||||
node.color = n.color;
|
||||
|
||||
n.in.forEach(function(p) {
|
||||
var nIn = {x:p.x,y:p.y,wires:[]};
|
||||
@@ -678,40 +551,18 @@ RED.nodes = (function() {
|
||||
node.outputLabels = n.outputLabels.slice();
|
||||
}
|
||||
if (n.icon) {
|
||||
if (n.icon !== "node-red/subflow.svg") {
|
||||
if (n.icon !== "node-red/subflow.png") {
|
||||
node.icon = n.icon;
|
||||
}
|
||||
}
|
||||
if (n.status) {
|
||||
node.status = {x: n.status.x, y: n.status.y, wires:[]};
|
||||
links.forEach(function(d) {
|
||||
if (d.target === n.status) {
|
||||
if (d.source.type != "subflow") {
|
||||
node.status.wires.push({id:d.source.id, port:d.sourcePort})
|
||||
} else {
|
||||
node.status.wires.push({id:n.id, port:0})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
/**
|
||||
* Converts the current node selection to an exportable JSON Object
|
||||
**/
|
||||
function createExportableNodeSet(set, exportedIds, exportedSubflows, exportedConfigNodes) {
|
||||
function createExportableNodeSet(set, exportedSubflows, exportedConfigNodes) {
|
||||
var nns = [];
|
||||
|
||||
exportedIds = exportedIds || {};
|
||||
set = set.filter(function(n) {
|
||||
if (exportedIds[n.id]) {
|
||||
return false;
|
||||
}
|
||||
exportedIds[n.id] = true;
|
||||
return true;
|
||||
})
|
||||
|
||||
exportedConfigNodes = exportedConfigNodes || {};
|
||||
exportedSubflows = exportedSubflows || {};
|
||||
for (var n=0;n<set.length;n++) {
|
||||
@@ -727,11 +578,11 @@ RED.nodes = (function() {
|
||||
subflowSet.push(n);
|
||||
}
|
||||
});
|
||||
var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes);
|
||||
var exportableSubflow = createExportableNodeSet(subflowSet, exportedSubflows, exportedConfigNodes);
|
||||
nns = exportableSubflow.concat(nns);
|
||||
}
|
||||
}
|
||||
if (node.type !== "subflow") {
|
||||
if (node.type != "subflow") {
|
||||
var convertedNode = RED.nodes.convertNode(node);
|
||||
for (var d in node._def.defaults) {
|
||||
if (node._def.defaults[d].type && node[d] in configNodes) {
|
||||
@@ -748,9 +599,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
nns.push(convertedNode);
|
||||
if (node.type === "group") {
|
||||
nns = nns.concat(createExportableNodeSet(node.nodes, exportedIds, exportedSubflows, exportedConfigNodes));
|
||||
}
|
||||
} else {
|
||||
var convertedSubflow = convertSubflow(node);
|
||||
nns.push(convertedSubflow);
|
||||
@@ -773,12 +621,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
for (i in subflows) {
|
||||
if (subflows.hasOwnProperty(i)) {
|
||||
nns.push(convertSubflow(subflows[i], exportCredentials));
|
||||
}
|
||||
}
|
||||
for (i in groups) {
|
||||
if (groups.hasOwnProperty(i)) {
|
||||
nns.push(convertNode(groups[i]));
|
||||
nns.push(convertSubflow(subflows[i]));
|
||||
}
|
||||
}
|
||||
for (i in configNodes) {
|
||||
@@ -794,39 +637,42 @@ RED.nodes = (function() {
|
||||
}
|
||||
|
||||
function checkForMatchingSubflow(subflow,subflowNodes) {
|
||||
subflowNodes = subflowNodes || [];
|
||||
var i;
|
||||
var match = null;
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
if (sf.name != subflow.name ||
|
||||
sf.info != subflow.info ||
|
||||
sf.in.length != subflow.in.length ||
|
||||
sf.out.length != subflow.out.length) {
|
||||
try {
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
if (sf.name != subflow.name ||
|
||||
sf.info != subflow.info ||
|
||||
sf.in.length != subflow.in.length ||
|
||||
sf.out.length != subflow.out.length) {
|
||||
return;
|
||||
}
|
||||
var sfNodes = RED.nodes.filterNodes({z:sf.id});
|
||||
if (sfNodes.length != subflowNodes.length) {
|
||||
return;
|
||||
}
|
||||
var sfNodes = RED.nodes.filterNodes({z:sf.id});
|
||||
if (sfNodes.length != subflowNodes.length) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var subflowNodeSet = [subflow].concat(subflowNodes);
|
||||
var sfNodeSet = [sf].concat(sfNodes);
|
||||
var subflowNodeSet = [subflow].concat(subflowNodes);
|
||||
var sfNodeSet = [sf].concat(sfNodes);
|
||||
|
||||
var exportableSubflowNodes = JSON.stringify(subflowNodeSet);
|
||||
var exportableSFNodes = JSON.stringify(createExportableNodeSet(sfNodeSet));
|
||||
var nodeMap = {};
|
||||
for (i=0;i<sfNodes.length;i++) {
|
||||
exportableSubflowNodes = exportableSubflowNodes.replace(new RegExp("\""+subflowNodes[i].id+"\"","g"),'"'+sfNodes[i].id+'"');
|
||||
}
|
||||
exportableSubflowNodes = exportableSubflowNodes.replace(new RegExp("\""+subflow.id+"\"","g"),'"'+sf.id+'"');
|
||||
var exportableSubflowNodes = JSON.stringify(subflowNodeSet);
|
||||
var exportableSFNodes = JSON.stringify(createExportableNodeSet(sfNodeSet));
|
||||
var nodeMap = {};
|
||||
for (i=0;i<sfNodes.length;i++) {
|
||||
exportableSubflowNodes = exportableSubflowNodes.replace(new RegExp("\""+subflowNodes[i].id+"\"","g"),'"'+sfNodes[i].id+'"');
|
||||
}
|
||||
exportableSubflowNodes = exportableSubflowNodes.replace(new RegExp("\""+subflow.id+"\"","g"),'"'+sf.id+'"');
|
||||
|
||||
if (exportableSubflowNodes !== exportableSFNodes) {
|
||||
return;
|
||||
}
|
||||
if (exportableSubflowNodes !== exportableSFNodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
match = sf;
|
||||
return false;
|
||||
});
|
||||
match = sf;
|
||||
throw new Error();
|
||||
});
|
||||
} catch(err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
function compareNodes(nodeA,nodeB,idMustMatch) {
|
||||
@@ -881,20 +727,6 @@ RED.nodes = (function() {
|
||||
if (!$.isArray(newNodes)) {
|
||||
newNodes = [newNodes];
|
||||
}
|
||||
|
||||
// Scan for any duplicate nodes and remove them. This is a temporary
|
||||
// fix to help resolve corrupted flows caused by 0.20.0 where multiple
|
||||
// copies of the flow would get loaded at the same time.
|
||||
// If the user hit deploy they would have saved those duplicates.
|
||||
var seenIds = {};
|
||||
newNodes = newNodes.filter(function(n) {
|
||||
if (seenIds[n.id]) {
|
||||
return false;
|
||||
}
|
||||
seenIds[n.id] = true;
|
||||
return true;
|
||||
})
|
||||
|
||||
var isInitialLoad = false;
|
||||
if (!initialLoad) {
|
||||
isInitialLoad = true;
|
||||
@@ -907,7 +739,6 @@ RED.nodes = (function() {
|
||||
if (n.type != "workspace" &&
|
||||
n.type != "tab" &&
|
||||
n.type != "subflow" &&
|
||||
n.type != "group" &&
|
||||
!registry.getNodeType(n.type) &&
|
||||
n.type.substring(0,8) != "subflow:" &&
|
||||
unknownTypes.indexOf(n.type)==-1) {
|
||||
@@ -921,7 +752,8 @@ RED.nodes = (function() {
|
||||
}
|
||||
if (!isInitialLoad && unknownTypes.length > 0) {
|
||||
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
|
||||
RED.notify("<p>"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+"</p>"+typeList,"error",false,10000);
|
||||
var type = "type"+(unknownTypes.length > 1?"s":"");
|
||||
RED.notify("<strong>"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+"</strong>"+typeList,"error",false,10000);
|
||||
}
|
||||
|
||||
var activeWorkspace = RED.workspaces.active();
|
||||
@@ -931,7 +763,7 @@ RED.nodes = (function() {
|
||||
var m = /^subflow:(.+)$/.exec(newNodes[i].type);
|
||||
if (m) {
|
||||
var subflowId = m[1];
|
||||
var parent = getSubflow(activeWorkspace);
|
||||
var parent = getSubflow(newNodes[i].z || activeWorkspace);
|
||||
if (parent) {
|
||||
var err;
|
||||
if (subflowId === parent.id) {
|
||||
@@ -957,7 +789,6 @@ RED.nodes = (function() {
|
||||
var node_map = {};
|
||||
var new_nodes = [];
|
||||
var new_links = [];
|
||||
var new_groups = [];
|
||||
var nid;
|
||||
var def;
|
||||
var configNode;
|
||||
@@ -1008,12 +839,6 @@ RED.nodes = (function() {
|
||||
output.i = i;
|
||||
output.id = getID();
|
||||
});
|
||||
if (n.status) {
|
||||
n.status.type = "subflow";
|
||||
n.status.direction = "status";
|
||||
n.status.z = n.id;
|
||||
n.status.id = getID();
|
||||
}
|
||||
new_subflows.push(n);
|
||||
addSubflow(n,createNewIds);
|
||||
}
|
||||
@@ -1076,17 +901,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
|
||||
if (!existingConfigNode || existingConfigNode._def.exclusive) { //} || !compareNodes(existingConfigNode,n,true) || existingConfigNode.z !== n.z) {
|
||||
configNode = {
|
||||
id:n.id,
|
||||
z:n.z,
|
||||
type:n.type,
|
||||
info: n.info,
|
||||
users:[],
|
||||
_config:{}
|
||||
};
|
||||
if (n.hasOwnProperty('d')) {
|
||||
configNode.d = n.d;
|
||||
}
|
||||
configNode = {id:n.id, z:n.z, type:n.type, users:[], _config:{}};
|
||||
for (d in def.defaults) {
|
||||
if (def.defaults.hasOwnProperty(d)) {
|
||||
configNode[d] = n[d];
|
||||
@@ -1121,29 +936,17 @@ RED.nodes = (function() {
|
||||
def = registry.getNodeType(n.type);
|
||||
if (!def || def.category != "config") {
|
||||
var node = {
|
||||
x:parseFloat(n.x || 0),
|
||||
y:parseFloat(n.y || 0),
|
||||
x:n.x,
|
||||
y:n.y,
|
||||
z:n.z,
|
||||
type:0,
|
||||
info: n.info,
|
||||
wires:n.wires,
|
||||
inputLabels: n.inputLabels,
|
||||
outputLabels: n.outputLabels,
|
||||
icon: n.icon,
|
||||
changed:false,
|
||||
_config:{}
|
||||
}
|
||||
if (n.type !== "group") {
|
||||
node.wires = n.wires||[];
|
||||
node.inputLabels = n.inputLabels;
|
||||
node.outputLabels = n.outputLabels;
|
||||
node.icon = n.icon;
|
||||
}
|
||||
if (n.hasOwnProperty('l')) {
|
||||
node.l = n.l;
|
||||
}
|
||||
if (n.hasOwnProperty('d')) {
|
||||
node.d = n.d;
|
||||
}
|
||||
if (n.hasOwnProperty('g')) {
|
||||
node.g = n.g;
|
||||
}
|
||||
};
|
||||
if (createNewIds) {
|
||||
if (subflow_blacklist[n.z]) {
|
||||
continue;
|
||||
@@ -1180,17 +983,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
node.type = n.type;
|
||||
node._def = def;
|
||||
if (node.type === "group") {
|
||||
node._def = RED.group.def;
|
||||
for (d in node._def.defaults) {
|
||||
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
|
||||
node[d] = n[d];
|
||||
node._config[d] = JSON.stringify(n[d]);
|
||||
}
|
||||
}
|
||||
node._config.x = node.x;
|
||||
node._config.y = node.y;
|
||||
} else if (n.type.substring(0,7) === "subflow") {
|
||||
if (n.type.substring(0,7) === "subflow") {
|
||||
var parentId = n.type.split(":")[1];
|
||||
var subflow = subflow_blacklist[parentId]||subflow_map[parentId]||getSubflow(parentId);
|
||||
if (createNewIds) {
|
||||
@@ -1202,7 +995,6 @@ RED.nodes = (function() {
|
||||
node.name = n.name;
|
||||
node.outputs = subflow.out.length;
|
||||
node.inputs = subflow.in.length;
|
||||
node.env = n.env;
|
||||
} else {
|
||||
if (!node._def) {
|
||||
if (node.x && node.y) {
|
||||
@@ -1210,7 +1002,7 @@ RED.nodes = (function() {
|
||||
color:"#fee",
|
||||
defaults: {},
|
||||
label: "unknown: "+n.type,
|
||||
labelStyle: "red-ui-flow-node-label-italic",
|
||||
labelStyle: "node_label_italic",
|
||||
outputs: n.outputs||n.wires.length,
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
}
|
||||
@@ -1220,13 +1012,6 @@ RED.nodes = (function() {
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
node.users = [];
|
||||
// This is a config node, so delete the default
|
||||
// non-config node properties
|
||||
delete node.x;
|
||||
delete node.y;
|
||||
delete node.wires;
|
||||
delete node.inputLabels;
|
||||
delete node.outputLabels;
|
||||
}
|
||||
var orig = {};
|
||||
for (var p in n) {
|
||||
@@ -1239,31 +1024,10 @@ RED.nodes = (function() {
|
||||
node.type = "unknown";
|
||||
}
|
||||
if (node._def.category != "config") {
|
||||
if (n.hasOwnProperty('inputs')) {
|
||||
node.inputs = n.inputs;
|
||||
node._config.inputs = JSON.stringify(n.inputs);
|
||||
} else {
|
||||
node.inputs = node._def.inputs;
|
||||
}
|
||||
if (n.hasOwnProperty('outputs')) {
|
||||
node.outputs = n.outputs;
|
||||
node._config.outputs = JSON.stringify(n.outputs);
|
||||
} else {
|
||||
node.outputs = node._def.outputs;
|
||||
}
|
||||
if (node.hasOwnProperty('wires') && node.wires.length > node.outputs) {
|
||||
if (!node._def.defaults.hasOwnProperty("outputs") || !isNaN(parseInt(n.outputs))) {
|
||||
// If 'wires' is longer than outputs, clip wires
|
||||
console.log("Warning: node.wires longer than node.outputs - trimming wires:",node.id," wires:",node.wires.length," outputs:",node.outputs);
|
||||
node.wires = node.wires.slice(0,node.outputs);
|
||||
} else {
|
||||
// The node declares outputs in its defaults, but has not got a valid value
|
||||
// Defer to the length of the wires array
|
||||
node.outputs = node.wires.length;
|
||||
}
|
||||
}
|
||||
node.inputs = n.inputs||node._def.inputs;
|
||||
node.outputs = n.outputs||node._def.outputs;
|
||||
for (d in node._def.defaults) {
|
||||
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
|
||||
if (node._def.defaults.hasOwnProperty(d)) {
|
||||
node[d] = n[d];
|
||||
node._config[d] = JSON.stringify(n[d]);
|
||||
}
|
||||
@@ -1280,19 +1044,11 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.type !== "group") {
|
||||
addNode(node);
|
||||
RED.editor.validateNode(node);
|
||||
} else {
|
||||
addGroup(node);
|
||||
}
|
||||
addNode(node);
|
||||
RED.editor.validateNode(node);
|
||||
node_map[n.id] = node;
|
||||
// If an 'unknown' config node, it will not have been caught by the
|
||||
// proper config node handling, so needs adding to new_nodes here
|
||||
if (node.type === "unknown" || node._def.category !== "config") {
|
||||
if (node._def.category != "config") {
|
||||
new_nodes.push(node);
|
||||
} else if (node.type === "group") {
|
||||
new_groups.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1302,7 +1058,6 @@ RED.nodes = (function() {
|
||||
var nodeTypeArrayReferences = {
|
||||
"catch":"scope",
|
||||
"status":"scope",
|
||||
"complete": "scope",
|
||||
"link in":"links",
|
||||
"link out":"links"
|
||||
}
|
||||
@@ -1327,11 +1082,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
delete n.wires;
|
||||
}
|
||||
if (n.g && node_map[n.g]) {
|
||||
n.g = node_map[n.g].id;
|
||||
} else {
|
||||
delete n.g
|
||||
}
|
||||
for (var d3 in n._def.defaults) {
|
||||
if (n._def.defaults.hasOwnProperty(d3)) {
|
||||
if (n._def.defaults[d3].type && node_map[n[d3]]) {
|
||||
@@ -1386,55 +1136,22 @@ RED.nodes = (function() {
|
||||
});
|
||||
delete output.wires;
|
||||
});
|
||||
if (n.status) {
|
||||
n.status.wires.forEach(function(wire) {
|
||||
var link;
|
||||
if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) {
|
||||
link = {source:n.in[wire.port], sourcePort:wire.port,target:n.status};
|
||||
} else {
|
||||
link = {source:node_map[wire.id]||subflow_map[wire.id], sourcePort:wire.port,target:n.status};
|
||||
}
|
||||
addLink(link);
|
||||
new_links.push(link);
|
||||
});
|
||||
delete n.status.wires;
|
||||
}
|
||||
}
|
||||
for (i=0;i<new_groups.length;i++) {
|
||||
n = new_groups[i];
|
||||
if (n.g && node_map[n.g]) {
|
||||
n.g = node_map[n.g].id;
|
||||
} else {
|
||||
delete n.g;
|
||||
}
|
||||
n.nodes = n.nodes.map(function(id) {
|
||||
return node_map[id];
|
||||
})
|
||||
}
|
||||
|
||||
RED.workspaces.refresh();
|
||||
return [new_nodes,new_links,new_groups,new_workspaces,new_subflows,missingWorkspace];
|
||||
return [new_nodes,new_links,new_workspaces,new_subflows,missingWorkspace];
|
||||
}
|
||||
|
||||
// TODO: supports filter.z|type
|
||||
function filterNodes(filter) {
|
||||
var result = [];
|
||||
var searchSet = nodes;
|
||||
var doZFilter = false;
|
||||
if (filter.hasOwnProperty("z")) {
|
||||
if (Object.hasOwnProperty("values") && nodeTabMap.hasOwnProperty(filter.z) ) {
|
||||
searchSet = Object.values(nodeTabMap[filter.z]);
|
||||
} else {
|
||||
doZFilter = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (var n=0;n<searchSet.length;n++) {
|
||||
var node = searchSet[n];
|
||||
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
|
||||
for (var n=0;n<nodes.length;n++) {
|
||||
var node = nodes[n];
|
||||
if (filter.hasOwnProperty("z") && node.z !== filter.z) {
|
||||
continue;
|
||||
}
|
||||
if (doZFilter && node.z !== filter.z) {
|
||||
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
|
||||
continue;
|
||||
}
|
||||
result.push(node);
|
||||
@@ -1501,12 +1218,8 @@ RED.nodes = (function() {
|
||||
function clear() {
|
||||
nodes = [];
|
||||
links = [];
|
||||
nodeTabMap = {};
|
||||
configNodes = {};
|
||||
workspacesOrder = [];
|
||||
groups = {};
|
||||
groupsByZ = {};
|
||||
|
||||
var subflowIds = Object.keys(subflows);
|
||||
subflowIds.forEach(function(id) {
|
||||
RED.subflow.removeSubflow(id)
|
||||
@@ -1535,73 +1248,34 @@ RED.nodes = (function() {
|
||||
// var loadedFlowVersion = null;
|
||||
}
|
||||
|
||||
function addGroup(group) {
|
||||
groupsByZ[group.z] = groupsByZ[group.z] || [];
|
||||
groupsByZ[group.z].push(group);
|
||||
groups[group.id] = group;
|
||||
}
|
||||
function removeGroup(group) {
|
||||
var i = groupsByZ[group.z].indexOf(group);
|
||||
groupsByZ[group.z].splice(i,1);
|
||||
|
||||
if (group.g) {
|
||||
if (groups[group.g]) {
|
||||
var index = groups[group.g].nodes.indexOf(group);
|
||||
groups[group.g].nodes.splice(index,1);
|
||||
}
|
||||
}
|
||||
RED.group.markDirty(group);
|
||||
|
||||
delete groups[group.id];
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
RED.events.on("registry:node-type-added",function(type) {
|
||||
var def = registry.getNodeType(type);
|
||||
var replaced = false;
|
||||
var replaceNodes = {};
|
||||
var replaceNodes = [];
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type === "unknown" && n.name === type) {
|
||||
replaceNodes[n.id] = n;
|
||||
replaceNodes.push(n);
|
||||
}
|
||||
});
|
||||
RED.nodes.eachConfig(function(n) {
|
||||
if (n.type === "unknown" && n.name === type) {
|
||||
replaceNodes[n.id] = n;
|
||||
replaceNodes.push(n);
|
||||
}
|
||||
});
|
||||
|
||||
var replaceNodeIds = Object.keys(replaceNodes);
|
||||
if (replaceNodeIds.length > 0) {
|
||||
if (replaceNodes.length > 0) {
|
||||
var reimportList = [];
|
||||
replaceNodeIds.forEach(function(id) {
|
||||
var n = replaceNodes[id];
|
||||
replaceNodes.forEach(function(n) {
|
||||
if (configNodes.hasOwnProperty(n.id)) {
|
||||
delete configNodes[n.id];
|
||||
} else {
|
||||
nodes.splice(nodes.indexOf(n),1);
|
||||
if (nodeTabMap[n.z]) {
|
||||
delete nodeTabMap[n.z][n.id];
|
||||
}
|
||||
}
|
||||
reimportList.push(convertNode(n));
|
||||
});
|
||||
|
||||
// Remove any links between nodes that are going to be reimported.
|
||||
// This prevents a duplicate link from being added.
|
||||
var removeLinks = [];
|
||||
RED.nodes.eachLink(function(l) {
|
||||
if (replaceNodes.hasOwnProperty(l.source.id) && replaceNodes.hasOwnProperty(l.target.id)) {
|
||||
removeLinks.push(l);
|
||||
}
|
||||
});
|
||||
removeLinks.forEach(removeLink);
|
||||
|
||||
// Force the redraw to be synchronous so the view updates
|
||||
// *now* and removes the unknown node
|
||||
RED.view.redraw(true, true);
|
||||
RED.view.redraw(true);
|
||||
var result = importNodes(reimportList,false);
|
||||
var newNodeMap = {};
|
||||
result[0].forEach(function(n) {
|
||||
@@ -1639,8 +1313,6 @@ RED.nodes = (function() {
|
||||
remove: removeNode,
|
||||
clear: clear,
|
||||
|
||||
moveNodeToTab: moveNodeToTab,
|
||||
|
||||
addLink: addLink,
|
||||
removeLink: removeLink,
|
||||
|
||||
@@ -1655,48 +1327,33 @@ RED.nodes = (function() {
|
||||
subflow: getSubflow,
|
||||
subflowContains: subflowContains,
|
||||
|
||||
addGroup: addGroup,
|
||||
removeGroup: removeGroup,
|
||||
group: function(id) { return groups[id] },
|
||||
groups: function(z) { return groupsByZ[z]||[] },
|
||||
|
||||
eachNode: function(cb) {
|
||||
for (var n=0;n<nodes.length;n++) {
|
||||
if (cb(nodes[n]) === false) {
|
||||
break;
|
||||
}
|
||||
cb(nodes[n]);
|
||||
}
|
||||
},
|
||||
eachLink: function(cb) {
|
||||
for (var l=0;l<links.length;l++) {
|
||||
if (cb(links[l]) === false) {
|
||||
break;
|
||||
}
|
||||
cb(links[l]);
|
||||
}
|
||||
},
|
||||
eachConfig: function(cb) {
|
||||
for (var id in configNodes) {
|
||||
if (configNodes.hasOwnProperty(id)) {
|
||||
if (cb(configNodes[id]) === false) {
|
||||
break;
|
||||
}
|
||||
cb(configNodes[id]);
|
||||
}
|
||||
}
|
||||
},
|
||||
eachSubflow: function(cb) {
|
||||
for (var id in subflows) {
|
||||
if (subflows.hasOwnProperty(id)) {
|
||||
if (cb(subflows[id]) === false) {
|
||||
break;
|
||||
}
|
||||
cb(subflows[id]);
|
||||
}
|
||||
}
|
||||
},
|
||||
eachWorkspace: function(cb) {
|
||||
for (var i=0;i<workspacesOrder.length;i++) {
|
||||
if (cb(workspaces[workspacesOrder[i]]) === false) {
|
||||
break;
|
||||
}
|
||||
cb(workspaces[workspacesOrder[i]]);
|
||||
}
|
||||
},
|
||||
|
@@ -13,5 +13,4 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = false
|
||||
var RED = {};
|
@@ -37,7 +37,7 @@ RED.settings = (function () {
|
||||
if (key === "auth-tokens") {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} else {
|
||||
RED.utils.setMessageProperty(userSettings,key,value);
|
||||
userSettings[key] = value;
|
||||
saveUserSettings();
|
||||
}
|
||||
};
|
||||
@@ -46,26 +46,16 @@ RED.settings = (function () {
|
||||
* If the key is not set in the localStorage it returns <i>undefined</i>
|
||||
* Else return the JSON parsed value
|
||||
* @param key
|
||||
* @param defaultIfUndefined
|
||||
* @returns {*}
|
||||
*/
|
||||
var get = function (key,defaultIfUndefined) {
|
||||
var get = function (key) {
|
||||
if (!hasLocalStorage()) {
|
||||
return undefined;
|
||||
}
|
||||
if (key === "auth-tokens") {
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
} else {
|
||||
var v;
|
||||
try {
|
||||
v = RED.utils.getMessageProperty(userSettings,key);
|
||||
if (v === undefined) {
|
||||
v = defaultIfUndefined;
|
||||
}
|
||||
} catch(err) {
|
||||
v = defaultIfUndefined;
|
||||
}
|
||||
return v;
|
||||
return userSettings[key];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,22 +89,18 @@ RED.settings = (function () {
|
||||
userSettings = data;
|
||||
}
|
||||
|
||||
var init = function (options, done) {
|
||||
var init = function (done) {
|
||||
var accessTokenMatch = /[?&]access_token=(.*?)(?:$|&)/.exec(window.location.search);
|
||||
if (accessTokenMatch) {
|
||||
var accessToken = accessTokenMatch[1];
|
||||
RED.settings.set("auth-tokens",{access_token: accessToken});
|
||||
window.location.search = "";
|
||||
}
|
||||
RED.settings.apiRootUrl = options.apiRootUrl;
|
||||
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(jqXHR,settings) {
|
||||
// Only attach auth header for requests to relative paths
|
||||
if (!/^\s*(https?:|\/|\.)/.test(settings.url)) {
|
||||
if (options.apiRootUrl) {
|
||||
settings.url = options.apiRootUrl+settings.url;
|
||||
}
|
||||
var auth_tokens = RED.settings.get("auth-tokens");
|
||||
if (auth_tokens) {
|
||||
jqXHR.setRequestHeader("Authorization","Bearer "+auth_tokens.access_token);
|
||||
@@ -141,12 +127,6 @@ RED.settings = (function () {
|
||||
RED.settings.remove("auth-tokens");
|
||||
}
|
||||
console.log("Node-RED: " + data.version);
|
||||
console.groupCollapsed("Versions");
|
||||
console.log("jQuery",$().jquery)
|
||||
console.log("jQuery UI",$.ui.version);
|
||||
console.log("ACE",ace.version);
|
||||
console.log("D3",d3.version);
|
||||
console.groupEnd();
|
||||
loadUserSettings(done);
|
||||
},
|
||||
error: function(jqXHR,textStatus,errorThrown) {
|
@@ -97,14 +97,14 @@ RED.text.bidi = (function() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces the text direction for all the spans with style red-ui-text-bidi-aware under
|
||||
* Enforces the text direction for all the spans with style bidiAware under
|
||||
* workspace or sidebar div
|
||||
*/
|
||||
function enforceTextDirectionOnPage() {
|
||||
$("#red-ui-workspace").find('span.red-ui-text-bidi-aware').each(function() {
|
||||
$("#workspace").find('span.bidiAware').each(function() {
|
||||
$(this).attr("dir", resolveBaseTextDir($(this).html()));
|
||||
});
|
||||
$("#red-ui-sidebar").find('span.red-ui-text-bidi-aware').each(function() {
|
||||
$("#sidebar").find('span.bidiAware').each(function() {
|
||||
$(this).attr("dir", resolveBaseTextDir($(this).text()));
|
||||
});
|
||||
}
|
@@ -1242,7 +1242,7 @@ RED.text.format = (function() {
|
||||
element.dispatchEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var range = selection.getRangeAt(0);
|
||||
var tempRange = range.cloneRange(), startNode, startOffset;
|
||||
startNode = range.startContainer;
|
||||
@@ -1304,7 +1304,7 @@ RED.text.format = (function() {
|
||||
}
|
||||
|
||||
return {
|
||||
/*!
|
||||
/**
|
||||
* Returns the HTML representation of a given structured text
|
||||
* @param text - the structured text
|
||||
* @param type - could be one of filepath, url, email
|
||||
@@ -1315,7 +1315,7 @@ RED.text.format = (function() {
|
||||
getHtml: function (text, type, args, isRtl, locale) {
|
||||
return getHandler(type).format(text, args, isRtl, true, locale);
|
||||
},
|
||||
/*!
|
||||
/**
|
||||
* Handle Structured text correct display for a given HTML element.
|
||||
* @param element - the element : should be of type div contenteditable=true
|
||||
* @param type - could be one of filepath, url, email
|
@@ -12,9 +12,9 @@ RED.actions = (function() {
|
||||
function getAction(name) {
|
||||
return actions[name];
|
||||
}
|
||||
function invokeAction(name,args) {
|
||||
function invokeAction(name) {
|
||||
if (actions.hasOwnProperty(name)) {
|
||||
actions[name](args);
|
||||
actions[name]();
|
||||
}
|
||||
}
|
||||
function listActions() {
|
380
editor/js/ui/clipboard.js
Normal file
@@ -0,0 +1,380 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
RED.clipboard = (function() {
|
||||
|
||||
var dialog;
|
||||
var dialogContainer;
|
||||
var exportNodesDialog;
|
||||
var importNodesDialog;
|
||||
var disabled = false;
|
||||
|
||||
function setupDialogs() {
|
||||
dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>')
|
||||
.appendTo("body")
|
||||
.dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 500,
|
||||
resizable: false,
|
||||
buttons: [
|
||||
{
|
||||
id: "clipboard-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-close",
|
||||
class: "primary",
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-copy",
|
||||
class: "primary",
|
||||
text: RED._("clipboard.export.copy"),
|
||||
click: function() {
|
||||
$("#clipboard-export").select();
|
||||
document.execCommand("copy");
|
||||
document.getSelection().removeAllRanges();
|
||||
RED.notify(RED._("clipboard.nodesExported"));
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-ok",
|
||||
class: "primary",
|
||||
text: RED._("common.label.import"),
|
||||
click: function() {
|
||||
RED.view.importNodes($("#clipboard-import").val(),$("#import-tab > a.selected").attr('id') === 'import-tab-new');
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
},
|
||||
close: function(e) {
|
||||
}
|
||||
});
|
||||
|
||||
dialogContainer = dialog.children(".dialog-form");
|
||||
|
||||
exportNodesDialog =
|
||||
'<div class="form-row">'+
|
||||
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.export.copy"></label>'+
|
||||
'<span id="export-range-group" class="button-group">'+
|
||||
'<a id="export-range-selected" class="editor-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
|
||||
'<a id="export-range-flow" class="editor-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
|
||||
'<a id="export-range-full" class="editor-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<textarea readonly style="resize: none; width: 100%; border-radius: 4px;font-family: monospace; font-size: 12px; background:#f3f3f3; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" style="text-align: right;">'+
|
||||
'<span id="export-format-group" class="button-group">'+
|
||||
'<a id="export-format-mini" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
||||
'<a id="export-format-full" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
||||
'</span>'+
|
||||
'</div>';
|
||||
|
||||
importNodesDialog = '<div class="form-row">'+
|
||||
'<textarea style="resize: none; width: 100%; border-radius: 0px;font-family: monospace; font-size: 12px; background:#eee; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-import" rows="5" placeholder="'+
|
||||
RED._("clipboard.pasteNodes")+
|
||||
'"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.import.import"></label>'+
|
||||
'<span id="import-tab" class="button-group">'+
|
||||
'<a id="import-tab-current" class="editor-button toggle selected" href="#" data-i18n="clipboard.export.current"></a>'+
|
||||
'<a id="import-tab-new" class="editor-button toggle" href="#" data-i18n="clipboard.import.newFlow"></a>'+
|
||||
'</span>'+
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function validateImport() {
|
||||
var importInput = $("#clipboard-import");
|
||||
var v = importInput.val();
|
||||
v = v.substring(v.indexOf('['),v.lastIndexOf(']')+1);
|
||||
try {
|
||||
JSON.parse(v);
|
||||
importInput.removeClass("input-error");
|
||||
importInput.val(v);
|
||||
$("#clipboard-dialog-ok").button("enable");
|
||||
} catch(err) {
|
||||
if (v !== "") {
|
||||
importInput.addClass("input-error");
|
||||
}
|
||||
$("#clipboard-dialog-ok").button("disable");
|
||||
}
|
||||
}
|
||||
|
||||
function importNodes() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(importNodesDialog));
|
||||
dialogContainer.i18n();
|
||||
|
||||
$("#clipboard-dialog-ok").show();
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-close").hide();
|
||||
$("#clipboard-dialog-copy").hide();
|
||||
$("#clipboard-dialog-ok").button("disable");
|
||||
$("#clipboard-import").keyup(validateImport);
|
||||
$("#clipboard-import").on('paste',function() { setTimeout(validateImport,10)});
|
||||
|
||||
$("#import-tab > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
|
||||
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
|
||||
}
|
||||
|
||||
function exportNodes() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(exportNodesDialog));
|
||||
dialogContainer.i18n();
|
||||
var format = RED.settings.flowFilePretty ? "export-format-full" : "export-format-mini";
|
||||
|
||||
$("#export-format-group > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
$("#clipboard-export").focus();
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
|
||||
var flow = $("#clipboard-export").val();
|
||||
if (flow.length > 0) {
|
||||
var nodes = JSON.parse(flow);
|
||||
|
||||
format = $(this).attr('id');
|
||||
if (format === 'export-format-full') {
|
||||
flow = JSON.stringify(nodes,null,4);
|
||||
} else {
|
||||
flow = JSON.stringify(nodes);
|
||||
}
|
||||
$("#clipboard-export").val(flow);
|
||||
$("#clipboard-export").focus();
|
||||
}
|
||||
});
|
||||
|
||||
$("#export-range-group > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
$("#clipboard-export").focus();
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
var type = $(this).attr('id');
|
||||
var flow = "";
|
||||
var nodes = null;
|
||||
if (type === 'export-range-selected') {
|
||||
var selection = RED.view.selection();
|
||||
// Don't include the subflow meta-port nodes in the exported selection
|
||||
nodes = RED.nodes.createExportableNodeSet(selection.nodes.filter(function(n) { return n.type !== 'subflow'}));
|
||||
} else if (type === 'export-range-flow') {
|
||||
var activeWorkspace = RED.workspaces.active();
|
||||
nodes = RED.nodes.filterNodes({z:activeWorkspace});
|
||||
var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
|
||||
nodes.unshift(parentNode);
|
||||
nodes = RED.nodes.createExportableNodeSet(nodes);
|
||||
} else if (type === 'export-range-full') {
|
||||
nodes = RED.nodes.createCompleteNodeSet(false);
|
||||
}
|
||||
if (nodes !== null) {
|
||||
if (format === "export-format-full") {
|
||||
flow = JSON.stringify(nodes,null,4);
|
||||
} else {
|
||||
flow = JSON.stringify(nodes);
|
||||
}
|
||||
}
|
||||
if (flow.length > 0) {
|
||||
$("#export-copy").removeClass('disabled');
|
||||
} else {
|
||||
$("#export-copy").addClass('disabled');
|
||||
}
|
||||
$("#clipboard-export").val(flow);
|
||||
$("#clipboard-export").focus();
|
||||
})
|
||||
|
||||
$("#clipboard-dialog-ok").hide();
|
||||
$("#clipboard-dialog-cancel").hide();
|
||||
$("#clipboard-dialog-copy").hide();
|
||||
$("#clipboard-dialog-close").hide();
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
$("#export-range-selected").click();
|
||||
} else {
|
||||
$("#export-range-selected").addClass('disabled').removeClass('selected');
|
||||
$("#export-range-flow").click();
|
||||
}
|
||||
if (format === "export-format-full") {
|
||||
$("#export-format-full").click();
|
||||
} else {
|
||||
$("#export-format-mini").click();
|
||||
}
|
||||
$("#clipboard-export")
|
||||
.focus(function() {
|
||||
var textarea = $(this);
|
||||
textarea.select();
|
||||
textarea.mouseup(function() {
|
||||
textarea.unbind("mouseup");
|
||||
return false;
|
||||
})
|
||||
});
|
||||
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
|
||||
|
||||
$("#clipboard-export").focus();
|
||||
if (!document.queryCommandSupported("copy")) {
|
||||
$("#clipboard-dialog-cancel").hide();
|
||||
$("#clipboard-dialog-close").show();
|
||||
} else {
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-copy").show();
|
||||
}
|
||||
}
|
||||
|
||||
function hideDropTarget() {
|
||||
$("#dropTarget").hide();
|
||||
RED.keyboard.remove("escape");
|
||||
}
|
||||
function copyText(value,element,msg) {
|
||||
var truncated = false;
|
||||
if (typeof value !== "string" ) {
|
||||
value = JSON.stringify(value, function(key,value) {
|
||||
if (value !== null && typeof value === 'object') {
|
||||
if (value.__encoded__ && value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
|
||||
truncated = value.data.length !== value.length;
|
||||
return value.data;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
if (truncated) {
|
||||
msg += "_truncated";
|
||||
}
|
||||
$("#clipboard-hidden").val(value).select();
|
||||
var result = document.execCommand("copy");
|
||||
if (result && element) {
|
||||
var popover = RED.popover.create({
|
||||
target: element,
|
||||
direction: 'left',
|
||||
size: 'small',
|
||||
content: RED._(msg)
|
||||
});
|
||||
setTimeout(function() {
|
||||
popover.close();
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
init: function() {
|
||||
setupDialogs();
|
||||
|
||||
$('<input type="text" id="clipboard-hidden">').appendTo("body");
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
if (!selection.nodes) {
|
||||
RED.menu.setDisabled("menu-item-export",true);
|
||||
RED.menu.setDisabled("menu-item-export-clipboard",true);
|
||||
RED.menu.setDisabled("menu-item-export-library",true);
|
||||
} else {
|
||||
RED.menu.setDisabled("menu-item-export",false);
|
||||
RED.menu.setDisabled("menu-item-export-clipboard",false);
|
||||
RED.menu.setDisabled("menu-item-export-library",false);
|
||||
}
|
||||
});
|
||||
|
||||
RED.actions.add("core:show-export-dialog",exportNodes);
|
||||
RED.actions.add("core:show-import-dialog",importNodes);
|
||||
|
||||
|
||||
RED.events.on("editor:open",function() { disabled = true; });
|
||||
RED.events.on("editor:close",function() { disabled = false; });
|
||||
RED.events.on("search:open",function() { disabled = true; });
|
||||
RED.events.on("search:close",function() { disabled = false; });
|
||||
RED.events.on("type-search:open",function() { disabled = true; });
|
||||
RED.events.on("type-search:close",function() { disabled = false; });
|
||||
|
||||
|
||||
$('#chart').on("dragenter",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
$("#dropTarget").css({display:'table'});
|
||||
RED.keyboard.add("*", "escape" ,hideDropTarget);
|
||||
}
|
||||
});
|
||||
|
||||
$('#dropTarget').on("dragover",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
.on("dragleave",function(event) {
|
||||
hideDropTarget();
|
||||
})
|
||||
.on("drop",function(event) {
|
||||
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);
|
||||
RED.view.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) {
|
||||
RED.view.importNodes(e.target.result);
|
||||
};
|
||||
})(file);
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
hideDropTarget();
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
},
|
||||
import: importNodes,
|
||||
export: exportNodes,
|
||||
copyText: copyText
|
||||
}
|
||||
})();
|
@@ -38,7 +38,7 @@
|
||||
this.options[0].show();
|
||||
}
|
||||
|
||||
this.element.on("change", function() {
|
||||
this.element.change(function() {
|
||||
if (this.checked) {
|
||||
that.options[0].hide();
|
||||
that.options[1].show();
|
||||
@@ -53,7 +53,7 @@
|
||||
child.checkboxSet('state',isChecked,false,true);
|
||||
})
|
||||
})
|
||||
this.uiElement.on("click", function(e) {
|
||||
this.uiElement.click(function(e) {
|
||||
e.stopPropagation();
|
||||
// state returns null for a partial state. Clicking on that should
|
||||
// result in false.
|
@@ -32,10 +32,7 @@
|
||||
* - scrollOnAdd : boolean - whether to scroll to newly added items
|
||||
* methods:
|
||||
* - addItem(itemData)
|
||||
* - insertItemAt : function(data,index) - add an item at the specified index
|
||||
* - removeItem(itemData)
|
||||
* - getItemAt(index)
|
||||
* - indexOf(itemData)
|
||||
* - width(width)
|
||||
* - height(height)
|
||||
* - items()
|
||||
@@ -78,9 +75,9 @@
|
||||
addLabel = 'add';
|
||||
}
|
||||
}
|
||||
$('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>')
|
||||
$('<a href="#" class="editor-button editor-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>')
|
||||
.appendTo(this.topContainer)
|
||||
.on("click", function(evt) {
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
that.addItem({});
|
||||
});
|
||||
@@ -188,11 +185,6 @@
|
||||
}
|
||||
},
|
||||
_destroy: function() {
|
||||
if (this.topContainer) {
|
||||
var tc = this.topContainer;
|
||||
delete this.topContainer;
|
||||
tc.remove();
|
||||
}
|
||||
},
|
||||
_refreshFilter: function() {
|
||||
var that = this;
|
||||
@@ -238,24 +230,7 @@
|
||||
this.uiHeight = desiredHeight;
|
||||
this._resize();
|
||||
},
|
||||
getItemAt: function(index) {
|
||||
var items = this.items();
|
||||
if (index >= 0 && index < items.length) {
|
||||
return $(items[index]).data('data');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
indexOf: function(data) {
|
||||
var items = this.items();
|
||||
for (var i=0;i<items.length;i++) {
|
||||
if ($(items[i]).data('data') === data) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
},
|
||||
insertItemAt: function(data,index) {
|
||||
addItem: function(data) {
|
||||
var that = this;
|
||||
data = data || {};
|
||||
var li = $('<li>');
|
||||
@@ -273,13 +248,7 @@
|
||||
});
|
||||
}
|
||||
if (!added) {
|
||||
if (index <= 0) {
|
||||
li.prependTo(this.element);
|
||||
} else if (index > that.element.children().length-1) {
|
||||
li.appendTo(this.element);
|
||||
} else {
|
||||
li.insertBefore(this.element.children().eq(index));
|
||||
}
|
||||
li.appendTo(this.element);
|
||||
}
|
||||
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
|
||||
row.data('data',data);
|
||||
@@ -288,10 +257,10 @@
|
||||
li.addClass("red-ui-editableList-item-sortable");
|
||||
}
|
||||
if (this.options.removable) {
|
||||
var deleteButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(li);
|
||||
var deleteButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove editor-button editor-button-small"}).appendTo(li);
|
||||
$('<i/>',{class:"fa fa-remove"}).appendTo(deleteButton);
|
||||
li.addClass("red-ui-editableList-item-removable");
|
||||
deleteButton.on("click", function(evt) {
|
||||
deleteButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var data = row.data('data');
|
||||
li.addClass("red-ui-editableList-item-deleting")
|
||||
@@ -324,9 +293,6 @@
|
||||
},0);
|
||||
}
|
||||
},
|
||||
addItem: function(data) {
|
||||
this.insertItemAt(data,this.element.children().length)
|
||||
},
|
||||
addItems: function(items) {
|
||||
for (var i=0; i<items.length;i++) {
|
||||
this.addItem(items[i]);
|
||||
@@ -346,7 +312,6 @@
|
||||
},
|
||||
empty: function() {
|
||||
this.element.empty();
|
||||
this.uiContainer.scrollTop(0);
|
||||
},
|
||||
filter: function(filter) {
|
||||
if (filter !== undefined) {
|
||||
@@ -362,22 +327,6 @@
|
||||
},
|
||||
length: function() {
|
||||
return this.element.children().length;
|
||||
},
|
||||
show: function(item) {
|
||||
var items = this.element.children().filter(function(f) {
|
||||
return item === $(this).find(".red-ui-editableList-item-content").data('data');
|
||||
});
|
||||
if (items.length > 0) {
|
||||
this.uiContainer.scrollTop(this.uiContainer.scrollTop()+items.position().top)
|
||||
}
|
||||
},
|
||||
getItem: function(li) {
|
||||
var el = li.find(".red-ui-editableList-item-content");
|
||||
if (el.length) {
|
||||
return el.data('data');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
@@ -56,12 +56,12 @@ RED.menu = (function() {
|
||||
}
|
||||
|
||||
if (opt === null) {
|
||||
item = $('<li class="red-ui-menu-divider"></li>');
|
||||
item = $('<li class="divider"></li>');
|
||||
} else {
|
||||
item = $('<li></li>');
|
||||
|
||||
if (opt.group) {
|
||||
item.addClass("red-ui-menu-group-"+opt.group);
|
||||
item.addClass("menu-group-"+opt.group);
|
||||
|
||||
}
|
||||
var linkContent = '<a '+(opt.id?'id="'+opt.id+'" ':'')+'tabindex="-1" href="#">';
|
||||
@@ -71,7 +71,7 @@ RED.menu = (function() {
|
||||
|
||||
}
|
||||
if (opt.icon !== undefined) {
|
||||
if (/\.(png|svg)/.test(opt.icon)) {
|
||||
if (/\.png/.test(opt.icon)) {
|
||||
linkContent += '<img src="'+opt.icon+'"/> ';
|
||||
} else {
|
||||
linkContent += '<i class="'+(opt.icon?opt.icon:'" style="display: inline-block;"')+'"></i> ';
|
||||
@@ -79,10 +79,10 @@ RED.menu = (function() {
|
||||
}
|
||||
|
||||
if (opt.sublabel) {
|
||||
linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+opt.label+'</span>'+
|
||||
'<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>'
|
||||
linkContent += '<span class="menu-label-container"><span class="menu-label">'+opt.label+'</span>'+
|
||||
'<span class="menu-sublabel">'+opt.sublabel+'</span></span>'
|
||||
} else {
|
||||
linkContent += '<span class="red-ui-menu-label">'+opt.label+'</span>'
|
||||
linkContent += '<span class="menu-label">'+opt.label+'</span>'
|
||||
}
|
||||
|
||||
linkContent += '</a>';
|
||||
@@ -92,16 +92,27 @@ RED.menu = (function() {
|
||||
menuItems[opt.id] = opt;
|
||||
|
||||
if (opt.onselect) {
|
||||
link.on("click", function(e) {
|
||||
link.click(function(e) {
|
||||
e.preventDefault();
|
||||
if ($(this).parent().hasClass("disabled")) {
|
||||
return;
|
||||
}
|
||||
if (opt.toggle) {
|
||||
if (opt.toggle === true) {
|
||||
setSelected(opt.id, !isSelected(opt.id));
|
||||
var selected = isSelected(opt.id);
|
||||
if (typeof opt.toggle === "string") {
|
||||
if (!selected) {
|
||||
for (var m in menuItems) {
|
||||
if (menuItems.hasOwnProperty(m)) {
|
||||
var mi = menuItems[m];
|
||||
if (mi.id != opt.id && opt.toggle == mi.toggle) {
|
||||
setSelected(mi.id,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
setSelected(opt.id,true);
|
||||
}
|
||||
} else {
|
||||
setSelected(opt.id, true);
|
||||
setSelected(opt.id, !selected);
|
||||
}
|
||||
} else {
|
||||
triggerAction(opt.id);
|
||||
@@ -114,13 +125,13 @@ RED.menu = (function() {
|
||||
link.attr("target","_blank").attr("href",opt.href);
|
||||
} else if (!opt.options) {
|
||||
item.addClass("disabled");
|
||||
link.on("click", function(event) {
|
||||
link.click(function(event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
if (opt.options) {
|
||||
item.addClass("red-ui-menu-dropdown-submenu pull-left");
|
||||
var submenu = $('<ul id="'+opt.id+'-submenu" class="red-ui-menu-dropdown"></ul>').appendTo(item);
|
||||
item.addClass("dropdown-submenu pull-left");
|
||||
var submenu = $('<ul id="'+opt.id+'-submenu" class="dropdown-menu"></ul>').appendTo(item);
|
||||
|
||||
for (var i=0;i<opt.options.length;i++) {
|
||||
var li = createMenuItem(opt.options[i]);
|
||||
@@ -139,30 +150,13 @@ RED.menu = (function() {
|
||||
|
||||
}
|
||||
function createMenu(options) {
|
||||
var topMenu = $("<ul/>",{class:"red-ui-menu red-ui-menu-dropdown pull-right"});
|
||||
|
||||
if (options.id) {
|
||||
topMenu.attr({id:options.id+"-submenu"});
|
||||
var menuParent = $("#"+options.id);
|
||||
if (menuParent.length === 1) {
|
||||
topMenu.insertAfter(menuParent);
|
||||
menuParent.on("click", function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
if (topMenu.is(":visible")) {
|
||||
$(document).off("click.red-ui-menu");
|
||||
topMenu.hide();
|
||||
} else {
|
||||
$(document).on("click.red-ui-menu", function(evt) {
|
||||
$(document).off("click.red-ui-menu");
|
||||
activeMenu = null;
|
||||
topMenu.hide();
|
||||
});
|
||||
$(".red-ui-menu").hide();
|
||||
topMenu.show();
|
||||
}
|
||||
})
|
||||
}
|
||||
var menuParent = $("#"+options.id);
|
||||
|
||||
var topMenu = $("<ul/>",{id:options.id+"-submenu", class:"dropdown-menu pull-right"});
|
||||
|
||||
if (menuParent.length === 1) {
|
||||
topMenu.insertAfter(menuParent);
|
||||
}
|
||||
|
||||
var lastAddedSeparator = false;
|
||||
@@ -198,9 +192,8 @@ RED.menu = (function() {
|
||||
}
|
||||
|
||||
function setSelected(id,state) {
|
||||
var alreadySet = false;
|
||||
if (isSelected(id) == state) {
|
||||
alreadySet = true;
|
||||
return;
|
||||
}
|
||||
var opt = menuItems[id];
|
||||
if (state) {
|
||||
@@ -208,26 +201,10 @@ RED.menu = (function() {
|
||||
} else {
|
||||
$("#"+id).removeClass("active");
|
||||
}
|
||||
if (opt) {
|
||||
if (opt.toggle && typeof opt.toggle === "string") {
|
||||
if (state) {
|
||||
for (var m in menuItems) {
|
||||
if (menuItems.hasOwnProperty(m)) {
|
||||
var mi = menuItems[m];
|
||||
if (mi.id != opt.id && opt.toggle == mi.toggle) {
|
||||
setSelected(mi.id,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!alreadySet && opt.onselect) {
|
||||
triggerAction(opt.id,state);
|
||||
}
|
||||
if (!opt.local && !alreadySet) {
|
||||
RED.settings.set(opt.setting||("menu-"+opt.id), state);
|
||||
}
|
||||
if (opt && opt.onselect) {
|
||||
triggerAction(opt.id,state);
|
||||
}
|
||||
RED.settings.set(opt.setting||("menu-"+opt.id), state);
|
||||
}
|
||||
|
||||
function toggleSelected(id) {
|
||||
@@ -244,14 +221,14 @@ RED.menu = (function() {
|
||||
|
||||
function addItem(id,opt) {
|
||||
var item = createMenuItem(opt);
|
||||
if (opt !== null && opt.group) {
|
||||
var groupItems = $("#"+id+"-submenu").children(".red-ui-menu-group-"+opt.group);
|
||||
if (opt.group) {
|
||||
var groupItems = $("#"+id+"-submenu").children(".menu-group-"+opt.group);
|
||||
if (groupItems.length === 0) {
|
||||
item.appendTo("#"+id+"-submenu");
|
||||
} else {
|
||||
for (var i=0;i<groupItems.length;i++) {
|
||||
var groupItem = groupItems[i];
|
||||
var label = $(groupItem).find(".red-ui-menu-label").html();
|
||||
var label = $(groupItem).find(".menu-label").html();
|
||||
if (opt.label < label) {
|
||||
$(groupItem).before(item);
|
||||
break;
|
||||
@@ -285,5 +262,6 @@ RED.menu = (function() {
|
||||
addItem: addItem,
|
||||
removeItem: removeItem,
|
||||
setAction: setAction
|
||||
//TODO: add an api for replacing a submenu - see library.js:loadFlowLibrary
|
||||
}
|
||||
})();
|
81
editor/js/ui/common/panels.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
RED.panels = (function() {
|
||||
|
||||
function createPanel(options) {
|
||||
var container = options.container || $("#"+options.id);
|
||||
var children = container.children();
|
||||
if (children.length !== 2) {
|
||||
throw new Error("Container must have exactly two children");
|
||||
}
|
||||
|
||||
container.addClass("red-ui-panels");
|
||||
var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
|
||||
var startPosition;
|
||||
var panelHeights = [];
|
||||
var modifiedHeights = false;
|
||||
var panelRatio;
|
||||
|
||||
separator.draggable({
|
||||
axis: "y",
|
||||
containment: container,
|
||||
scroll: false,
|
||||
start:function(event,ui) {
|
||||
var height = container.height();
|
||||
startPosition = ui.position.top;
|
||||
panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
var height = container.height();
|
||||
var delta = ui.position.top-startPosition;
|
||||
var newHeights = [panelHeights[0]+delta,panelHeights[1]-delta];
|
||||
$(children[0]).height(newHeights[0]);
|
||||
$(children[1]).height(newHeights[1]);
|
||||
if (options.resize) {
|
||||
options.resize(newHeights[0],newHeights[1]);
|
||||
}
|
||||
ui.position.top -= delta;
|
||||
panelRatio = newHeights[0]/height;
|
||||
},
|
||||
stop:function(event,ui) {
|
||||
modifiedHeights = true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
resize: function(height) {
|
||||
var panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
container.height(height);
|
||||
if (modifiedHeights) {
|
||||
var topPanelHeight = panelRatio*height;
|
||||
var bottomPanelHeight = height - topPanelHeight - 48;
|
||||
panelHeights = [topPanelHeight,bottomPanelHeight];
|
||||
$(children[0]).height(panelHeights[0]);
|
||||
$(children[1]).height(panelHeights[1]);
|
||||
}
|
||||
if (options.resize) {
|
||||
options.resize(panelHeights[0],panelHeights[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPanel
|
||||
}
|
||||
})();
|