Compare commits

..

6 Commits

Author SHA1 Message Date
Nick O'Leary
f8461d31c2 Merge pull request #3132 from hardillb/v1.x-docker-release
Check out corect node-red-docker branch for a release
2021-09-07 12:06:42 +01:00
Ben Hardill
35e7538b9c Check out corect node-red-docker branch
Also remove website update as nothing to change for 1.x releases
2021-09-06 15:03:57 +01:00
Nick O'Leary
7aec7c8460 Bump for 1.3.7 2021-09-02 09:07:04 +01:00
Nick O'Leary
297dd81327 Update generate-publish-script to handle maintenance releases 2021-07-30 10:44:46 +01:00
Nick O'Leary
1750690309 Fix dependencies 2021-07-30 10:30:41 +01:00
Nick O'Leary
773ead3eec Bump for 1.3.6 2021-07-30 10:29:52 +01:00
623 changed files with 13123 additions and 85267 deletions

View File

@@ -1,13 +1,10 @@
name: Publish Release name: PublishDockerImage
env: env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true ACTIONS_ALLOW_UNSECURE_COMMANDS: true
on: on:
release: release:
types: [published] types: [published]
permissions:
contents: read
jobs: jobs:
generate: generate:
name: 'Update node-red-docker image' name: 'Update node-red-docker image'
@@ -21,15 +18,11 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
repository: 'node-red/node-red-docker' repository: 'node-red/node-red-docker'
ref: 'v1.x'
path: 'node-red-docker' path: 'node-red-docker'
- name: Check out node-red.github.io repository
uses: actions/checkout@v2
with:
repository: 'node-red/node-red.github.io'
path: 'node-red.github.io'
- uses: actions/setup-node@v1 - uses: actions/setup-node@v1
with: with:
node-version: '16' node-version: '12'
- run: node ./node-red/.github/scripts/update-node-red-docker.js - run: node ./node-red/.github/scripts/update-node-red-docker.js
- name: Create Docker Pull Request - name: Create Docker Pull Request
uses: peter-evans/create-pull-request@v2 uses: peter-evans/create-pull-request@v2
@@ -45,18 +38,4 @@ jobs:
Once this is merged, you will need to create a new release with the tag `v${{ env.newVersion }}`. Once this is merged, you will need to create a new release with the tag `v${{ env.newVersion }}`.
This PR was auto-generated by a GitHub Action. Any questions, speak to @knolleary
- run: node ./node-red/.github/scripts/update-node-red-website.js
- name: Create Website Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.NR_REPO_TOKEN }}
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
path: 'node-red.github.io'
commit-message: 'Bump to ${{ env.newVersion }}'
title: '🚀 Update to Node-RED ${{ env.newVersion }} release'
body: |
Updates the Node-RED Website repo for the ${{ env.newVersion }} release.
This PR was auto-generated by a GitHub Action. Any questions, speak to @knolleary This PR was auto-generated by a GitHub Action. Any questions, speak to @knolleary

View File

@@ -1,36 +0,0 @@
name: Run tests
on:
push:
branches: [ master, dev ]
pull_request:
branches: [ master, dev ]
permissions:
contents: read
jobs:
build:
permissions:
checks: write # for coverallsapp/github-action to create new checks
contents: read # for actions/checkout to fetch code
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install Dependencies
run: npm install
- name: Run tests
run: |
npm run test
- name: Publish to coveralls.io
if: ${{ matrix.node-version == 16 }}
uses: coverallsapp/github-action@v1.1.2
with:
github-token: ${{ github.token }}

View File

@@ -15,5 +15,5 @@
"shadow": true, // allow variable shadowing (re-use of names...) "shadow": true, // allow variable shadowing (re-use of names...)
"sub": true, // don't warn that foo['bar'] should be written as foo.bar "sub": true, // don't warn that foo['bar'] should be written as foo.bar
"proto": true, // allow setting of __proto__ in node < v0.12, "proto": true, // allow setting of __proto__ in node < v0.12,
"esversion": 11 // allow es11(ES2020) "esversion": 6 // allow es6
} }

24
.travis.yml Normal file
View File

@@ -0,0 +1,24 @@
sudo: false
addons:
chrome: stable
language: node_js
matrix:
include:
- node_js: "16"
script:
- ./node_modules/.bin/grunt no-coverage
- node_js: "14"
script:
- ./node_modules/.bin/grunt && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
# - scripts/install-ui-test-dependencies.sh && grunt test-ui
before_script:
- npm install -g coveralls
- node_js: "12"
script:
- ./node_modules/.bin/grunt no-coverage
- node_js: "10"
script:
- ./node_modules/.bin/grunt no-coverage
#- node_js: "8"
# script:
# - ./node_modules/.bin/grunt no-coverage

14
API.md
View File

@@ -1,12 +1,8 @@
Node-RED consists of 6 node modules under the `@node-red` scope, which are pulled together Node-RED Modules
by the top-level `node-red` module. The typical scenario is where you are embedding Node-RED into your ---
own application, in which case you would use the `node-red` module rather than any of the
internal modules directly.
```javascript
let RED = require("node-red");
```
Node-RED provides a set of node modules that implement different parts of the
application.
Module | Description Module | Description
-------|------- -------|-------
@@ -15,5 +11,5 @@ Module | Description
[@node-red/runtime](@node-red_runtime.html) | the core runtime of Node-RED [@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/util](@node-red_util.html) | common utilities for the Node-RED runtime and editor modules
[@node-red/registry](@node-red_registry.html) | the internal node registry [@node-red/registry](@node-red_registry.html) | the internal node registry
@node-red/nodes | the default set of core nodes. This module only contains the Node-RED nodes - it does not expose any APIs. @node-red/nodes | the default set of core nodes
@node-red/editor-client | the client-side resources of the Node-RED editor application @node-red/editor-client | the client-side resources of the Node-RED editor application

File diff suppressed because it is too large Load Diff

View File

@@ -38,9 +38,12 @@ 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 of existing code, it may well get rejected if you haven't discussed it on
the [forum](https://discourse.nodered.org) first. the [forum](https://discourse.nodered.org) first.
All contributors need to sign the OpenJS Foundation's Contributor License Agreement. All contributors need to sign the JS Foundation's Contributor License Agreement.
It is an online process and quick to do. If you raise a pull-request without It is an online process and quick to do. You can read the details of the agreement
having signed the CLA, you will be prompted to do so automatically. here: https://cla.js.foundation/node-red/node-red.
If you raise a pull-request without having signed the CLA, you will be prompted
to do so automatically.
### Code Branches ### Code Branches

View File

@@ -40,10 +40,11 @@ module.exports = function(grunt) {
if (nonHeadless) { if (nonHeadless) {
process.env.NODE_RED_NON_HEADLESS = true; process.env.NODE_RED_NON_HEADLESS = true;
} }
const pkg = grunt.file.readJSON('package.json'); let packageFile = grunt.file.readJSON('package.json')
process.env.NODE_RED_PACKAGE_VERSION = pkg.version; process.env.NODE_RED_PACKAGE_VERSION = packageFile.version;
grunt.initConfig({ grunt.initConfig({
pkg: pkg, pkg: packageFile,
paths: { paths: {
dist: ".dist" dist: ".dist"
}, },
@@ -137,12 +138,10 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/jquery-addons.js", "packages/node_modules/@node-red/editor-client/src/js/jquery-addons.js",
"packages/node_modules/@node-red/editor-client/src/js/red.js", "packages/node_modules/@node-red/editor-client/src/js/red.js",
"packages/node_modules/@node-red/editor-client/src/js/events.js", "packages/node_modules/@node-red/editor-client/src/js/events.js",
"packages/node_modules/@node-red/editor-client/src/js/hooks.js",
"packages/node_modules/@node-red/editor-client/src/js/i18n.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/settings.js",
"packages/node_modules/@node-red/editor-client/src/js/user.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/comms.js",
"packages/node_modules/@node-red/editor-client/src/js/runtime.js",
"packages/node_modules/@node-red/editor-client/src/js/text/bidi.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/text/format.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/state.js", "packages/node_modules/@node-red/editor-client/src/js/ui/state.js",
@@ -151,7 +150,6 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js", "packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
"packages/node_modules/@node-red/editor-client/src/js/history.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/validators.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js", "packages/node_modules/@node-red/editor-client/src/js/ui/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/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/treeList.js",
@@ -164,17 +162,14 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/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/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/toggleButton.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.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/actions.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js", "packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/diagnostics.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js", "packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js", "packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/env-var.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js", "packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/statusBar.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.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/view-annotations.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-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/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/sidebar.js",
@@ -186,16 +181,13 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.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/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/editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js", "packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-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/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/tray.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.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/library.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/notifications.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/search.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.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/typeSearch.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js", "packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
@@ -205,8 +197,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.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/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/projects/tab-versionControl.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js", "packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js"
"packages/node_modules/@node-red/editor-client/src/js/ui/tour/*.js"
], ],
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js" dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
}, },
@@ -220,13 +211,11 @@ module.exports = function(grunt) {
"node_modules/marked/marked.min.js", "node_modules/marked/marked.min.js",
"node_modules/dompurify/dist/purify.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/d3/d3.v3.min.js",
"node_modules/i18next/i18next.min.js", "packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js",
"node_modules/i18next-http-backend/i18nextHttpBackend.min.js",
"node_modules/jquery-i18next/jquery-i18next.min.js",
"node_modules/jsonata/jsonata-es5.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/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/ace.js",
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js" "packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js",
], ],
// "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [ // "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
// // TODO: resolve relative resource paths in // // TODO: resolve relative resource paths in
@@ -235,9 +224,6 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [ "packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
"node_modules/jsonata/jsonata-es5.min.js", "node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js" "packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
],
"packages/node_modules/@node-red/editor-client/public/vendor/mermaid/mermaid.min.js": [
"node_modules/mermaid/dist/mermaid.min.js"
] ]
} }
} }
@@ -298,9 +284,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/public/index.html", "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/favicon.ico",
"packages/node_modules/@node-red/editor-client/public/icons", "packages/node_modules/@node-red/editor-client/public/icons",
"packages/node_modules/@node-red/editor-client/public/vendor", "packages/node_modules/@node-red/editor-client/public/vendor"
"packages/node_modules/@node-red/editor-client/public/types/node",
"packages/node_modules/@node-red/editor-client/public/types/node-red",
] ]
}, },
release: { release: {
@@ -336,12 +320,6 @@ module.exports = function(grunt) {
], ],
tasks: ['jsonlint:keymaps','copy:build'] tasks: ['jsonlint:keymaps','copy:build']
}, },
tours: {
files: [
'packages/node_modules/@node-red/editor-client/src/tours/**/*.js'
],
tasks: ['copy:build']
},
misc: { misc: {
files: [ files: [
'CHANGELOG.md' 'CHANGELOG.md'
@@ -396,24 +374,11 @@ module.exports = function(grunt) {
src: [ src: [
'ace/**', 'ace/**',
'jquery/css/base/**', 'jquery/css/base/**',
'font-awesome/**', 'font-awesome/**'
'monaco/dist/**',
'monaco/types/extraLibs.js',
'monaco/style.css',
'monaco/monaco-bootstrap.js'
], ],
expand: true, expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/' dest: 'packages/node_modules/@node-red/editor-client/public/vendor/'
}, },
{
cwd: 'packages/node_modules/@node-red/editor-client/src',
src: [
'types/node/*.ts',
'types/node-red/*.ts',
],
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/'
},
{ {
cwd: 'packages/node_modules/@node-red/editor-client/src/icons', cwd: 'packages/node_modules/@node-red/editor-client/src/icons',
src: '**', src: '**',
@@ -439,12 +404,6 @@ module.exports = function(grunt) {
src: '**', src: '**',
expand: true, expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/' dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/'
},
{
cwd: 'packages/node_modules/@node-red/editor-client/src/tours',
src: '**',
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/red/tours/'
} }
] ]
} }
@@ -591,7 +550,7 @@ module.exports = function(grunt) {
grunt.registerMultiTask('attachCopyright', function() { grunt.registerMultiTask('attachCopyright', function() {
var files = this.data.src; var files = this.data.src;
var copyright = "/**\n"+ var copyright = "/**\n"+
" * Copyright OpenJS Foundation and other contributors, https://openjsf.org/\n"+ " * Copyright JS Foundation and other contributors, http://js.foundation\n"+
" *\n"+ " *\n"+
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"+ " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"+
" * you may not use this file except in compliance with the License.\n"+ " * you may not use this file except in compliance with the License.\n"+

View File

@@ -56,13 +56,13 @@ This project adheres to the [Contributor Covenant 1.4](http://contributor-covena
## Authors ## Authors
Node-RED is a project of the [OpenJS Foundation](http://openjsf.org). Node-RED is a project of the [OpenJS Foundation](https://openjsf.org).
It is maintained by: It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-technology/).
* Nick O'Leary [@knolleary](http://twitter.com/knolleary)
* Dave Conway-Jones [@ceejay](http://twitter.com/ceejay)
* Nick O'Leary [@knolleary](http://twitter.com/knolleary)
* Dave Conway-Jones [@ceejay](http://twitter.com/ceejay)
* And many others...
## Copyright and license ## Copyright and license

View File

@@ -1,6 +1,6 @@
{ {
"name": "node-red", "name": "node-red",
"version": "3.1.0-beta.1", "version": "1.3.7",
"description": "Low-code programming for event-driven applications", "description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org", "homepage": "http://nodered.org",
"license": "Apache-2.0", "license": "Apache-2.0",
@@ -26,102 +26,97 @@
} }
], ],
"dependencies": { "dependencies": {
"acorn": "8.8.2", "acorn": "8.3.0",
"acorn-walk": "8.2.0", "acorn-walk": "8.1.0",
"ajv": "8.12.0", "ajv": "6.12.6",
"async-mutex": "0.4.0", "async-mutex": "0.3.1",
"basic-auth": "2.0.1", "basic-auth": "2.0.1",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.20.2", "body-parser": "1.19.0",
"cheerio": "1.0.0-rc.10", "cheerio": "0.22.0",
"clone": "2.1.2", "clone": "2.1.2",
"content-type": "1.0.5", "content-type": "1.0.4",
"cookie": "0.5.0", "cookie": "0.4.1",
"cookie-parser": "1.4.6", "cookie-parser": "1.4.5",
"cors": "2.8.5", "cors": "2.8.5",
"cronosjs": "1.7.1", "cron": "1.7.2",
"denque": "2.1.0", "denque": "1.5.0",
"express": "4.18.2", "express": "4.17.1",
"express-session": "1.17.3", "express-session": "1.17.1",
"form-data": "4.0.0", "fs-extra": "8.1.0",
"fs-extra": "10.1.0", "fs.notify": "0.0.4",
"got": "11.8.6",
"hash-sum": "2.0.0", "hash-sum": "2.0.0",
"hpagent": "1.2.0", "https-proxy-agent": "5.0.0",
"https-proxy-agent": "5.0.1", "i18next": "15.1.2",
"i18next": "21.10.0", "iconv-lite": "0.6.2",
"iconv-lite": "0.6.3",
"is-utf8": "0.2.1", "is-utf8": "0.2.1",
"js-yaml": "4.1.0", "js-yaml": "3.14.0",
"json-stringify-safe": "5.0.1", "json-stringify-safe": "5.0.1",
"jsonata": "1.8.6", "jsonata": "1.8.4",
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"media-typer": "1.1.0", "media-typer": "1.1.0",
"memorystore": "1.6.7", "memorystore": "1.6.6",
"mime": "3.0.0", "mime": "2.5.2",
"moment": "2.29.4", "moment-timezone": "0.5.33",
"moment-timezone": "0.5.41", "mqtt": "4.2.6",
"mqtt": "4.3.7", "multer": "1.4.2",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0", "mustache": "4.2.0",
"node-red-admin": "^3.0.0", "node-red-admin": "0.2.7",
"node-watch": "0.7.3", "node-red-node-rbe": "^0.5.0",
"node-red-node-sentiment": "^0.1.6",
"node-red-node-tail": "^0.3.0",
"nopt": "5.0.0", "nopt": "5.0.0",
"oauth2orize": "1.11.1", "oauth2orize": "1.11.0",
"on-headers": "1.0.2", "on-headers": "1.0.2",
"passport": "0.6.0", "passport": "0.4.1",
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.2", "raw-body": "2.4.1",
"semver": "7.3.8", "request": "2.88.0",
"tar": "6.1.13", "semver": "6.3.0",
"tough-cookie": "4.1.2", "tar": "6.1.11",
"uglify-js": "3.17.4", "uglify-js": "3.13.3",
"uuid": "9.0.0", "ws": "6.2.2",
"ws": "7.5.6",
"xml2js": "0.4.23" "xml2js": "0.4.23"
}, },
"optionalDependencies": { "optionalDependencies": {
"bcrypt": "5.1.0" "bcrypt": "3.0.8"
}, },
"devDependencies": { "devDependencies": {
"dompurify": "2.4.1", "dompurify": "2.2.7",
"grunt": "1.6.1", "grunt": "1.3.0",
"grunt-chmod": "~1.1.1", "grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3", "grunt-cli": "~1.4.2",
"grunt-concurrent": "3.0.0", "grunt-concurrent": "3.0.0",
"grunt-contrib-clean": "2.0.1", "grunt-contrib-clean": "~2.0.0",
"grunt-contrib-compress": "2.0.0", "grunt-contrib-compress": "1.6.0",
"grunt-contrib-concat": "2.1.0", "grunt-contrib-concat": "~1.0.1",
"grunt-contrib-copy": "1.0.0", "grunt-contrib-copy": "~1.0.0",
"grunt-contrib-jshint": "3.2.0", "grunt-contrib-jshint": "~2.1.0",
"grunt-contrib-uglify": "5.2.2", "grunt-contrib-uglify": "~4.0.1",
"grunt-contrib-watch": "1.1.0", "grunt-contrib-watch": "~1.1.0",
"grunt-jsdoc": "2.4.1", "grunt-jsdoc": "2.4.1",
"grunt-jsdoc-to-markdown": "6.0.0", "grunt-jsdoc-to-markdown": "5.0.0",
"grunt-jsonlint": "2.1.3", "grunt-jsonlint": "2.1.3",
"grunt-mkdir": "~1.1.0", "grunt-mkdir": "~1.1.0",
"grunt-npm-command": "~0.1.2", "grunt-npm-command": "~0.1.2",
"grunt-sass": "~3.1.0", "grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1", "grunt-simple-mocha": "~0.4.1",
"grunt-simple-nyc": "^3.0.1", "grunt-simple-nyc": "^3.0.1",
"i18next-http-backend": "1.4.1", "http-proxy": "1.18.1",
"jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "4.2.12", "marked": "2.0.1",
"mermaid": "^9.3.0",
"minami": "1.2.3", "minami": "1.2.3",
"mocha": "9.2.2", "mocha": "^5.2.0",
"node-red-node-test-helper": "^0.3.0", "node-red-node-test-helper": "^0.2.7",
"nodemon": "2.0.20", "nodemon": "2.0.7",
"proxy": "^1.0.2", "sass": "1.32.12",
"sass": "1.58.3",
"should": "13.2.3", "should": "13.2.3",
"sinon": "11.1.2", "sinon": "1.17.7",
"stoppable": "^1.1.0", "stoppable": "^1.1.0",
"supertest": "6.3.3" "supertest": "5.0.0"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=8"
} }
} }

View File

@@ -1,4 +1,4 @@
Copyright OpenJS Foundation and other contributors, https://openjsf.org/ Copyright JS Foundation and other contributors, http://js.foundation
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004

View File

@@ -1,23 +0,0 @@
let runtimeAPI;
let settings;
const apiUtil = require("../util");
module.exports = {
init: function(_settings, _runtimeAPI) {
settings = _settings;
runtimeAPI = _runtimeAPI;
},
getReport: function(req, res) {
const diagnosticsOpts = settings.diagnostics || {};
const opts = {
user: req.user,
scope: diagnosticsOpts.level || "basic"
}
if(diagnosticsOpts.enabled === false || diagnosticsOpts.enabled === "false") {
apiUtil.rejectHandler(req, res, {message: "diagnostics are disabled", status: 403, code: "diagnostics.disabled" })
} else {
runtimeAPI.diagnostics.get(opts)
.then(function(result) { res.json(result); })
.catch(err => apiUtil.rejectHandler(req, res, err))
}
}
}

View File

@@ -68,28 +68,5 @@ module.exports = {
}).catch(function(err) { }).catch(function(err) {
apiUtils.rejectHandler(req,res,err); apiUtils.rejectHandler(req,res,err);
}) })
},
getState: function(req,res) {
const opts = {
user: req.user,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.getState(opts).then(function(result) {
res.json(result);
}).catch(function(err) {
apiUtils.rejectHandler(req,res,err);
})
},
postState: function(req,res) {
const opts = {
user: req.user,
state: req.body.state || "",
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.setState(opts).then(function(result) {
res.json(result);
}).catch(function(err) {
apiUtils.rejectHandler(req,res,err);
})
} }
} }

View File

@@ -23,7 +23,6 @@ var context = require("./context");
var auth = require("../auth"); var auth = require("../auth");
var info = require("./settings"); var info = require("./settings");
var plugins = require("./plugins"); var plugins = require("./plugins");
var diagnostics = require("./diagnostics");
var apiUtil = require("../util"); var apiUtil = require("../util");
@@ -35,31 +34,15 @@ module.exports = {
context.init(runtimeAPI); context.init(runtimeAPI);
info.init(settings,runtimeAPI); info.init(settings,runtimeAPI);
plugins.init(runtimeAPI); plugins.init(runtimeAPI);
diagnostics.init(settings, runtimeAPI);
var needsPermission = auth.needsPermission; var needsPermission = auth.needsPermission;
var adminApp = express(); var adminApp = express();
var defaultServerSettings = {
"x-powered-by": false
}
var serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
for (var eOption in serverSettings) {
adminApp.set(eOption, serverSettings[eOption]);
}
// Flows // Flows
adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler); adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler);
adminApp.post("/flows",needsPermission("flows.write"),flows.post,apiUtil.errorHandler); adminApp.post("/flows",needsPermission("flows.write"),flows.post,apiUtil.errorHandler);
// Flows/state
adminApp.get("/flows/state", needsPermission("flows.read"), flows.getState, apiUtil.errorHandler);
if (settings.runtimeState && settings.runtimeState.enabled === true) {
adminApp.post("/flows/state", needsPermission("flows.write"), flows.postState, apiUtil.errorHandler);
}
// Flow // Flow
adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get,apiUtil.errorHandler); adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get,apiUtil.errorHandler);
adminApp.post("/flow",needsPermission("flows.write"),flow.post,apiUtil.errorHandler); adminApp.post("/flow",needsPermission("flows.write"),flow.post,apiUtil.errorHandler);
@@ -103,8 +86,6 @@ module.exports = {
adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler); adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler);
adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler); adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler);
adminApp.get("/diagnostics", needsPermission("diagnostics.read"), diagnostics.getReport, apiUtil.errorHandler);
return adminApp; return adminApp;
} }
} }

View File

@@ -106,15 +106,9 @@ async function login(req,res) {
urlPrefix += "/"; urlPrefix += "/";
} }
response = { response = {
"type":"strategy" "type":"strategy",
"prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}]
} }
if (mergedAdminAuth.strategy.autoLogin) {
response.autoLogin = true
response.loginRedirect = urlPrefix + "auth/strategy"
}
response.prompts = [
{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}
]
if (mergedAdminAuth.strategy.icon) { if (mergedAdminAuth.strategy.icon) {
response.prompts[0].icon = mergedAdminAuth.strategy.icon; response.prompts[0].icon = mergedAdminAuth.strategy.icon;
} }
@@ -147,7 +141,7 @@ function completeVerify(profile,done) {
Users.authenticate(profile).then(function(user) { Users.authenticate(profile).then(function(user) {
if (user) { if (user) {
Tokens.create(user.username,"node-red-editor",user.permissions).then(function(tokens) { Tokens.create(user.username,"node-red-editor",user.permissions).then(function(tokens) {
log.audit({event: "auth.login",user,username:user.username,scope:user.permissions}); log.audit({event: "auth.login",username:user.username,scope:user.permissions});
user.tokens = tokens; user.tokens = tokens;
done(null,user); done(null,user);
}); });
@@ -179,38 +173,31 @@ function genericStrategy(adminApp,strategy) {
adminApp.use(passport.session()); adminApp.use(passport.session());
var options = strategy.options; var options = strategy.options;
var verify = function() {
var originalDone = arguments[arguments.length-1];
if (options.verify) {
var args = Array.from(arguments);
args[args.length-1] = function(err,profile) {
if (err) {
return originalDone(err);
} else {
return completeVerify(profile,originalDone);
}
};
options.verify.apply(this,args); passport.use(new strategy.strategy(options,
} else { function() {
var profile = arguments[arguments.length - 2]; var originalDone = arguments[arguments.length-1];
return completeVerify(profile,originalDone); if (options.verify) {
var args = Array.from(arguments);
args[args.length-1] = function(err,profile) {
if (err) {
return originalDone(err);
} else {
return completeVerify(profile,originalDone);
}
};
options.verify.apply(null,args);
} else {
var profile = arguments[arguments.length - 2];
return completeVerify(profile,originalDone);
}
} }
}; ));
// Give our callback the same arity as the original one from options
if (options.verify) {
Object.defineProperty(verify, "length", { value: options.verify.length })
}
passport.use(new strategy.strategy(options, verify));
adminApp.get('/auth/strategy', adminApp.get('/auth/strategy',
passport.authenticate(strategy.name, {session:false, passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
failureMessage: true, completeGenerateStrategyAuth
failureRedirect: settings.httpAdminRoot
}),
completeGenerateStrategyAuth,
handleStrategyError
); );
var callbackMethodFunc = adminApp.get; var callbackMethodFunc = adminApp.get;
@@ -218,13 +205,8 @@ function genericStrategy(adminApp,strategy) {
callbackMethodFunc = adminApp.post; callbackMethodFunc = adminApp.post;
} }
callbackMethodFunc.call(adminApp,'/auth/strategy/callback', callbackMethodFunc.call(adminApp,'/auth/strategy/callback',
passport.authenticate(strategy.name, { passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
session:false, completeGenerateStrategyAuth
failureMessage: true,
failureRedirect: settings.httpAdminRoot
}),
completeGenerateStrategyAuth,
handleStrategyError
); );
} }
@@ -234,13 +216,6 @@ function completeGenerateStrategyAuth(req,res) {
// Successful authentication, redirect home. // Successful authentication, redirect home.
res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken); res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken);
} }
function handleStrategyError(err, req, res, next) {
if (res.headersSent) {
return next(err)
}
log.audit({event: "auth.login.fail.oauth",error:err.toString()});
res.redirect(settings.httpAdminRoot + '?session_message='+err.toString());
}
module.exports = { module.exports = {
init: init, init: init,

View File

@@ -92,16 +92,10 @@ var passwordTokenExchange = function(client, username, password, scope, done) {
loginAttempts = loginAttempts.filter(function(logEntry) { loginAttempts = loginAttempts.filter(function(logEntry) {
return logEntry.user !== username; return logEntry.user !== username;
}); });
// Check if the user contains a user defined token and use it Tokens.create(username,client.id,scope).then(function(tokens) {
// instead of generating a new token log.audit({event: "auth.login",username:username,client:client.id,scope:scope});
if(user.token){ done(null,tokens.accessToken,null,{expires_in:tokens.expires_in});
done(null,user.token,null,null); });
} else {
Tokens.create(username,client.id,scope).then(function(tokens) {
log.audit({event: "auth.login",user,username:username,client:client.id,scope:scope});
done(null,tokens.accessToken,null,{expires_in:tokens.expires_in});
});
}
} else { } else {
log.audit({event: "auth.login.fail.permissions",username:username,client:client.id,scope:scope}); log.audit({event: "auth.login.fail.permissions",username:username,client:client.id,scope:scope});
done(null,false); done(null,false);
@@ -152,7 +146,7 @@ function authenticateUserToken(req) {
} else { } else {
reject(); reject();
} }
}).catch(reject); });
} else { } else {
reject(); reject();
} }
@@ -169,9 +163,6 @@ TokensStrategy.prototype.authenticate = function(req) {
authenticateUserToken(req).then(user => { authenticateUserToken(req).then(user => {
this.success(user,{scope:user.permissions}); this.success(user,{scope:user.permissions});
}).catch(err => { }).catch(err => {
if (err) {
log.trace("token authentication failure: "+err.stack?err.stack:err)
}
this.fail(401); this.fail(401);
}); });
} }

View File

@@ -158,31 +158,25 @@ function CommsConnection(ws, user) {
} }
CommsConnection.prototype.send = function(topic,data) { CommsConnection.prototype.send = function(topic,data) {
var self = this;
if (topic && data) { if (topic && data) {
this.stack.push({topic:topic,data:data}); this.stack.push({topic:topic,data:data});
} }
this._queueSend();
}
CommsConnection.prototype._queueSend = function() {
var self = this;
if (!this._xmitTimer) { if (!this._xmitTimer) {
this._xmitTimer = setTimeout(function() { this._xmitTimer = setTimeout(function() {
try { try {
self.ws.send(JSON.stringify(self.stack.splice(0,50))); self.ws.send(JSON.stringify(self.stack));
self.lastSentTime = Date.now(); self.lastSentTime = Date.now();
} catch(err) { } catch(err) {
removeActiveConnection(self); removeActiveConnection(self);
log.warn(log._("comms.error-send",{message:err.toString()})); log.warn(log._("comms.error-send",{message:err.toString()}));
} }
delete self._xmitTimer; delete self._xmitTimer;
if (self.stack.length > 0) { self.stack = [];
self._queueSend();
}
},50); },50);
} }
} }
CommsConnection.prototype.subscribe = function(topic) { CommsConnection.prototype.subscribe = function(topic) {
runtimeAPI.comms.subscribe({ runtimeAPI.comms.subscribe({
user: this.user, user: this.user,

View File

@@ -64,12 +64,10 @@ module.exports = {
} }
}); });
} }
var defaultServerSettings = { if (settings.httpServerOptions) {
"x-powered-by": false for (var eOption in settings.httpServerOptions) {
} editorApp.set(eOption, settings.httpServerOptions[eOption]);
var serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{}); }
for (var eOption in serverSettings) {
editorApp.set(eOption, serverSettings[eOption]);
} }
editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor); editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor);

View File

@@ -48,10 +48,9 @@ module.exports = {
var prevLang = i18n.i.language; var prevLang = i18n.i.language;
// Trigger a load from disk of the language if it is not the default // Trigger a load from disk of the language if it is not the default
i18n.i.changeLanguage(lang, function(){ i18n.i.changeLanguage(lang, function(){
i18n.i.changeLanguage(prevLang, function() { var catalog = loadResource(lang, namespace);
var catalog = loadResource(lang, namespace); res.json(catalog||{});
res.json(catalog||{});
});
}); });
i18n.i.changeLanguage(prevLang);
} }
} }

View File

@@ -122,7 +122,6 @@ module.exports = {
} }
if (req.body.active) { if (req.body.active) {
opts.clearContext = req.body.hasOwnProperty('clearContext')?req.body.clearContext:true
runtimeAPI.projects.setActiveProject(opts).then(function() { runtimeAPI.projects.setActiveProject(opts).then(function() {
listProjects(req,res); listProjects(req,res);
}).catch(function(err) { }).catch(function(err) {

View File

@@ -18,6 +18,14 @@ var apiUtils = require("../util");
var express = require("express"); var express = require("express");
var runtimeAPI; var runtimeAPI;
function getUsername(userObj) {
var username = '__default';
if ( userObj && userObj.name ) {
username = userObj.name;
}
return username;
}
module.exports = { module.exports = {
init: function(_runtimeAPI) { init: function(_runtimeAPI) {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;

View File

@@ -24,20 +24,16 @@ var defaultContext = {
page: { page: {
title: "Node-RED", title: "Node-RED",
favicon: "favicon.ico", favicon: "favicon.ico",
tabicon: { tabicon: "red/images/node-red-icon-black.svg"
icon: "red/images/node-red-icon-black.svg",
colour: "#8f0000"
},
version: require(path.join(__dirname,"../../package.json")).version
}, },
header: { header: {
title: "Node-RED", title: "Node-RED",
image: "red/images/node-red.svg" image: "red/images/node-red.svg"
}, },
asset: { asset: {
red: "red/red.min.js", red: (process.env.NODE_ENV == "development")? "red/red.js":"red/red.min.js",
main: "red/main.min.js", main: (process.env.NODE_ENV == "development")? "red/main.js":"red/main.min.js",
vendorMonaco: ""
} }
}; };
@@ -78,7 +74,7 @@ function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
let fullPath = array[i]; let fullPath = array[i];
if (baseDirectory) { if (baseDirectory) {
fullPath = path.resolve(baseDirectory,array[i]); fullPath = path.resolve(baseDirectory,array[i]);
if (fullPath.indexOf(path.resolve(baseDirectory)) !== 0) { if (fullPath.indexOf(baseDirectory) !== 0) {
continue; continue;
} }
} }
@@ -95,16 +91,8 @@ module.exports = {
init: function(settings, _runtimeAPI) { init: function(settings, _runtimeAPI) {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
themeContext = clone(defaultContext); themeContext = clone(defaultContext);
if (process.env.NODE_ENV == "development") {
themeContext.asset.red = "red/red.js";
themeContext.asset.main = "red/main.js";
}
themeSettings = null; themeSettings = null;
theme = settings.editorTheme || {}; theme = settings.editorTheme || {};
themeContext.asset.vendorMonaco = "vendor/monaco/monaco-bootstrap.js"
if (theme.codeEditor && theme.codeEditor.lib === 'ace') {
themeContext.asset.vendorMonaco = ''
}
activeTheme = theme.theme; activeTheme = theme.theme;
}, },
@@ -134,13 +122,9 @@ module.exports = {
} }
if (theme.page.tabicon) { if (theme.page.tabicon) {
let icon = theme.page.tabicon.icon || theme.page.tabicon url = serveFile(themeApp,"/tabicon/",theme.page.tabicon)
url = serveFile(themeApp,"/tabicon/", icon)
if (url) { if (url) {
themeContext.page.tabicon.icon = url; themeContext.page.tabicon = url;
}
if (theme.page.tabicon.colour) {
themeContext.page.tabicon.colour = theme.page.tabicon.colour
} }
} }
@@ -231,11 +215,6 @@ module.exports = {
if (theme.theme) { if (theme.theme) {
themeSettings.theme = theme.theme; themeSettings.theme = theme.theme;
} }
if (theme.hasOwnProperty("tours")) {
themeSettings.tours = theme.tours;
}
return themeApp; return themeApp;
}, },
context: async function() { context: async function() {
@@ -266,69 +245,6 @@ module.exports = {
theme.page = theme.page || {_:{}} theme.page = theme.page || {_:{}}
theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || []) theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || [])
} }
// check and load page settings from theme
if (themePlugin.page) {
if (themePlugin.page.favicon && !theme.page.favicon) {
const result = serveFilesFromTheme(
[themePlugin.page.favicon],
themeApp,
"/",
themePlugin.path
)
if(result && result.length > 0) {
// update themeContext page favicon
themeContext.page.favicon = result[0]
theme.page = theme.page || {_:{}}
theme.page._.favicon = result[0]
}
}
if (themePlugin.page.tabicon && themePlugin.page.tabicon.icon && !theme.page.tabicon) {
const result = serveFilesFromTheme(
[themePlugin.page.tabicon.icon],
themeApp,
"/page/",
themePlugin.path
)
if(result && result.length > 0) {
// update themeContext page tabicon
themeContext.page.tabicon.icon = result[0]
themeContext.page.tabicon.colour = themeContext.page.tabicon.colour || themeContext.page.tabicon.colour
theme.page = theme.page || {_:{}}
theme.page._.tabicon = theme.page._.tabicon || {}
theme.page._.tabicon.icon = themeContext.page.tabicon.icon
theme.page._.tabicon.colour = themeContext.page.tabicon.colour
}
}
// if the plugin has a title AND the users settings.js does NOT
if (themePlugin.page.title && !theme.page.title) {
themeContext.page.title = themePlugin.page.title || themeContext.page.title
}
}
// check and load header settings from theme
if (themePlugin.header) {
if (themePlugin.header.image && !theme.header.image) {
const result = serveFilesFromTheme(
[themePlugin.header.image],
themeApp,
"/header/",
themePlugin.path
)
if(result && result.length > 0) {
// update themeContext header image
themeContext.header.image = result[0]
}
}
// if the plugin has a title AND the users settings.js does NOT have a title
if (themePlugin.header.title && !theme.header.title) {
themeContext.header.title = themePlugin.header.title || themeContext.header.title
}
// if the plugin has a header url AND the users settings.js does NOT
if (themePlugin.header.url && !theme.header.url) {
themeContext.header.url = themePlugin.header.url || themeContext.header.url
}
}
theme.codeEditor = theme.codeEditor || {}
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
} }
activeThemeInitialised = true; activeThemeInitialised = true;
} }

View File

@@ -91,16 +91,7 @@ module.exports = {
}, },
editor: async function(req,res) { editor: async function(req,res) {
res.send(Mustache.render(editorTemplate,await theme.context()));
let sessionMessages;
if (req.session && req.session.messages) {
sessionMessages = JSON.stringify(req.session.messages);
delete req.session.messages
}
res.send(Mustache.render(editorTemplate,{
sessionMessages,
...await theme.context()
}));
}, },
editorResources: express.static(path.join(editorClientDir,'public')) editorResources: express.static(path.join(editorClientDir,'public'))
}; };

View File

@@ -64,14 +64,6 @@ function init(settings,_server,storage,runtimeAPI) {
} }
} }
var defaultServerSettings = {
"x-powered-by": false
}
var serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
for (var eOption in serverSettings) {
adminApp.set(eOption, serverSettings[eOption]);
}
auth.init(settings,storage); auth.init(settings,storage);
var maxApiRequestSize = settings.apiMaxLength || '5mb'; var maxApiRequestSize = settings.apiMaxLength || '5mb';
@@ -90,8 +82,6 @@ function init(settings,_server,storage,runtimeAPI) {
auth.getToken, auth.getToken,
auth.errorHandler auth.errorHandler
); );
} else if (settings.adminAuth.tokens) {
adminApp.use(passport.initialize());
} }
adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler); adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler);
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/editor-api", "name": "@node-red/editor-api",
"version": "3.1.0-beta.1", "version": "1.3.7",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -16,25 +16,25 @@
} }
], ],
"dependencies": { "dependencies": {
"@node-red/util": "3.1.0-beta.1", "@node-red/util": "1.3.7",
"@node-red/editor-client": "3.1.0-beta.1", "@node-red/editor-client": "1.3.7",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.20.2", "body-parser": "1.19.0",
"clone": "2.1.2", "clone": "2.1.2",
"cors": "2.8.5", "cors": "2.8.5",
"express-session": "1.17.3", "express-session": "1.17.1",
"express": "4.18.2", "express": "4.17.1",
"memorystore": "1.6.7", "memorystore": "1.6.6",
"mime": "3.0.0", "mime": "2.5.2",
"multer": "1.4.5-lts.1", "multer": "1.4.2",
"mustache": "4.2.0", "mustache": "4.2.0",
"oauth2orize": "1.11.1", "oauth2orize": "1.11.0",
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"passport": "0.6.0", "passport": "0.4.1",
"ws": "7.5.6" "ws": "6.2.2"
}, },
"optionalDependencies": { "optionalDependencies": {
"bcrypt": "5.1.0" "bcrypt": "3.0.6"
} }
} }

View File

@@ -1,4 +1,4 @@
Copyright OpenJS Foundation and other contributors, https://openjsf.org/ Copyright JS Foundation and other contributors, http://js.foundation
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004

269
packages/node_modules/@node-red/editor-client/locales/de/editor.json vendored Normal file → Executable file
View File

@@ -44,8 +44,7 @@
"loadNodes": "Lade Nodes __count__", "loadNodes": "Lade Nodes __count__",
"loadFlows": "Lade Flows", "loadFlows": "Lade Flows",
"importFlows": "Füge Flows dem Arbeitsbereich hinzu", "importFlows": "Füge Flows dem Arbeitsbereich hinzu",
"importError": "<p>Fehler beim Laden von Flows.</p><p>__message__</p>", "importError": "<p>Fehler beim Laden von Flows.</p><p>__message__</p>"
"loadingProject": "Lade Projekt"
}, },
"workspace": { "workspace": {
"defaultName": "Flow __number__", "defaultName": "Flow __number__",
@@ -54,16 +53,7 @@
"delete": "Sind Sie sicher, dass '__label__' gelöscht werden soll?", "delete": "Sind Sie sicher, dass '__label__' gelöscht werden soll?",
"dropFlowHere": "Hier kann der Flow eingefügt werden", "dropFlowHere": "Hier kann der Flow eingefügt werden",
"addFlow": "Flow hinzufügen", "addFlow": "Flow hinzufügen",
"addFlowToRight": "Flow zum Arbeitsbereich rechts hinzufügen",
"hideFlow": "Flow ausblenden",
"hideOtherFlows": "Andere Flows ausblenden",
"showAllFlows": "Alle Flows anzeigen",
"hideAllFlows": "Alle Flows ausblenden",
"hiddenFlows": "Liste __count__ ausgeblendeten Flow auf",
"hiddenFlows_plural": "Liste __count__ ausgeblendete Flows auf",
"showLastHiddenFlow": "Letzten ausgeblendeten Flow anzeigen",
"listFlows": "Flows auflisten", "listFlows": "Flows auflisten",
"listSubflows": "Subflows auflisten",
"status": "Status", "status": "Status",
"enabled": "Aktiviert", "enabled": "Aktiviert",
"disabled": "Deaktiviert", "disabled": "Deaktiviert",
@@ -75,8 +65,6 @@
"view": { "view": {
"view": "Ansicht", "view": "Ansicht",
"grid": "Raster", "grid": "Raster",
"storeZoom": "Zoomstufe beim Laden wiederherstellen",
"storePosition": "Scrollposition beim Laden wiederherstellen",
"showGrid": "Raster anzeigen", "showGrid": "Raster anzeigen",
"snapGrid": "Am Raster ausrichten", "snapGrid": "Am Raster ausrichten",
"gridSize": "Rastergröße", "gridSize": "Rastergröße",
@@ -94,7 +82,6 @@
"palette": { "palette": {
"show": "Palette anzeigen" "show": "Palette anzeigen"
}, },
"edit": "Bearbeiten",
"settings": "Einstellungen", "settings": "Einstellungen",
"userSettings": "Einstellungen", "userSettings": "Einstellungen",
"nodes": "Nodes", "nodes": "Nodes",
@@ -105,7 +92,7 @@
"search": "Flows durchsuchen", "search": "Flows durchsuchen",
"searchInput": "Flows durchsuchen", "searchInput": "Flows durchsuchen",
"subflows": "Subflow", "subflows": "Subflow",
"createSubflow": "Hinzufügen", "createSubflow": "Erstellen",
"selectionToSubflow": "Auswahl in Subflow umwandeln", "selectionToSubflow": "Auswahl in Subflow umwandeln",
"flows": "Flow", "flows": "Flow",
"add": "Hinzufügen", "add": "Hinzufügen",
@@ -117,43 +104,24 @@
"editPalette": "Palette verwalten", "editPalette": "Palette verwalten",
"other": "Sonstige", "other": "Sonstige",
"showTips": "Tipps anzeigen", "showTips": "Tipps anzeigen",
"showWelcomeTours": "Geführte Touren für neue Versionen anzeigen",
"help": "Node-RED-Website", "help": "Node-RED-Website",
"projects": "Projekte", "projects": "Projekt",
"projects-new": "Neu", "projects-new": "Neu",
"projects-open": "Öffnen", "projects-open": "Öffnen",
"projects-settings": "Einstellungen", "projects-settings": "Einstellungen",
"showNodeLabelDefault": "Zeige Namen von neu hinzugefügten Nodes", "showNodeLabelDefault": "Zeige Namen von neu hinzugefügten Nodes",
"codeEditor": "Code-Editor", "groups": "Gruppe",
"groups": "Gruppen",
"groupSelection": "Auswahl gruppieren", "groupSelection": "Auswahl gruppieren",
"ungroupSelection": "Gruppe auflösen", "ungroupSelection": "Gruppe auflösen",
"groupMergeSelection": "Auswahl der Gruppe hinzufügen", "groupMergeSelection": "Auswahl der Gruppe hinzufügen",
"groupRemoveSelection": "Auswahl aus der Gruppe entfernen", "groupRemoveSelection": "Auswahl aus der Gruppe entfernen"
"arrange": "Anordnen",
"alignLeft": "Links ausrichten",
"alignCenter": "Zentrieren",
"alignRight": "Rechts ausrichten",
"alignTop": "Oben ausrichten",
"alignMiddle": "Mittig ausrichten",
"alignBottom": "Unten ausrichten",
"distributeHorizontally": "Horizontal verteilen",
"distributeVertically": "Vertikal verteilen",
"moveToBack": "Nach hinten verschieben",
"moveToFront": "Nach vorne verschieben",
"moveBackwards": "Rückwärts verschieben",
"moveForwards": "Vorwärts verschieben"
} }
}, },
"actions": { "actions": {
"toggle-navigator": "Navigator ein-/ausblenden", "toggle-navigator": "Navigator ein-/ausblenden",
"zoom-out": "Verkleinern", "zoom-out": "Verkleinern",
"zoom-reset": "Vergrößerung rücksetzen", "zoom-reset": "Vergrößerung rücksetzen",
"zoom-in": "Vergrößern", "zoom-in": "Vergrößern"
"search-flows": "Flows durchsuchen",
"search-prev": "Vorherige",
"search-next": "Nächste",
"search-counter": "\"__term__\" __result__ von __count__"
}, },
"user": { "user": {
"loggedInAs": "Angemeldet als __name__", "loggedInAs": "Angemeldet als __name__",
@@ -163,52 +131,48 @@
"loginFailed": "Anmeldung fehlgeschlagen", "loginFailed": "Anmeldung fehlgeschlagen",
"notAuthorized": "Nicht berechtigt", "notAuthorized": "Nicht berechtigt",
"errors": { "errors": {
"settings": "Sie müssen angemeldet sein, um auf die Einstellungen zugreifen zu können", "settings": "Sie müssen angemeldet sein, um auf die Einstellungen zuzugreifen zu können",
"deploy": "Sie müssen angemeldet sein, um Änderungen übernehmen (deploy) zu können", "deploy": "Sie müssen angemeldet sein, um Änderungen übernehmen (deploy) zu können",
"notAuthorized": "Sie müssen angemeldet sein, um diese Aktion ausführen zu können" "notAuthorized": "Sie müssen angemeldet sein, um diese Aktion ausführen zu können"
} }
}, },
"notification": { "notification": {
"state": { "warning": "<strong>Warnung:</strong> __message__",
"flowsStopped": "Flows gestoppt",
"flowsStarted": "Flows gestartet"
},
"warning": "<strong>Warnung</strong>: __message__",
"warnings": { "warnings": {
"undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen", "undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen",
"nodeActionDisabled": "Node-Aktionen deaktiviert", "nodeActionDisabled": "Node-Aktionen deaktiviert",
"nodeActionDisabledSubflow": "Node-Aktionen innerhalb des Subflows deaktiviert", "nodeActionDisabledSubflow": "Node-Aktionen deaktiviert im Subflow",
"missing-types": "<p>Flows gestoppt aufgrund fehlender Node-Typen</p>", "missing-types": "<p>Flows gestoppt aufgrund fehlender Node-Typen</p>",
"missing-modules": "<p>Flows angehalten aufgrund fehlender Module</p>", "missing-modules": "<p>Flows angehalten aufgrund fehlender Module</p>",
"safe-mode": "<p>Flows sind im abgesicherten Modus gestoppt.</p><p>Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.</p>", "safe-mode": "<p>Flows sind im abgesicherten Modus gestoppt.</p><p>Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.</p>",
"restartRequired": "Node-RED muss neu gestartet werden, damit die Module nach Upgrade aktiviert werden", "restartRequired": "Node-RED muss neu gestartet werden, damit die Module nach Upgrade aktiviert werden",
"credentials_load_failed": "<p>Flows gestoppt, da die Credentials nicht entschlüsselt werden konnten.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>", "credentials_load_failed": "<p>Flows gestoppt, da die Berechtigungen nicht entschlüsselt werden konnten.</p><p>Die Datei mit dem Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>",
"credentials_load_failed_reset": "<p>Die Credentials konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Credentials wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Credentials werden gelöscht.</p>", "credentials_load_failed_reset": "<p>Die Berechtigungen konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Berechtigungen wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Berechtigungen werden gelöscht.</p>",
"missing_flow_file": "<p>Die Flow-Datei des Projekts wurde nicht gefunden.</p><p>Das Projekt ist nicht mit einer Flow-Datei konfiguriert.</p>", "missing_flow_file": "<p>Die Flow-Datei des Projekts wurde nicht gefunden.</p><p>Das Projekt ist nicht mit einer Flow-Datei konfiguriert.</p>",
"missing_package_file": "<p>Die Paket-Datei des Projekts wurde nicht gefunden.</p><p>In dem Projekt fehlt die 'package.json'-Datei.</p>", "missing_package_file": "<p>Die Paket-Datei des Projekts wurde nicht gefunden.</p><p>In dem Projekt fehlt die 'package.json'-Datei.</p>",
"project_empty": "<p>Das Projekt ist leer.</p><p>Soll ein Standardsatz an Projektdateien erstellen werden?<br/>Andernfalls müssen die Dateien manuell außerhalb des Editors dem Projekt hinzugefügt werden.</p>", "project_empty": "<p>Das Projekt ist leer.</p><p>Soll ein Standardsatz an Projektdateien erstellen werden?<br/>Andernfalls müssen die Dateien manuell außerhalb des Editors dem Projekt hinzugefügt werden.</p>",
"project_not_found": "<p>Das Projekt '__project__' wurde nicht gefunden.</p>", "project_not_found": "<p>Das Projekt '__project__' wurde nicht gefunden.</p>",
"git_merge_conflict": "<p>Der automatische Merge der Änderungen ist fehlgeschlagen.</p><p>Die Merge-Konflikte müssen behoben und die Ergebnisse ins Repository übertragen werden (commit).</p>" "git_merge_conflict": "<p>Der automatische Merge der Änderungen ist fehlgeschlagen.</p><p>Die Merge-Konflikte müssen behoben und die Ergebnisse ins Repository übertragen werden (commit).</p>"
}, },
"error": "<strong>Fehler</strong>: __message__", "error": "<strong>Fehler:</strong> __message__",
"errors": { "errors": {
"lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...", "lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...",
"lostConnectionReconnect": "Verbindung zum Server verloren. Wiederherstellung der Verbindung in __time__s.", "lostConnectionReconnect": "Verbindung zum Server verloren. Verbindung wird in __time__ s versucht wieder herzustellen.",
"lostConnectionTry": "Jetzt versuchen", "lostConnectionTry": "Jetzt testen",
"cannotAddSubflowToItself": "Subflow kann nicht zu sich selbst hinzugefügt werden", "cannotAddSubflowToItself": "Subflow kann nicht zu sich selbst hinzugefügt werden",
"cannotAddCircularReference": "Subflow kann nicht hinzugefügt werden, da ein zirkulärer Bezug erkannt wurde", "cannotAddCircularReference": "Subflow kann nicht hinzugefügt werden, da ein zirkulärer Bezug erkannt wurde",
"unsupportedVersion": "<p>Nicht unterstützte Version von Node.js erkannt.</p><p>Es muss ein Upgrade auf das neueste LTS-Release von Node.js durchgeführt werden.</p>", "unsupportedVersion": "<p>Nicht unterstützte Version von Node.js erkannt.</p><p>Es muss ein Upgrade auf das neueste LTS-Release von Node.js durchgeführt werden.</p>",
"failedToAppendNode": "<p>Fehler beim Laden von '__module__'.</p><p>__error__</p>" "failedToAppendNode": "<p>Fehler beim Laden von '__module__'.</p><p>__error__</p>"
}, },
"project": { "project": {
"change-branch": "Wechsel in den lokalen Branch '__project__'", "change-branch": "Wechsel in den Branch '__project__'",
"merge-abort": "Git-Merge abgebrochen", "merge-abort": "Merge abgebrochen",
"loaded": "Projekt '__project__' geladen", "loaded": "Projekt '__project__' geladen",
"updated": "Projekt '__project__' aktualisiert", "updated": "Projekt '__project__' aktualisiert",
"pull": "Projekt '__project__' erneut geladen", "pull": "Projekt '__project__' erneut geladen",
"revert": "Änderungen im Projekt '__project__' rückgängig gemacht", "revert": "Änderungen im Projekt '__project__' rückgängig gemacht",
"merge-complete": "Git-Merge abgeschlossen", "merge-complete": "Merge abgeschlossen",
"setupCredentials": "Credentials einrichten", "setupCredentials": "Berechtigungen einrichten",
"setupProjectFiles": "Projektdateien einrichten", "setupProjectFiles": "Projektdateien einrichten",
"no": "Nein, Danke", "no": "Nein, Danke",
"createDefault": "Standardprojektdateien erstellen", "createDefault": "Standardprojektdateien erstellen",
@@ -216,13 +180,12 @@
}, },
"label": { "label": {
"manage-project-dep": "Projektabhängigkeiten verwalten", "manage-project-dep": "Projektabhängigkeiten verwalten",
"setup-cred": "Credentials einrichten", "setup-cred": "Berechtigungen einrichten",
"setup-project": "Projektdateien einrichten", "setup-project": "Projektdateien einrichten",
"create-default-package": "Standardpaketdatei erstellen", "create-default-package": "Standardpaketdatei erstellen",
"no-thanks": "Nein, Danke", "no-thanks": "Nein, Danke",
"create-default-project": "Standardprojektdateien erstellen", "create-default-project": "Standardprojektdateien erstellen",
"show-merge-conflicts": "Merge-Konflikte anzeigen", "show-merge-conflicts": "Merge-Konflikte anzeigen"
"unknownNodesButton": "Nach unbekannten Nodes suchen"
} }
}, },
"clipboard": { "clipboard": {
@@ -240,17 +203,17 @@
"subflow_plural": "__count__ Subflows", "subflow_plural": "__count__ Subflows",
"replacedNodes": "__count__ Node ersetzt", "replacedNodes": "__count__ Node ersetzt",
"replacedNodes_plural": "__count__ Nodes ersetzt", "replacedNodes_plural": "__count__ Nodes ersetzt",
"pasteNodes": "Flow-JSON einfügen oder", "pasteNodes": "Flow-JSON hier einfügen oder",
"selectFile": "Datei für Import auswählen", "selectFile": "Datei für Import auswählen",
"importNodes": "Import", "importNodes": "Import",
"exportNodes": "Export", "exportNodes": "Export",
"download": "Download", "download": "Download",
"importUnrecognised": "Nicht erkannten Typ importiert:", "importUnrecognised": "Importierter Typ nicht erkannt:",
"importUnrecognised_plural": "Nicht erkannte Typen importiert:", "importUnrecognised_plural": "Importierte Typen nicht erkannt:",
"importDuplicate": "Doppelten Node importiert:", "importDuplicate": "Importiertes doppeltes Node:",
"importDuplicate_plural": "Doppelte Nodes importiert:", "importDuplicate_plural": "Importierte doppelte Nodes:",
"nodesExported": "Nodes in die Zwischenablage exportiert", "nodesExported": "Nodes in der Zwischenablage abgelegt",
"nodesImported": "Importiert:", "nodesImported": "Eingefügt:",
"nodeCopied": "__count__ Node kopiert", "nodeCopied": "__count__ Node kopiert",
"nodeCopied_plural": "__count__ Nodes kopiert", "nodeCopied_plural": "__count__ Nodes kopiert",
"groupCopied": "__count__ Gruppe kopiert", "groupCopied": "__count__ Gruppe kopiert",
@@ -266,11 +229,11 @@
"all": "Alle Flows", "all": "Alle Flows",
"compact": "Kompakt", "compact": "Kompakt",
"formatted": "Formatiert", "formatted": "Formatiert",
"copy": "In Zwischenablage kopieren", "copy": "In Zwischenablage exportieren",
"export": "In Bibliothek exportieren", "export": "In Bibliothek exportieren",
"exportAs": "Exportiere als", "exportAs": "Exportiere als",
"overwrite": "Ersetzen", "overwrite": "Ersetzen",
"exists": "<p><b>\"__file__\"</b> existiert bereits.</p><p>Soll sie ersetzt werden?</p>" "exists": "<p>'__file__' existiert bereits.</p><p>Soll sie ersetzt werden?</p>"
}, },
"import": { "import": {
"import": "Importiere in", "import": "Importiere in",
@@ -300,19 +263,13 @@
"modifiedFlowsDesc": "Übernimmt nur Flows, die geänderte Nodes enthalten", "modifiedFlowsDesc": "Übernimmt nur Flows, die geänderte Nodes enthalten",
"modifiedNodes": "Geänderte Nodes", "modifiedNodes": "Geänderte Nodes",
"modifiedNodesDesc": "Übernimmt nur Nodes, die sich geändert haben", "modifiedNodesDesc": "Übernimmt nur Nodes, die sich geändert haben",
"startFlows": "Start",
"startFlowsDesc": "Flows starten",
"stopFlows": "Stop",
"stopFlowsDesc": "Flows stoppen",
"restartFlows": "Flows neustarten", "restartFlows": "Flows neustarten",
"restartFlowsDesc": "Startet die aktuell übernommenen Flows (ohne vorheriges Deploy)", "restartFlowsDesc": "Startet die aktuell übernommenen Flows (ohne vorheriges Deploy)",
"successfulDeploy": "Erfolgreich übernommen (deploy)", "successfulDeploy": "Erfolgreich übernommen (deploy)",
"successfulRestart": "Flows erfolgreich neugestartet", "successfulRestart": "Flows erfolgreich neugestartet",
"deployFailed": "Übernahme (deploy) fehlgeschlagen: __message__", "deployFailed": "Übernahme (deploy) fehlgeschlagen: __message__",
"unusedConfigNodes": "Einige Konfigurations-Nodes werden nicht verwendet.", "unusedConfigNodes": "Einige Konfigurations-Nodes werden nicht verwendet.",
"unusedConfigNodesButton": "Suche nach unbenutzten Konfigurations-Nodes", "unusedConfigNodesLink": "Hier klicken, um sie anzuschauen.",
"unknownNodesButton": "Suche nach unbekannten Nodes",
"invalidNodesButton": "Suche nach ungültigen Nodes",
"errors": { "errors": {
"noResponse": "Keine Antwort vom Server" "noResponse": "Keine Antwort vom Server"
}, },
@@ -385,7 +342,7 @@
"confirmDelete": "Sind Sie sicher mit dem Löschen dieses Subflows?", "confirmDelete": "Sind Sie sicher mit dem Löschen dieses Subflows?",
"info": "Beschreibung", "info": "Beschreibung",
"category": "Kategorie", "category": "Kategorie",
"module": "Modul", "module": "Module",
"license": "Lizenz", "license": "Lizenz",
"licenseNone": "Keine", "licenseNone": "Keine",
"licenseOther": "Andere", "licenseOther": "Andere",
@@ -395,10 +352,10 @@
"keys": "Schlüsselwörter", "keys": "Schlüsselwörter",
"keysPlaceholder": "Komma-getrennte Schlüsselwörter", "keysPlaceholder": "Komma-getrennte Schlüsselwörter",
"author": "Author", "author": "Author",
"authorPlaceholder": "Ihr Name <email@example.com>", "authorPlaceholder": "Dein Name <email@beispiel.de>",
"desc": "Beschreibung", "desc": "Beschreibung",
"env": { "env": {
"restore": "Subflow-Standard wiederherstellen", "restore": "Stelle auf Subflow-Standard zurück",
"remove": "Entferne Umgebungsvariable" "remove": "Entferne Umgebungsvariable"
}, },
"errors": { "errors": {
@@ -407,9 +364,9 @@
} }
}, },
"group": { "group": {
"editGroup": "Bearbeite Gruppe: __name__", "editGroup": "Editiere Gruppe: __name__",
"errors": { "errors": {
"cannotCreateDiffGroups": "Kann keine Gruppe mit Nodes von anderen Gruppen erstellen", "cannotCreateDiffGroups": "Kann keine Gruppe erzeugen mit Nodes von verschiedenen Gruppen",
"cannotAddSubflowPorts": "Kann keine Subflow-Anschlüsse zu einer Gruppe hinzufügen" "cannotAddSubflowPorts": "Kann keine Subflow-Anschlüsse zu einer Gruppe hinzufügen"
} }
}, },
@@ -423,7 +380,7 @@
"addNewConfig": "Neuen Konfigurations-Node '__type__' hinzufügen", "addNewConfig": "Neuen Konfigurations-Node '__type__' hinzufügen",
"editNode": "Node '__type__' bearbeiten", "editNode": "Node '__type__' bearbeiten",
"editConfig": "Konfigurations-Node '__type__' bearbeiten", "editConfig": "Konfigurations-Node '__type__' bearbeiten",
"addNewType": "Neuen Typ '__type__' hinzufügen ...", "addNewType": "Neuen Typ '__type__' hinzufügen",
"nodeProperties": "Node-Eigenschaften", "nodeProperties": "Node-Eigenschaften",
"label": "Name", "label": "Name",
"color": "Farbe", "color": "Farbe",
@@ -443,10 +400,10 @@
"icon": "Icon", "icon": "Icon",
"inputType": "Eingangstyp", "inputType": "Eingangstyp",
"selectType": "Wähle Typen ...", "selectType": "Wähle Typen ...",
"loadCredentials": "Lade Node-Credentials", "loadCredentials": "Lade Node-Berechtigungen",
"inputs": { "inputs": {
"input": "Eingang", "input": "Eingang",
"select": "Auswahl", "select": "hle",
"checkbox": "Checkbox", "checkbox": "Checkbox",
"spinner": "Spinner", "spinner": "Spinner",
"none": "Kein", "none": "Kein",
@@ -459,7 +416,7 @@
"json": "JSON", "json": "JSON",
"bin": "buffer", "bin": "buffer",
"env": "Umgebungsvariable", "env": "Umgebungsvariable",
"cred": "Credentials" "cred": "Berechtigung"
}, },
"menu": { "menu": {
"input": "Eingang", "input": "Eingang",
@@ -479,7 +436,7 @@
"errors": { "errors": {
"scopeChange": "Wenn Sie den Geltungsbereich (scope) ändern, wird er für Nodes in anderen Flows nicht verfügbar sein", "scopeChange": "Wenn Sie den Geltungsbereich (scope) ändern, wird er für Nodes in anderen Flows nicht verfügbar sein",
"invalidProperties": "Ungültige Eigenschaften:", "invalidProperties": "Ungültige Eigenschaften:",
"credentialLoadFailed": "Laden der Node-Credentials fehlgeschlagen" "credentialLoadFailed": "Laden der Node-Berechtigungen fehlgeschlagen"
} }
}, },
"keyboard": { "keyboard": {
@@ -489,27 +446,23 @@
"shortcut": "Tastenkürzel", "shortcut": "Tastenkürzel",
"scope": "Geltungsbereich", "scope": "Geltungsbereich",
"unassigned": "Nicht zugeordnet", "unassigned": "Nicht zugeordnet",
"global": "Global", "global": "global",
"workspace": "Arbeitsbereich", "workspace": "Arbeitsbereich",
"selectAll": "Alles auswählen", "selectAll": "Alle Nodes auswählen",
"selectNone": "Alles abwählen",
"selectAllConnected": "Alle verbundenen Nodes auswählen", "selectAllConnected": "Alle verbundenen Nodes auswählen",
"addRemoveNode": "Node aus Auswahl hinzufügen/entfernen", "addRemoveNode": "Node aus Auswahl hinzufügen/entfernen",
"editSelected": "Ausgewählten Node bearbeiten", "editSelected": "Ausgewählten Node bearbeiten",
"deleteSelected": "Ausgewählte Nodes oder Links löschen", "deleteSelected": "Ausgewählte Nodes oder Links löschen",
"importNode": "Nodes importieren", "importNode": "Node importieren",
"exportNode": "Nodes exportieren", "exportNode": "Node exportieren",
"nudgeNode": "Ausgewählte Nodes verschieben (1px)", "nudgeNode": "Ausgewählte Nodes verschieben (1px)",
"moveNode": "Ausgewählte Nodes verschieben (20px)", "moveNode": "Ausgewählte Nodes verschieben (20px)",
"toggleSidebar": "Seitenleiste ein-/ausblenden", "toggleSidebar": "Seitenleiste ein-/ausblenden",
"togglePalette": "Palette ein-/ausblenden", "togglePalette": "Palette ein-/ausblenden",
"copyNode": "Ausgewählte Nodes kopieren", "copyNode": "Ausgewählte Nodes kopieren",
"cutNode": "Ausgewählte Nodes ausschneiden", "cutNode": "Ausgewählte Nodes ausschneiden",
"pasteNode": "Nodes einfügen", "pasteNode": "Node einfügen",
"copyGroupStyle": "Gruppenstil kopieren",
"pasteGroupStyle": "Gruppenstil einfügen",
"undoChange": "Letzte Änderung rückgängig machen", "undoChange": "Letzte Änderung rückgängig machen",
"redoChange": "Letzte Änderung wiederholen",
"searchBox": "Suchfeld öffnen", "searchBox": "Suchfeld öffnen",
"managePalette": "Palette verwalten", "managePalette": "Palette verwalten",
"actionList": "Aktionsliste" "actionList": "Aktionsliste"
@@ -535,7 +488,7 @@
"palette": { "palette": {
"noInfo": "Keine Informationen verfügbar", "noInfo": "Keine Informationen verfügbar",
"filter": "Nodes filtern", "filter": "Nodes filtern",
"search": "Module durchsuchen", "search": "Modules durchsuchen",
"addCategory": "Neu hinzufügen ...", "addCategory": "Neu hinzufügen ...",
"label": { "label": {
"subflows": "Subflows", "subflows": "Subflows",
@@ -564,8 +517,7 @@
"nodeEnabled_plural": "Nodes aktiviert:", "nodeEnabled_plural": "Nodes aktiviert:",
"nodeDisabled": "Node deaktiviert:", "nodeDisabled": "Node deaktiviert:",
"nodeDisabled_plural": "Nodes deaktiviert:", "nodeDisabled_plural": "Nodes deaktiviert:",
"nodeUpgraded": "Upgrade von Node-Modul __module__ auf Version __version__ durchgeführt", "nodeUpgraded": "Upgrade von Node-Modul __module__ auf Version __version__ durchgeführt"
"unknownNodeRegistered": "Fehler beim Laden des Nodes: <ul><li>__type__<br>__error__</li></ul>"
}, },
"editor": { "editor": {
"title": "Palette verwalten", "title": "Palette verwalten",
@@ -681,8 +633,15 @@
"outline": "Entwurf", "outline": "Entwurf",
"empty": "leer", "empty": "leer",
"globalConfig": "Globale Konfigurations-Nodes", "globalConfig": "Globale Konfigurations-Nodes",
"triggerAction": "Aktion auslösen", "triggerAction": "Auslösen",
"find": "Suche im Arbeitsbereich" "find": "Suche im Arbeitsbereich",
"search": {
"configNodes": "Konfigurations-Nodes",
"unusedConfigNodes": "Unbenutzte Konfigurations-Nodes",
"invalidNodes": "Ungültige Nodes",
"uknownNodes": "Unbekannte Nodes",
"unusedSubflows": "Unbenutzte Subflows"
}
}, },
"help": { "help": {
"name": "Hilfe", "name": "Hilfe",
@@ -692,8 +651,7 @@
"showHelp": "Hilfe zeigen", "showHelp": "Hilfe zeigen",
"showInOutline": "Zeige im Editor", "showInOutline": "Zeige im Editor",
"showTopics": "Zeige Hilfethemen", "showTopics": "Zeige Hilfethemen",
"noHelp": "Kein Hilfethema ausgewählt", "noHelp": "Kein Hilfethema ausgewählt"
"changeLog": "Änderungsprotokoll"
}, },
"config": { "config": {
"name": "Konfigurations-Node", "name": "Konfigurations-Node",
@@ -747,7 +705,7 @@
"addToProject": "Zu Projekt hinzufügen", "addToProject": "Zu Projekt hinzufügen",
"files": "Dateien", "files": "Dateien",
"flow": "Flow", "flow": "Flow",
"credentials": "Credentials", "credentials": "Berechtigungen",
"package": "Paket", "package": "Paket",
"packageCreate": "Datei wird erstellt beim Speichern der Änderungen", "packageCreate": "Datei wird erstellt beim Speichern der Änderungen",
"fileNotExist": "Datei existiert nicht", "fileNotExist": "Datei existiert nicht",
@@ -760,7 +718,7 @@
"changeTheEncryptionKey": "Schlüssel ändern", "changeTheEncryptionKey": "Schlüssel ändern",
"currentKey": "Aktueller Schlüssel", "currentKey": "Aktueller Schlüssel",
"newKey": "Neuer Schlüssel", "newKey": "Neuer Schlüssel",
"credentialsAlert": "Dadurch werden alle vorhandenen Credentials gelöscht", "credentialsAlert": "Dadurch werden alle vorhandenen Berechtigungen gelöscht",
"versionControl": "Versionsverwaltung (Git)", "versionControl": "Versionsverwaltung (Git)",
"branches": "Branches", "branches": "Branches",
"noBranches": "Keine Branches", "noBranches": "Keine Branches",
@@ -785,7 +743,7 @@
"userName": "Benutzername", "userName": "Benutzername",
"email": "E-Mail", "email": "E-Mail",
"workflow": "Arbeitsablauf", "workflow": "Arbeitsablauf",
"workfowTip": "Wählen Sie Ihren bevorzugten Git-Arbeitsablauf (Workflow)", "workfowTip": "Wähle deinen bevorzugten Git-Arbeitsablauf",
"workflowManual": "Manuell", "workflowManual": "Manuell",
"workflowManualTip": "Alle Änderungen müssen manuell übertragen werden (commit) über die Seitenleiste 'Projekthistorie'", "workflowManualTip": "Alle Änderungen müssen manuell übertragen werden (commit) über die Seitenleiste 'Projekthistorie'",
"workflowAuto": "Automatisch", "workflowAuto": "Automatisch",
@@ -896,7 +854,7 @@
"date": "timestamp", "date": "timestamp",
"jsonata": "JSONata", "jsonata": "JSONata",
"env": "Umgebungsvariable", "env": "Umgebungsvariable",
"cred": "Credentials" "cred": "Berechtigung"
} }
}, },
"editableList": { "editableList": {
@@ -904,20 +862,8 @@
"addTitle": "Element hinzufügen" "addTitle": "Element hinzufügen"
}, },
"search": { "search": {
"history": "Suchhistorie",
"clear": "Leeren",
"empty": "Keine Übereinstimmungen gefunden", "empty": "Keine Übereinstimmungen gefunden",
"addNode": "Node hinzufügen ...", "addNode": "Node hinzufügen ..."
"options": {
"configNodes": "Konfigurations-Nodes",
"unusedConfigNodes": "Unbenutzte Konfigurations-Nodes",
"invalidNodes": "Ungültige Nodes",
"uknownNodes": "Unbekannte Nodes",
"unusedSubflows": "Unbenutzte Subflows",
"hiddenFlows": "Versteckte Flows",
"modifiedNodes": "Geänderte Nodes",
"thisFlow": "Aktueller Flow"
}
}, },
"expressionEditor": { "expressionEditor": {
"functions": "Funktionen", "functions": "Funktionen",
@@ -938,9 +884,6 @@
"eval": "Fehler beim Auswerten des Ausdrucks\n__message__" "eval": "Fehler beim Auswerten des Ausdrucks\n__message__"
} }
}, },
"monaco": {
"setTheme": "Thema auswählen"
},
"jsEditor": { "jsEditor": {
"title": "JavaScript-Editor" "title": "JavaScript-Editor"
}, },
@@ -950,10 +893,8 @@
"jsonEditor": { "jsonEditor": {
"title": "JSON-Editor", "title": "JSON-Editor",
"format": "JSON formatieren", "format": "JSON formatieren",
"rawMode": "Bearbeite JSON", "rawMode": "JSON-Editor",
"uiMode": "Visueller Editor", "uiMode": "Visueller Editor",
"rawMode-readonly": "JSON",
"uiMode-readonly": "Visuell",
"insertAbove": "Oberhalb einfügen", "insertAbove": "Oberhalb einfügen",
"insertBelow": "Unterhalb einfügen", "insertBelow": "Unterhalb einfügen",
"addItem": "Element hinzufügen", "addItem": "Element hinzufügen",
@@ -1024,7 +965,7 @@
"clone": "Projekt klonen", "clone": "Projekt klonen",
"desc0": "Wenn Sie bereits über ein Git-Repository verfügen, das ein Projekt enthält, können Sie es klonen, um damit zu arbeiten.", "desc0": "Wenn Sie bereits über ein Git-Repository verfügen, das ein Projekt enthält, können Sie es klonen, um damit zu arbeiten.",
"already-exists": "Das Projekt ist bereits vorhanden", "already-exists": "Das Projekt ist bereits vorhanden",
"must-contain": "Darf nur A-Z 0-9 _ - enthalten", "must-contain": "Darf nur A-Z 0-9 _ enthalten",
"project-name": "Projektname", "project-name": "Projektname",
"no-info-in-url": "Geben Sie Benutzername & Passwort nicht innerhalb der URL vor", "no-info-in-url": "Geben Sie Benutzername & Passwort nicht innerhalb der URL vor",
"git-url": "Git-Repository-URL", "git-url": "Git-Repository-URL",
@@ -1036,7 +977,7 @@
"passphrase": "Passphrase", "passphrase": "Passphrase",
"ssh-key-desc": "Bevor Sie ein Repository über SSH lokal klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zugreifen zu können", "ssh-key-desc": "Bevor Sie ein Repository über SSH lokal klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zugreifen zu können",
"ssh-key-add": "SSH-Schlüssel hinzufügen", "ssh-key-add": "SSH-Schlüssel hinzufügen",
"credential-key": "Schlüssel für Credentials", "credential-key": "Schlüssel für Berechtigungen",
"cant-get-ssh-key": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden", "cant-get-ssh-key": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden",
"already-exists2": "bereits vorhanden", "already-exists2": "bereits vorhanden",
"git-error": "Git-Fehler", "git-error": "Git-Fehler",
@@ -1048,27 +989,27 @@
"create": "Erstellen Sie Ihre Projektdateien", "create": "Erstellen Sie Ihre Projektdateien",
"desc0": "Ein Projekt enthält Ihre Flow-Dateien, eine README-Datei und die 'package.json'-Datei.", "desc0": "Ein Projekt enthält Ihre Flow-Dateien, eine README-Datei und die 'package.json'-Datei.",
"desc1": "Es kann alle anderen Dateien enthalten, die im Git-Repository verwaltet werden sollen.", "desc1": "Es kann alle anderen Dateien enthalten, die im Git-Repository verwaltet werden sollen.",
"desc2": "Ihre vorhandenen Flow- und Credential-Dateien werden in das Projekt kopiert.", "desc2": "Ihre vorhandenen Flow- und Berechtigungs-Dateien werden in das Projekt kopiert.",
"flow-file": "Flow-Datei", "flow-file": "Flow-Datei",
"credentials-file": "Datei mit Credentials" "credentials-file": "Datei mit Berechtigungen"
}, },
"encryption-config": { "encryption-config": {
"setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Credentials", "setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Berechtigungen",
"desc0": "Die Datei mit den Flow-Credentials kann verschlüsselt werden, um ihren Inhalt zu schützen.", "desc0": "Die Datei mit den Flow-Berechtigungen kann verschlüsselt werden, um ihren Inhalt zu schützen.",
"desc1": "Wenn Sie diese Credentials in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.", "desc1": "Wenn Sie diese Berechtigungen in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.",
"desc2": "Die Datei mit den Flow-Credentials ist derzeit nicht verschlüsselt.", "desc2": "Die Datei mit den Flow-Berechtigungen ist derzeit nicht verschlüsselt.",
"desc3": "D.h. ihr Inhalt (z.B. Passwörter und Zugriffs-Tokens) kann von jedem mit Zugriff auf die Datei gelesen werden.", "desc3": "D.h. ihr Inhalt (z.B. Passwörter und Zugriffs-Tokens) kann von jedem mit Zugriff auf die Datei gelesen werden.",
"desc4": "Wenn Sie diese Credentials in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.", "desc4": "Wenn Sie diese Berechtigungen in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.",
"desc5": "Ihre Datei mit den Flow-Credentials wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.", "desc5": "Ihre Datei mit den Flow-Berechtigungen wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.",
"desc6": "Die Datei mit den Flow-Credentials wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.", "desc6": "Die Datei mit den Flow-Berechtigungen wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.",
"desc7": "Der Schlüssel wird separat von den Projektdateien gespeichert. Sie müssen den Schlüssel angeben, damit dieses Projekt auch in einem anderen Node-RED-System verwendet werden kann.", "desc7": "Der Schlüssel wird separat von den Projektdateien gespeichert. Sie müssen den Schlüssel angeben, damit dieses Projekt auch in einem anderen Node-RED-System verwendet werden kann.",
"credentials": "Credentials", "credentials": "Berechtigung",
"enable": "Verschlüsselung aktivieren", "enable": "Verschlüsselung aktivieren",
"disable": "Verschlüsselung deaktivieren", "disable": "Verschlüsselung deaktivieren",
"disabled": "deaktiviert", "disabled": "deaktiviert",
"copy": "Vorhandenen Schlüssel ersetzen", "copy": "Vorhandenen Schlüssel ersetzen",
"use-custom": "Eigenen Schlüssel verwenden", "use-custom": "Eigenen Schlüssel verwenden",
"desc8": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden", "desc8": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden",
"create-project-files": "Projektdateien erstellen", "create-project-files": "Projektdateien erstellen",
"create-project": "Projekt erstellen", "create-project": "Projekt erstellen",
"already-exists": "bereits vorhanden", "already-exists": "bereits vorhanden",
@@ -1082,7 +1023,7 @@
"desc2": "Im Tab 'Commit-Historie' in der Seitenleiste werden alle Dateien angezeigt, die sich in Ihrem Projekt geändert haben, und um sie ins lokale Repository zu übertragen (commit). Es zeigt Ihnen eine vollständige Historie Ihrer Commits an und ermöglicht es Ihnen, Ihre Commits in ein (remote) Server-Repository zu schieben (push)." "desc2": "Im Tab 'Commit-Historie' in der Seitenleiste werden alle Dateien angezeigt, die sich in Ihrem Projekt geändert haben, und um sie ins lokale Repository zu übertragen (commit). Es zeigt Ihnen eine vollständige Historie Ihrer Commits an und ermöglicht es Ihnen, Ihre Commits in ein (remote) Server-Repository zu schieben (push)."
}, },
"create": { "create": {
"projects": "Projekte", "projects": "Projekt",
"already-exists": "Das Projekt ist bereits vorhanden", "already-exists": "Das Projekt ist bereits vorhanden",
"must-contain": "Darf nur A-Z 0-9 _ enthalten", "must-contain": "Darf nur A-Z 0-9 _ enthalten",
"no-info-in-url": "Geben Sie Benutzername & Passwort nicht innerhalb der URL vor", "no-info-in-url": "Geben Sie Benutzername & Passwort nicht innerhalb der URL vor",
@@ -1093,12 +1034,12 @@
"desc": "Beschreibung", "desc": "Beschreibung",
"opt": "Optional", "opt": "Optional",
"flow-file": "Flow-Datei", "flow-file": "Flow-Datei",
"credentials": "Credentials", "credentials": "Berechtigungen",
"enable-encryption": "Verschlüsselung aktivieren", "enable-encryption": "Verschlüsselung aktivieren",
"disable-encryption": "Verschlüsselung deaktivieren", "disable-encryption": "Verschlüsselung deaktivieren",
"encryption-key": "Schlüssel", "encryption-key": "Schlüssel",
"desc0": "Eine Ausdruck, mit der Sie Ihre Credentials schützen", "desc0": "Eine Floskel, mit der Sie Ihre Berechtigungen schützen",
"desc1": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden", "desc1": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden",
"git-url": "Git-Repository-URL", "git-url": "Git-Repository-URL",
"protocols": "https://, ssh:// oder file://", "protocols": "https://, ssh:// oder file://",
"auth-failed": "Authentifizierung fehlgeschlagen", "auth-failed": "Authentifizierung fehlgeschlagen",
@@ -1108,15 +1049,14 @@
"passphrase": "Passphrase", "passphrase": "Passphrase",
"desc2": "Bevor Sie ein Repository über SSH klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zu zugreifen", "desc2": "Bevor Sie ein Repository über SSH klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zu zugreifen",
"add-ssh-key": "Einen SSH-Schlüssel hinzufügen", "add-ssh-key": "Einen SSH-Schlüssel hinzufügen",
"credentials-encryption-key": "Schlüssel für Credentials", "credentials-encryption-key": "Schlüssel für Berechtigungen",
"already-exists-2": "bereits vorhanden", "already-exists-2": "bereits vorhanden",
"git-error": "Git-Fehler", "git-error": "Git-Fehler",
"con-failed": "Verbindung fehlgeschlagen", "con-failed": "Verbindung fehlgeschlagen",
"not-git": "Kein Git-Repository", "not-git": "Kein Git-Repository",
"no-resource": "Repository nicht gefunden", "no-resource": "Repository nicht gefunden",
"cant-get-ssh-key-path": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden.", "cant-get-ssh-key-path": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden.",
"unexpected_error": "unerwarteter_Fehler", "unexpected_error": "unerwarteter_Fehler"
"clearContext": "Kontextdaten löschen beim Projektwechsel"
}, },
"delete": { "delete": {
"confirm": "Sind Sie sicher, dass dieses Projekt gelöscht werden soll?" "confirm": "Sind Sie sicher, dass dieses Projekt gelöscht werden soll?"
@@ -1163,44 +1103,13 @@
"preview": "Vorschau", "preview": "Vorschau",
"defaultValue": "Standardwert" "defaultValue": "Standardwert"
}, },
"tourGuide": {
"takeATour": "Tour starten",
"start": "Start",
"next": "Nächste",
"welcomeTours": "Welcome Tours"
},
"diagnostics": {
"title": "System-Informationen"
},
"languages": { "languages": {
"de": "Deutsch", "de": "German",
"en-US": "Englisch", "en-US": "English",
"ja": "Japanisch", "ja": "Japanese",
"ko": "Koreanisch", "ko": "Korean",
"ru": "Russisch", "ru": "Russian",
"zh-CN": "Chinesisch (Vereinfacht)", "zh-CN": "Chinese(Simplified)",
"zh-TW": "Chinesisch (Traditionell)" "zh-TW": "Chinese(Traditional)"
},
"validator": {
"errors": {
"invalid-json": "Ungültige JSON-Daten: __error__",
"invalid-json-prop": "__prop__: ungültige JSON-Daten: __error__",
"invalid-prop": "Ungültiger Eigenschaftsausdruck",
"invalid-prop-prop": "__prop__: ungültiger Eigenschaftsausdruck",
"invalid-num": "Ungültige Nummer",
"invalid-num-prop": "__prop__: ungültige Nummer",
"invalid-regexp": "Ungültiges Eingabemuster",
"invalid-regex-prop": "__prop__: ungültiges Eingabemuster",
"missing-required-prop": "__prop__: Eigenschaftswert fehlt",
"invalid-config": "__prop__: ungültige Konfigurations-Node",
"missing-config": "__prop__: Konfigurations-Node fehlt",
"validation-error": "__prop__: Validierungsfehler: __node__, __id__: __error__"
}
},
"contextMenu": {
"insert": "Einfügen",
"node": "Node",
"junction": "Kreuzung",
"linkNodes": "Verknüpfe Nodes"
} }
} }

View File

View File

View File

@@ -3,7 +3,7 @@
"label": { "label": {
"name": "Name", "name": "Name",
"ok": "Ok", "ok": "Ok",
"done": "Done", "done":"Done",
"cancel": "Cancel", "cancel": "Cancel",
"delete": "Delete", "delete": "Delete",
"close": "Close", "close": "Close",
@@ -23,11 +23,7 @@
"position": "Position", "position": "Position",
"enable": "Enable", "enable": "Enable",
"disable": "Disable", "disable": "Disable",
"upload": "Upload", "upload": "Upload"
"lock": "Lock",
"unlock": "Unlock",
"locked": "Locked",
"unlocked": "Unlocked"
}, },
"type": { "type": {
"string": "string", "string": "string",
@@ -57,38 +53,19 @@
"confirmDelete": "Confirm delete", "confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?", "delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here", "dropFlowHere": "Drop the flow here",
"dropImageHere": "Drop the image here", "addFlow": "Add Flow",
"addFlow": "Add flow", "listFlows": "List Flows",
"addFlowToRight": "Add flow to the right",
"closeFlow": "Close flow",
"hideFlow": "Hide flow",
"hideOtherFlows": "Hide other flows",
"showAllFlows": "Show all flows (__count__ hidden)",
"hideAllFlows": "Hide all flows",
"hiddenFlows": "List __count__ hidden flow",
"hiddenFlows_plural": "List __count__ hidden flows",
"showLastHiddenFlow": "Reopen hidden flow",
"listFlows": "List flows",
"listSubflows": "List subflows",
"status": "Status", "status": "Status",
"enabled": "Enabled", "enabled": "Enabled",
"disabled": "Disabled", "disabled":"Disabled",
"info": "Description", "info": "Description",
"selectNodes": "Click nodes to select", "selectNodes": "Click nodes to select"
"enableFlow": "Enable flow",
"disableFlow": "Disable flow",
"lockFlow": "Lock flow",
"unlockFlow": "Unlock flow",
"moveToStart": "Move flow to start",
"moveToEnd": "Move flow to end"
}, },
"menu": { "menu": {
"label": { "label": {
"view": { "view": {
"view": "View", "view": "View",
"grid": "Grid", "grid": "Grid",
"storeZoom": "Restore zoom level on load",
"storePosition": "Restore scroll position on load",
"showGrid": "Show grid", "showGrid": "Show grid",
"snapGrid": "Snap to grid", "snapGrid": "Snap to grid",
"gridSize": "Grid size", "gridSize": "Grid size",
@@ -106,14 +83,12 @@
"palette": { "palette": {
"show": "Show palette" "show": "Show palette"
}, },
"edit": "Edit",
"settings": "Settings", "settings": "Settings",
"userSettings": "User Settings", "userSettings": "User Settings",
"nodes": "Nodes", "nodes": "Nodes",
"displayStatus": "Show node status", "displayStatus": "Show node status",
"displayConfig": "Configuration nodes", "displayConfig": "Configuration nodes",
"import": "Import", "import": "Import",
"importExample": "Import Example Flow",
"export": "Export", "export": "Export",
"search": "Search flows", "search": "Search flows",
"searchInput": "search your flows", "searchInput": "search your flows",
@@ -127,46 +102,27 @@
"keyboardShortcuts": "Keyboard shortcuts", "keyboardShortcuts": "Keyboard shortcuts",
"login": "Login", "login": "Login",
"logout": "Logout", "logout": "Logout",
"editPalette": "Manage palette", "editPalette":"Manage palette",
"other": "Other", "other": "Other",
"showTips": "Show tips", "showTips": "Show tips",
"showWelcomeTours": "Show guided tours for new versions",
"help": "Node-RED website", "help": "Node-RED website",
"projects": "Projects", "projects": "Projects",
"projects-new": "New", "projects-new": "New",
"projects-open": "Open", "projects-open": "Open",
"projects-settings": "Project Settings", "projects-settings": "Project Settings",
"showNodeLabelDefault": "Show label of newly added nodes", "showNodeLabelDefault": "Show label of newly added nodes",
"codeEditor": "Code Editor",
"groups": "Groups", "groups": "Groups",
"groupSelection": "Group selection", "groupSelection": "Group selection",
"ungroupSelection": "Ungroup selection", "ungroupSelection": "Ungroup selection",
"groupMergeSelection": "Merge selection", "groupMergeSelection": "Merge selection",
"groupRemoveSelection": "Remove from group", "groupRemoveSelection": "Remove from group"
"arrange": "Arrange",
"alignLeft": "Align to left",
"alignCenter": "Align to center",
"alignRight": "Align to right",
"alignTop": "Align to top",
"alignMiddle": "Align to middle",
"alignBottom": "Align to bottom",
"distributeHorizontally": "Distribute horizontally",
"distributeVertically": "Distribute vertically",
"moveToBack": "Move to back",
"moveToFront": "Move to front",
"moveBackwards": "Move backwards",
"moveForwards": "Move forwards"
} }
}, },
"actions": { "actions": {
"toggle-navigator": "Toggle navigator", "toggle-navigator": "Toggle navigator",
"zoom-out": "Zoom out", "zoom-out": "Zoom out",
"zoom-reset": "Reset zoom", "zoom-reset": "Reset zoom",
"zoom-in": "Zoom in", "zoom-in": "Zoom in"
"search-flows": "Search flows",
"search-prev": "Previous",
"search-next": "Next",
"search-counter": "\"__term__\" __result__ of __count__"
}, },
"user": { "user": {
"loggedInAs": "Logged in as __name__", "loggedInAs": "Logged in as __name__",
@@ -182,10 +138,6 @@
} }
}, },
"notification": { "notification": {
"state": {
"flowsStopped": "Flows stopped",
"flowsStarted": "Flows started"
},
"warning": "<strong>Warning</strong>: __message__", "warning": "<strong>Warning</strong>: __message__",
"warnings": { "warnings": {
"undeployedChanges": "node has undeployed changes", "undeployedChanges": "node has undeployed changes",
@@ -193,10 +145,10 @@
"nodeActionDisabledSubflow": "node actions disabled within subflow", "nodeActionDisabledSubflow": "node actions disabled within subflow",
"missing-types": "<p>Flows stopped due to missing node types.</p>", "missing-types": "<p>Flows stopped due to missing node types.</p>",
"missing-modules": "<p>Flows stopped due to missing modules.</p>", "missing-modules": "<p>Flows stopped due to missing modules.</p>",
"safe-mode": "<p>Flows stopped in safe mode.</p><p>You can modify your flows and deploy the changes to restart.</p>", "safe-mode":"<p>Flows stopped in safe mode.</p><p>You can modify your flows and deploy the changes to restart.</p>",
"restartRequired": "Node-RED must be restarted to enable upgraded modules", "restartRequired": "Node-RED must be restarted to enable upgraded modules",
"credentials_load_failed": "<p>Flows stopped as the credentials could not be decrypted.</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p>", "credentials_load_failed": "<p>Flows stopped as the credentials could not be decrypted.</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p>",
"credentials_load_failed_reset": "<p>Credentials could not be decrypted</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p><p>The flow credential file will be reset on the next deployment. Any existing flow credentials will be cleared.</p>", "credentials_load_failed_reset":"<p>Credentials could not be decrypted</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p><p>The flow credential file will be reset on the next deployment. Any existing flow credentials will be cleared.</p>",
"missing_flow_file": "<p>Project flow file not found.</p><p>The project is not configured with a flow file.</p>", "missing_flow_file": "<p>Project flow file not found.</p><p>The project is not configured with a flow file.</p>",
"missing_package_file": "<p>Project package file not found.</p><p>The project is missing a package.json file.</p>", "missing_package_file": "<p>Project package file not found.</p><p>The project is missing a package.json file.</p>",
"project_empty": "<p>The project is empty.</p><p>Do you want to create a default set of project files?<br/>Otherwise, you will have to manually add files to the project outside of the editor.</p>", "project_empty": "<p>The project is empty.</p><p>Do you want to create a default set of project files?<br/>Otherwise, you will have to manually add files to the project outside of the editor.</p>",
@@ -234,8 +186,7 @@
"create-default-package": "Create default package file", "create-default-package": "Create default package file",
"no-thanks": "No thanks", "no-thanks": "No thanks",
"create-default-project": "Create default project files", "create-default-project": "Create default project files",
"show-merge-conflicts": "Show merge conflicts", "show-merge-conflicts": "Show merge conflicts"
"unknownNodesButton": "Search for unknown nodes"
} }
}, },
"clipboard": { "clipboard": {
@@ -274,11 +225,11 @@
"recoveredNodesInfo": "The nodes on this flow were missing a valid flow id when they were imported. They have been added to this flow so you can either restore or delete them.", "recoveredNodesInfo": "The nodes on this flow were missing a valid flow id when they were imported. They have been added to this flow so you can either restore or delete them.",
"recoveredNodesNotification": "<p>Imported nodes without a valid flow id</p><p>They have been added to a new flow called '__flowName__'.</p>", "recoveredNodesNotification": "<p>Imported nodes without a valid flow id</p><p>They have been added to a new flow called '__flowName__'.</p>",
"export": { "export": {
"selected": "selected nodes", "selected":"selected nodes",
"current": "current flow", "current":"current flow",
"all": "all flows", "all":"all flows",
"compact": "compact", "compact":"compact",
"formatted": "formatted", "formatted":"formatted",
"copy": "Copy to clipboard", "copy": "Copy to clipboard",
"export": "Export to library", "export": "Export to library",
"exportAs": "Export as", "exportAs": "Export as",
@@ -313,19 +264,13 @@
"modifiedFlowsDesc": "Only deploys flows that contain changed nodes", "modifiedFlowsDesc": "Only deploys flows that contain changed nodes",
"modifiedNodes": "Modified Nodes", "modifiedNodes": "Modified Nodes",
"modifiedNodesDesc": "Only deploys nodes that have changed", "modifiedNodesDesc": "Only deploys nodes that have changed",
"startFlows": "Start",
"startFlowsDesc": "Start Flows",
"stopFlows": "Stop",
"stopFlowsDesc": "Stop Flows",
"restartFlows": "Restart Flows", "restartFlows": "Restart Flows",
"restartFlowsDesc": "Restarts the current deployed flows", "restartFlowsDesc": "Restarts the current deployed flows",
"successfulDeploy": "Successfully deployed", "successfulDeploy": "Successfully deployed",
"successfulRestart": "Successfully restarted flows", "successfulRestart": "Successfully restarted flows",
"deployFailed": "Deploy failed: __message__", "deployFailed": "Deploy failed: __message__",
"unusedConfigNodes": "You have some unused configuration nodes.", "unusedConfigNodes":"You have some unused configuration nodes.",
"unusedConfigNodesButton": "Search unused config nodes", "unusedConfigNodesLink":"Click here to see them",
"unknownNodesButton": "Search for unknown nodes",
"invalidNodesButton": "Search for invalid nodes",
"errors": { "errors": {
"noResponse": "no response from server" "noResponse": "no response from server"
}, },
@@ -372,8 +317,8 @@
}, },
"nodeCount": "__count__ node", "nodeCount": "__count__ node",
"nodeCount_plural": "__count__ nodes", "nodeCount_plural": "__count__ nodes",
"local": "Local changes", "local":"Local changes",
"remote": "Remote changes", "remote":"Remote changes",
"reviewChanges": "Review Changes", "reviewChanges": "Review Changes",
"noBinaryFileShowed": "Cannot show binary file contents", "noBinaryFileShowed": "Cannot show binary file contents",
"viewCommitDiff": "View Commit Changes", "viewCommitDiff": "View Commit Changes",
@@ -457,7 +402,7 @@
"inputType": "Input type", "inputType": "Input type",
"selectType": "select types...", "selectType": "select types...",
"loadCredentials": "Loading node credentials", "loadCredentials": "Loading node credentials",
"inputs": { "inputs" : {
"input": "input", "input": "input",
"select": "select", "select": "select",
"checkbox": "checkbox", "checkbox": "checkbox",
@@ -504,13 +449,11 @@
"unassigned": "Unassigned", "unassigned": "Unassigned",
"global": "global", "global": "global",
"workspace": "workspace", "workspace": "workspace",
"selectAll": "Select all", "selectAll": "Select all nodes",
"selectNone": "Select none", "selectAllConnected": "Select all connected nodes",
"selectAllConnected": "Select connected",
"addRemoveNode": "Add/remove node from selection", "addRemoveNode": "Add/remove node from selection",
"editSelected": "Edit selected node", "editSelected": "Edit selected node",
"deleteSelected": "Delete selected nodes or link", "deleteSelected": "Delete selected nodes or link",
"deleteReconnect": "Delete and Reconnect",
"importNode": "Import nodes", "importNode": "Import nodes",
"exportNode": "Export nodes", "exportNode": "Export nodes",
"nudgeNode": "Move selected nodes (1px)", "nudgeNode": "Move selected nodes (1px)",
@@ -520,14 +463,10 @@
"copyNode": "Copy selected nodes", "copyNode": "Copy selected nodes",
"cutNode": "Cut selected nodes", "cutNode": "Cut selected nodes",
"pasteNode": "Paste nodes", "pasteNode": "Paste nodes",
"copyGroupStyle": "Copy group style", "undoChange": "Undo the last change performed",
"pasteGroupStyle": "Paste group style",
"undoChange": "Undo",
"redoChange": "Redo",
"searchBox": "Open search box", "searchBox": "Open search box",
"managePalette": "Manage palette", "managePalette": "Manage palette",
"actionList": "Action list", "actionList":"Action list"
"splitWireWithLinks": "Split selection with Link nodes"
}, },
"library": { "library": {
"library": "Library", "library": "Library",
@@ -579,8 +518,7 @@
"nodeEnabled_plural": "Nodes enabled:", "nodeEnabled_plural": "Nodes enabled:",
"nodeDisabled": "Node disabled:", "nodeDisabled": "Node disabled:",
"nodeDisabled_plural": "Nodes disabled:", "nodeDisabled_plural": "Nodes disabled:",
"nodeUpgraded": "Node module __module__ upgraded to version __version__", "nodeUpgraded": "Node module __module__ upgraded to version __version__"
"unknownNodeRegistered": "Error loading node: <ul><li>__type__<br>__error__</li></ul>"
}, },
"editor": { "editor": {
"title": "Manage palette", "title": "Manage palette",
@@ -639,19 +577,19 @@
}, },
"confirm": { "confirm": {
"install": { "install": {
"body": "<p>Installing '__module__'</p><p>Before installing, please read the node's documentation. Some nodes have dependencies that cannot be automatically resolved and can require a restart of Node-RED.</p>", "body":"<p>Installing '__module__'</p><p>Before installing, please read the node's documentation. Some nodes have dependencies that cannot be automatically resolved and can require a restart of Node-RED.</p>",
"title": "Install nodes" "title": "Install nodes"
}, },
"remove": { "remove": {
"body": "<p>Removing '__module__'</p><p>Removing the node will uninstall it from Node-RED. The node may continue to use resources until Node-RED is restarted.</p>", "body":"<p>Removing '__module__'</p><p>Removing the node will uninstall it from Node-RED. The node may continue to use resources until Node-RED is restarted.</p>",
"title": "Remove nodes" "title": "Remove nodes"
}, },
"update": { "update": {
"body": "<p>Updating '__module__'</p><p>Updating the node will require a restart of Node-RED to complete the update. This must be done manually.</p>", "body":"<p>Updating '__module__'</p><p>Updating the node will require a restart of Node-RED to complete the update. This must be done manually.</p>",
"title": "Update nodes" "title": "Update nodes"
}, },
"cannotUpdate": { "cannotUpdate": {
"body": "An update for this node is available, but it is not installed in a location that the palette manager can update.<br/><br/>Please refer to the documentation for how to update this node." "body":"An update for this node is available, but it is not installed in a location that the palette manager can update.<br/><br/>Please refer to the documentation for how to update this node."
}, },
"button": { "button": {
"review": "Open node information", "review": "Open node information",
@@ -685,23 +623,26 @@
"showMore": "show more", "showMore": "show more",
"showLess": "show less", "showLess": "show less",
"flow": "Flow", "flow": "Flow",
"selection": "Selection", "selection":"Selection",
"nodes": "__count__ nodes", "nodes":"__count__ nodes",
"flowDesc": "Flow Description", "flowDesc": "Flow Description",
"subflowDesc": "Subflow Description", "subflowDesc": "Subflow Description",
"nodeHelp": "Node Help", "nodeHelp": "Node Help",
"none": "None", "none":"None",
"arrayItems": "__count__ items", "arrayItems": "__count__ items",
"showTips": "You can open the tips from the settings panel", "showTips":"You can open the tips from the settings panel",
"outline": "Outline", "outline": "Outline",
"empty": "empty", "empty": "empty",
"globalConfig": "Global Configuration Nodes", "globalConfig": "Global Configuration Nodes",
"triggerAction": "Trigger action", "triggerAction": "Trigger action",
"find": "Find in workspace", "find": "Find in workspace",
"copyItemUrl": "Copy item url", "search": {
"copyURL2Clipboard": "Copied url to clipboard", "configNodes": "Configuration nodes",
"showFlow": "Show", "unusedConfigNodes": "Unused configuration nodes",
"hideFlow": "Hide" "invalidNodes": "Invalid nodes",
"uknownNodes": "Unknown nodes",
"unusedSubflows": "Unused subflows"
}
}, },
"help": { "help": {
"name": "Help", "name": "Help",
@@ -711,8 +652,7 @@
"showHelp": "Show help", "showHelp": "Show help",
"showInOutline": "Show in outline", "showInOutline": "Show in outline",
"showTopics": "Show topics", "showTopics": "Show topics",
"noHelp": "No help topic selected", "noHelp": "No help topic selected"
"changeLog": "Change Log"
}, },
"config": { "config": {
"name": "Configuration nodes", "name": "Configuration nodes",
@@ -728,8 +668,8 @@
"filtered": "__count__ hidden" "filtered": "__count__ hidden"
}, },
"context": { "context": {
"name": "Context Data", "name":"Context Data",
"label": "context", "label":"context",
"none": "none selected", "none": "none selected",
"refresh": "refresh to load", "refresh": "refresh to load",
"empty": "empty", "empty": "empty",
@@ -767,9 +707,9 @@
"files": "Files", "files": "Files",
"flow": "Flow", "flow": "Flow",
"credentials": "Credentials", "credentials": "Credentials",
"package": "Package", "package":"Package",
"packageCreate": "File will be created when changes are saved", "packageCreate":"File will be created when changes are saved",
"fileNotExist": "File does not exist", "fileNotExist":"File does not exist",
"selectFile": "Select File", "selectFile": "Select File",
"invalidEncryptionKey": "Invalid encryption key", "invalidEncryptionKey": "Invalid encryption key",
"encryptionEnabled": "Encryption enabled", "encryptionEnabled": "Encryption enabled",
@@ -923,20 +863,8 @@
"addTitle": "add an item" "addTitle": "add an item"
}, },
"search": { "search": {
"history": "Search history",
"clear": "clear all",
"empty": "No matches found", "empty": "No matches found",
"addNode": "add a node...", "addNode": "add a node..."
"options": {
"configNodes": "Configuration nodes",
"unusedConfigNodes": "Unused configuration nodes",
"invalidNodes": "Invalid nodes",
"uknownNodes": "Unknown nodes",
"unusedSubflows": "Unused subflows",
"hiddenFlows": "Hidden flows",
"modifiedNodes": "Modified nodes and flows",
"thisFlow": "Current flow"
}
}, },
"expressionEditor": { "expressionEditor": {
"functions": "Functions", "functions": "Functions",
@@ -954,15 +882,9 @@
"invalid-expr": "Invalid JSONata expression:\n __message__", "invalid-expr": "Invalid JSONata expression:\n __message__",
"invalid-msg": "Invalid example JSON message:\n __message__", "invalid-msg": "Invalid example JSON message:\n __message__",
"context-unsupported": "Cannot test context functions\n $flowContext or $globalContext", "context-unsupported": "Cannot test context functions\n $flowContext or $globalContext",
"env-unsupported": "Cannot test $env function",
"moment-unsupported": "Cannot test $moment function",
"clone-unsupported": "Cannot test $clone function",
"eval": "Error evaluating expression:\n __message__" "eval": "Error evaluating expression:\n __message__"
} }
}, },
"monaco": {
"setTheme": "Set theme"
},
"jsEditor": { "jsEditor": {
"title": "JavaScript editor" "title": "JavaScript editor"
}, },
@@ -974,8 +896,6 @@
"format": "format JSON", "format": "format JSON",
"rawMode": "Edit JSON", "rawMode": "Edit JSON",
"uiMode": "Visual editor", "uiMode": "Visual editor",
"rawMode-readonly": "JSON",
"uiMode-readonly": "Visual",
"insertAbove": "Insert above", "insertAbove": "Insert above",
"insertBelow": "Insert below", "insertBelow": "Insert below",
"addItem": "Add item", "addItem": "Add item",
@@ -1002,16 +922,13 @@
"quote": "Quote", "quote": "Quote",
"link": "Link", "link": "Link",
"horizontal-rule": "Horizontal rule", "horizontal-rule": "Horizontal rule",
"toggle-preview": "Toggle preview", "toggle-preview": "Toggle preview"
"mermaid": {
"summary": "Mermaid Diagram"
}
}, },
"bufferEditor": { "bufferEditor": {
"title": "Buffer editor", "title": "Buffer editor",
"modeString": "Handle as UTF-8 String", "modeString": "Handle as UTF-8 String",
"modeArray": "Handle as JSON array", "modeArray": "Handle as JSON array",
"modeDesc": "<h3>Buffer editor</h3><p>The Buffer type is stored as a JSON array of byte values. The editor will attempt to parse the entered value as a JSON array. If it is not valid JSON, it will be treated as a UTF-8 String and converted to an array of the individual character code points.</p><p>For example, a value of <code>Hello World</code> will be converted to the JSON array:<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>" "modeDesc":"<h3>Buffer editor</h3><p>The Buffer type is stored as a JSON array of byte values. The editor will attempt to parse the entered value as a JSON array. If it is not valid JSON, it will be treated as a UTF-8 String and converted to an array of the individual character code points.</p><p>For example, a value of <code>Hello World</code> will be converted to the JSON array:<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>"
}, },
"projects": { "projects": {
"config-git": "Configure Git client", "config-git": "Configure Git client",
@@ -1140,8 +1057,7 @@
"not-git": "Not a git repository", "not-git": "Not a git repository",
"no-resource": "Repository not found", "no-resource": "Repository not found",
"cant-get-ssh-key-path": "Error! Can't get selected SSH key path.", "cant-get-ssh-key-path": "Error! Can't get selected SSH key path.",
"unexpected_error": "unexpected_error", "unexpected_error": "unexpected_error"
"clearContext": "Clear context when switching projects"
}, },
"delete": { "delete": {
"confirm": "Are you sure you want to delete this project?" "confirm": "Are you sure you want to delete this project?"
@@ -1173,7 +1089,7 @@
"no-empty": "Cannot create default file set on a non-empty project", "no-empty": "Cannot create default file set on a non-empty project",
"git-error": "git error" "git-error": "git error"
}, },
"errors": { "errors" : {
"no-username-email": "Your Git client is not configured with a username/email.", "no-username-email": "Your Git client is not configured with a username/email.",
"unexpected": "An unexpected error occurred", "unexpected": "An unexpected error occurred",
"code": "code" "code": "code"
@@ -1188,16 +1104,7 @@
"preview": "UI Preview", "preview": "UI Preview",
"defaultValue": "Default value" "defaultValue": "Default value"
}, },
"tourGuide": { "languages" : {
"takeATour": "Take a tour",
"start": "Start",
"next": "Next",
"welcomeTours": "Welcome Tours"
},
"diagnostics": {
"title": "System Info"
},
"languages": {
"de": "German", "de": "German",
"en-US": "English", "en-US": "English",
"ja": "Japanese", "ja": "Japanese",
@@ -1205,32 +1112,5 @@
"ru": "Russian", "ru": "Russian",
"zh-CN": "Chinese(Simplified)", "zh-CN": "Chinese(Simplified)",
"zh-TW": "Chinese(Traditional)" "zh-TW": "Chinese(Traditional)"
},
"validator": {
"errors": {
"invalid-json": "Invalid JSON data: __error__",
"invalid-json-prop": "__prop__: invalid JSON data: __error__",
"invalid-prop": "Invalid property expression",
"invalid-prop-prop": "__prop__: invalid property expression",
"invalid-num": "Invalid number",
"invalid-num-prop": "__prop__: invalid number",
"invalid-regexp": "Invalid input pattern",
"invalid-regex-prop": "__prop__: invalid input pattern",
"missing-required-prop": "__prop__: property value missing",
"invalid-config": "__prop__: invalid configuration node",
"missing-config": "__prop__: missing configuration node",
"validation-error": "__prop__: validation error: __node__, __id__: __error__"
}
},
"contextMenu": {
"insert": "Insert",
"node": "Node",
"junction": "Junction",
"linkNodes": "Link Nodes"
},
"env-var": {
"environment": "Environment",
"header": "Global Environment Variables",
"revert": "Revert"
} }
} }

View File

@@ -1,23 +1,23 @@
{ {
"info": { "info": {
"tip0": "You can remove the selected nodes or links with {{core:delete-selection}}", "tip0" : "You can remove the selected nodes or links with {{core:delete-selection}}",
"tip1": "Search for nodes using {{core:search}}", "tip1" : "Search for nodes using {{core:search}}",
"tip2": "{{core:toggle-sidebar}} will toggle the view of this sidebar", "tip2" : "{{core:toggle-sidebar}} will toggle the view of this sidebar",
"tip3": "You can manage your palette of nodes with {{core:manage-palette}}", "tip3" : "You can manage your palette of nodes with {{core:manage-palette}}",
"tip4": "Your flow configuration nodes are listed in the sidebar panel. It can be accessed from the menu or with {{core:show-config-tab}}", "tip4" : "Your flow configuration nodes are listed in the sidebar panel. It can be accessed from the menu or with {{core:show-config-tab}}",
"tip5": "Enable or disable these tips from the option in the settings", "tip5" : "Enable or disable these tips from the option in the settings",
"tip6": "Move the selected nodes using the [left] [up] [down] and [right] keys. Hold [shift] to nudge them further", "tip6" : "Move the selected nodes using the [left] [up] [down] and [right] keys. Hold [shift] to nudge them further",
"tip7": "Dragging a node onto a wire will splice it into the link", "tip7" : "Dragging a node onto a wire will splice it into the link",
"tip8": "Export the selected nodes, or the current tab with {{core:show-export-dialog}}", "tip8" : "Export the selected nodes, or the current tab with {{core:show-export-dialog}}",
"tip9": "Import a flow by dragging its JSON into the editor, or with {{core:show-import-dialog}}", "tip9" : "Import a flow by dragging its JSON into the editor, or with {{core:show-import-dialog}}",
"tip10": "[shift] [click] and drag on a node port to move all of the attached wires or just the selected one", "tip10" : "[shift] [click] and drag on a node port to move all of the attached wires or just the selected one",
"tip11": "Show the Info tab with {{core:show-info-tab}} or the Debug tab with {{core:show-debug-tab}}", "tip11" : "Show the Info tab with {{core:show-info-tab}} or the Debug tab with {{core:show-debug-tab}}",
"tip12": "[ctrl] [click] in the workspace to open the quick-add dialog", "tip12" : "[ctrl] [click] in the workspace to open the quick-add dialog",
"tip13": "Hold down [ctrl] when you [click] on a node port to enable quick-wiring", "tip13" : "Hold down [ctrl] when you [click] on a node port to enable quick-wiring",
"tip14": "Hold down [shift] when you [click] on a node to also select all of its connected nodes", "tip14" : "Hold down [shift] when you [click] on a node to also select all of its connected nodes",
"tip15": "Hold down [ctrl] when you [click] on a node to add or remove it from the current selection", "tip15" : "Hold down [ctrl] when you [click] on a node to add or remove it from the current selection",
"tip16": "Switch flow tabs with {{core:show-previous-tab}} and {{core:show-next-tab}}", "tip16" : "Switch flow tabs with {{core:show-previous-tab}} and {{core:show-next-tab}}",
"tip17": "You can confirm your changes in the node edit tray with {{core:confirm-edit-tray}} or cancel them with {{core:cancel-edit-tray}}", "tip17" : "You can confirm your changes in the node edit tray with {{core:confirm-edit-tray}} or cancel them with {{core:cancel-edit-tray}}",
"tip18": "Pressing {{core:edit-selected-node}} will edit the first node in the current selection" "tip18" : "Pressing {{core:edit-selected-node}} will edit the first node in the current selection"
} }
} }

View File

@@ -52,52 +52,52 @@
"desc": "Finds occurrences of `pattern` within `str` and replaces them with `replacement`.\n\nThe optional `limit` parameter is the maximum number of replacements." "desc": "Finds occurrences of `pattern` within `str` and replaces them with `replacement`.\n\nThe optional `limit` parameter is the maximum number of replacements."
}, },
"$now": { "$now": {
"args": "$[picture [, timezone]]", "args":"",
"desc": "Generates a timestamp in ISO 8601 compatible format and returns it as a string. If the optional picture and timezone parameters are supplied, then the current timestamp is formatted as described by the `$fromMillis()` function" "desc":"Generates a timestamp in ISO 8601 compatible format and returns it as a string."
}, },
"$base64encode": { "$base64encode": {
"args": "string", "args":"string",
"desc": "Converts an ASCII string to a base 64 representation. Each character in the string is treated as a byte of binary data. This requires that all characters in the string are in the 0x00 to 0xFF range, which includes all characters in URI encoded strings. Unicode characters outside of that range are not supported." "desc":"Converts an ASCII string to a base 64 representation. Each character in the string is treated as a byte of binary data. This requires that all characters in the string are in the 0x00 to 0xFF range, which includes all characters in URI encoded strings. Unicode characters outside of that range are not supported."
}, },
"$base64decode": { "$base64decode": {
"args": "string", "args":"string",
"desc": "Converts base 64 encoded bytes to a string, using a UTF-8 Unicode codepage." "desc":"Converts base 64 encoded bytes to a string, using a UTF-8 Unicode codepage."
}, },
"$number": { "$number": {
"args": "arg", "args": "arg",
"desc": "Casts the `arg` parameter to a number using the following casting rules:\n\n - Numbers are unchanged\n - Strings that contain a sequence of characters that represent a legal JSON number are converted to that number\n - All other values cause an error to be thrown." "desc": "Casts the `arg` parameter to a number using the following casting rules:\n\n - Numbers are unchanged\n - Strings that contain a sequence of characters that represent a legal JSON number are converted to that number\n - All other values cause an error to be thrown."
}, },
"$abs": { "$abs": {
"args": "number", "args":"number",
"desc": "Returns the absolute value of the `number` parameter." "desc":"Returns the absolute value of the `number` parameter."
}, },
"$floor": { "$floor": {
"args": "number", "args":"number",
"desc": "Returns the value of `number` rounded down to the nearest integer that is smaller or equal to `number`." "desc":"Returns the value of `number` rounded down to the nearest integer that is smaller or equal to `number`."
}, },
"$ceil": { "$ceil": {
"args": "number", "args":"number",
"desc": "Returns the value of `number` rounded up to the nearest integer that is greater than or equal to `number`." "desc":"Returns the value of `number` rounded up to the nearest integer that is greater than or equal to `number`."
}, },
"$round": { "$round": {
"args": "number [, precision]", "args":"number [, precision]",
"desc": "Returns the value of the `number` parameter rounded to the number of decimal places specified by the optional `precision` parameter." "desc":"Returns the value of the `number` parameter rounded to the number of decimal places specified by the optional `precision` parameter."
}, },
"$power": { "$power": {
"args": "base, exponent", "args":"base, exponent",
"desc": "Returns the value of `base` raised to the power of `exponent`." "desc":"Returns the value of `base` raised to the power of `exponent`."
}, },
"$sqrt": { "$sqrt": {
"args": "number", "args":"number",
"desc": "Returns the square root of the value of the `number` parameter." "desc":"Returns the square root of the value of the `number` parameter."
}, },
"$random": { "$random": {
"args": "", "args":"",
"desc": "Returns a pseudo random number greater than or equal to zero and less than one." "desc":"Returns a pseudo random number greater than or equal to zero and less than one."
}, },
"$millis": { "$millis": {
"args": "", "args":"",
"desc": "Returns the number of milliseconds since the Unix Epoch (1 January, 1970 UTC) as a number. All invocations of `$millis()` within an evaluation of an expression will all return the same value." "desc":"Returns the number of milliseconds since the Unix Epoch (1 January, 1970 UTC) as a number. All invocations of `$millis()` within an evaluation of an expression will all return the same value."
}, },
"$sum": { "$sum": {
"args": "array", "args": "array",
@@ -136,20 +136,20 @@
"desc": "Appends two arrays" "desc": "Appends two arrays"
}, },
"$sort": { "$sort": {
"args": "array [, function]", "args":"array [, function]",
"desc": "Returns an array containing all the values in the `array` parameter, but sorted into order.\n\nIf a comparator `function` is supplied, then it must be a function that takes two parameters:\n\n`function(left, right)`\n\nThis function gets invoked by the sorting algorithm to compare two values left and right. If the value of left should be placed after the value of right in the desired sort order, then the function must return Boolean `true` to indicate a swap. Otherwise it must return `false`." "desc":"Returns an array containing all the values in the `array` parameter, but sorted into order.\n\nIf a comparator `function` is supplied, then it must be a function that takes two parameters:\n\n`function(left, right)`\n\nThis function gets invoked by the sorting algorithm to compare two values left and right. If the value of left should be placed after the value of right in the desired sort order, then the function must return Boolean `true` to indicate a swap. Otherwise it must return `false`."
}, },
"$reverse": { "$reverse": {
"args": "array", "args":"array",
"desc": "Returns an array containing all the values from the `array` parameter, but in reverse order." "desc":"Returns an array containing all the values from the `array` parameter, but in reverse order."
}, },
"$shuffle": { "$shuffle": {
"args": "array", "args":"array",
"desc": "Returns an array containing all the values from the `array` parameter, but shuffled into random order." "desc":"Returns an array containing all the values from the `array` parameter, but shuffled into random order."
}, },
"$zip": { "$zip": {
"args": "array, ...", "args":"array, ...",
"desc": "Returns a convolved (zipped) array containing grouped arrays of values from the `array1` … `arrayN` arguments from index 0, 1, 2...." "desc":"Returns a convolved (zipped) array containing grouped arrays of values from the `array1` … `arrayN` arguments from index 0, 1, 2...."
}, },
"$keys": { "$keys": {
"args": "object", "args": "object",
@@ -168,24 +168,24 @@
"desc": "Merges an array of `objects` into a single `object` containing all the key/value pairs from each of the objects in the input array. If any of the input objects contain the same key, then the returned `object` will contain the value of the last one in the array. It is an error if the input array contains an item that is not an object." "desc": "Merges an array of `objects` into a single `object` containing all the key/value pairs from each of the objects in the input array. If any of the input objects contain the same key, then the returned `object` will contain the value of the last one in the array. It is an error if the input array contains an item that is not an object."
}, },
"$sift": { "$sift": {
"args": "object, function", "args":"object, function",
"desc": "Returns an object that contains only the key/value pairs from the `object` parameter that satisfy the predicate `function` passed in as the second parameter.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, key [, object]])`" "desc":"Returns an object that contains only the key/value pairs from the `object` parameter that satisfy the predicate `function` passed in as the second parameter.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, key [, object]])`"
}, },
"$each": { "$each": {
"args": "object, function", "args":"object, function",
"desc": "Returns an array containing the values return by the `function` when applied to each key/value pair in the `object`." "desc":"Returns an array containing the values return by the `function` when applied to each key/value pair in the `object`."
}, },
"$map": { "$map": {
"args": "array, function", "args":"array, function",
"desc": "Returns an array containing the results of applying the `function` parameter to each value in the `array` parameter.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, index [, array]])`" "desc":"Returns an array containing the results of applying the `function` parameter to each value in the `array` parameter.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, index [, array]])`"
}, },
"$filter": { "$filter": {
"args": "array, function", "args":"array, function",
"desc": "Returns an array containing only the values in the `array` parameter that satisfy the `function` predicate.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, index [, array]])`" "desc":"Returns an array containing only the values in the `array` parameter that satisfy the `function` predicate.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, index [, array]])`"
}, },
"$reduce": { "$reduce": {
"args": "array, function [, init]", "args":"array, function [, init]",
"desc": "Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`. The signature of `function` must be of the form: `myfunc($accumulator, $value[, $index[, $array]])`\n\nThe optional `init` parameter is used as the initial value in the aggregation." "desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`. The signature of `function` must be of the form: `myfunc($accumulator, $value[, $index[, $array]])`\n\nThe optional `init` parameter is used as the initial value in the aggregation."
}, },
"$flowContext": { "$flowContext": {
"args": "string[, string]", "args": "string[, string]",
@@ -200,8 +200,8 @@
"desc": "Returns a copy of the `string` with extra padding, if necessary, so that its total number of characters is at least the absolute value of the `width` parameter.\n\nIf `width` is a positive number, then the string is padded to the right; if negative, it is padded to the left.\n\nThe optional `char` argument specifies the padding character(s) to use. If not specified, it defaults to the space character." "desc": "Returns a copy of the `string` with extra padding, if necessary, so that its total number of characters is at least the absolute value of the `width` parameter.\n\nIf `width` is a positive number, then the string is padded to the right; if negative, it is padded to the left.\n\nThe optional `char` argument specifies the padding character(s) to use. If not specified, it defaults to the space character."
}, },
"$fromMillis": { "$fromMillis": {
"args": "number, [, picture [, timezone]]", "args": "number",
"desc": "Convert the `number` representing milliseconds since the Unix Epoch (1 January, 1970 UTC) to a formatted string representation of the timestamp as specified by the picture string.\n\nIf the optional `picture` parameter is omitted, then the timestamp is formatted in the ISO 8601 format.\n\nIf the optional `picture` string is supplied, then the timestamp is formatted occording to the representation specified in that string. The behaviour of this function is consistent with the two-argument version of the XPath/XQuery function `format-dateTime` as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the timestamp is formatted and has the same syntax as `format-dateTime`.\n\nIf the optional `timezone` string is supplied, then the formatted timestamp will be in that timezone. The `timezone` string should be in the format '±HHMM', where ± is either the plus or minus sign and HHMM is the offset in hours and minutes from UTC. Positive offset for timezones east of UTC, negative offset for timezones west of UTC." "desc": "Convert a number representing milliseconds since the Unix Epoch (1 January, 1970 UTC) to a timestamp string in the ISO 8601 format."
}, },
"$formatNumber": { "$formatNumber": {
"args": "number, picture [, options]", "args": "number, picture [, options]",

View File

@@ -23,11 +23,7 @@
"position": "配置", "position": "配置",
"enable": "有効", "enable": "有効",
"disable": "無効", "disable": "無効",
"upload": "アップロード", "upload": "アップロード"
"lock": "固定",
"unlock": "固定を解除",
"locked": "固定済み",
"unlocked": "固定なし"
}, },
"type": { "type": {
"string": "文字列", "string": "文字列",
@@ -57,38 +53,19 @@
"confirmDelete": "削除の確認", "confirmDelete": "削除の確認",
"delete": "本当に '__label__' を削除しますか?", "delete": "本当に '__label__' を削除しますか?",
"dropFlowHere": "ここにフローをドロップしてください", "dropFlowHere": "ここにフローをドロップしてください",
"dropImageHere": "ここに画像ファイルをドロップしてください",
"addFlow": "フローの追加", "addFlow": "フローの追加",
"addFlowToRight": "右側にフローを追加",
"closeFlow": "フローを閉じる",
"hideFlow": "フローを非表示",
"hideOtherFlows": "他のフローを非表示",
"showAllFlows": "全てのフローを表示",
"hideAllFlows": "全てのフローを非表示",
"hiddenFlows": "__count__ 個の非表示のフロー一覧",
"hiddenFlows_plural": "__count__ 個の非表示のフロー一覧",
"showLastHiddenFlow": "最後に非表示にしたフローを表示",
"listFlows": "フロー一覧", "listFlows": "フロー一覧",
"listSubflows": "サブフロー一覧",
"status": "状態", "status": "状態",
"enabled": "有効", "enabled": "有効",
"disabled": "無効", "disabled": "無効",
"info": "詳細", "info": "詳細",
"selectNodes": "ノードをクリックして選択", "selectNodes": "ノードをクリックして選択"
"enableFlow": "フローを有効化",
"disableFlow": "フローを無効化",
"lockFlow": "フローを固定",
"unlockFlow": "フローの固定を解除",
"moveToStart": "フローを先頭へ移動",
"moveToEnd": "フローを最後へ移動"
}, },
"menu": { "menu": {
"label": { "label": {
"view": { "view": {
"view": "表示", "view": "表示",
"grid": "グリッド", "grid": "グリッド",
"storeZoom": "読み込み時に拡大/縮小のレベルを復元",
"storePosition": "読み込み時にスクロール位置を復元",
"showGrid": "グリッドを表示", "showGrid": "グリッドを表示",
"snapGrid": "ノードの配置を補助", "snapGrid": "ノードの配置を補助",
"gridSize": "グリッドの大きさ", "gridSize": "グリッドの大きさ",
@@ -106,14 +83,12 @@
"palette": { "palette": {
"show": "パレットを表示" "show": "パレットを表示"
}, },
"edit": "編集",
"settings": "設定", "settings": "設定",
"userSettings": "ユーザ設定", "userSettings": "ユーザ設定",
"nodes": "ノード", "nodes": "ノード",
"displayStatus": "ノードのステータスを表示", "displayStatus": "ノードのステータスを表示",
"displayConfig": "設定ノード", "displayConfig": "設定ノード",
"import": "読み込み", "import": "読み込み",
"importExample": "フロー例を読み込み",
"export": "書き出し", "export": "書き出し",
"search": "ノードを検索", "search": "ノードを検索",
"searchInput": "ノードを検索", "searchInput": "ノードを検索",
@@ -130,43 +105,24 @@
"editPalette": "パレットの管理", "editPalette": "パレットの管理",
"other": "その他", "other": "その他",
"showTips": "ヒントを表示", "showTips": "ヒントを表示",
"showWelcomeTours": "新バージョンのガイドツアーを表示",
"help": "Node-REDウェブサイト", "help": "Node-REDウェブサイト",
"projects": "プロジェクト", "projects": "プロジェクト",
"projects-new": "新規", "projects-new": "新規",
"projects-open": "開く", "projects-open": "開く",
"projects-settings": "設定", "projects-settings": "設定",
"showNodeLabelDefault": "追加したノードのラベルを表示", "showNodeLabelDefault": "追加したノードのラベルを表示",
"codeEditor": "コードエディタ",
"groups": "グループ", "groups": "グループ",
"groupSelection": "選択部分をグループ化", "groupSelection": "選択部分をグループ化",
"ungroupSelection": "選択部分をグループ解除", "ungroupSelection": "選択部分をグループ解除",
"groupMergeSelection": "選択部分をマージ", "groupMergeSelection": "選択部分をマージ",
"groupRemoveSelection": "グループから削除", "groupRemoveSelection": "グループから削除"
"arrange": "配置",
"alignLeft": "左揃え",
"alignCenter": "左右中央揃え",
"alignRight": "右揃え",
"alignTop": "上揃え",
"alignMiddle": "上下中央揃え",
"alignBottom": "下揃え",
"distributeHorizontally": "左右に整列",
"distributeVertically": "上下に整列",
"moveToBack": "最背面へ移動",
"moveToFront": "最前面へ移動",
"moveBackwards": "背面へ移動",
"moveForwards": "前面へ移動"
} }
}, },
"actions": { "actions": {
"toggle-navigator": "ナビゲータの表示/非表示を切替", "toggle-navigator": "ナビゲータの表示/非表示を切替",
"zoom-out": "縮小", "zoom-out": "縮小",
"zoom-reset": "拡大/縮小を初期化", "zoom-reset": "拡大/縮小を初期化",
"zoom-in": "拡大", "zoom-in": "拡大"
"search-flows": "フローを検索",
"search-prev": "前へ",
"search-next": "次へ",
"search-counter": "\"__term__\" __count__ 件中の __result__ 件目"
}, },
"user": { "user": {
"loggedInAs": "__name__ としてログインしました", "loggedInAs": "__name__ としてログインしました",
@@ -182,10 +138,6 @@
} }
}, },
"notification": { "notification": {
"state": {
"flowsStopped": "フローを停止しました",
"flowsStarted": "フローを開始しました"
},
"warning": "<strong>警告</strong>: __message__", "warning": "<strong>警告</strong>: __message__",
"warnings": { "warnings": {
"undeployedChanges": "ノードの変更をデプロイしていません", "undeployedChanges": "ノードの変更をデプロイしていません",
@@ -234,8 +186,7 @@
"create-default-package": "デフォルトパッケージファイルの作成", "create-default-package": "デフォルトパッケージファイルの作成",
"no-thanks": "不要", "no-thanks": "不要",
"create-default-project": "デフォルトプロジェクトファイルの作成", "create-default-project": "デフォルトプロジェクトファイルの作成",
"show-merge-conflicts": "マージ競合を表示", "show-merge-conflicts": "マージ競合を表示"
"unknownNodesButton": "不明なノードを検索する"
} }
}, },
"clipboard": { "clipboard": {
@@ -313,19 +264,13 @@
"modifiedFlowsDesc": "変更したノードを含むフローのみデプロイ", "modifiedFlowsDesc": "変更したノードを含むフローのみデプロイ",
"modifiedNodes": "変更したノード", "modifiedNodes": "変更したノード",
"modifiedNodesDesc": "変更したノードのみデプロイ", "modifiedNodesDesc": "変更したノードのみデプロイ",
"startFlows": "開始",
"startFlowsDesc": "フローを開始",
"stopFlows": "停止",
"stopFlowsDesc": "フローを停止",
"restartFlows": "フローを再起動", "restartFlows": "フローを再起動",
"restartFlowsDesc": "デプロイされた現在のフローを再起動", "restartFlowsDesc": "デプロイされた現在のフローを再起動",
"successfulDeploy": "デプロイが成功しました", "successfulDeploy": "デプロイが成功しました",
"successfulRestart": "フローの再起動が成功しました", "successfulRestart": "フローの再起動が成功しました",
"deployFailed": "デプロイが失敗しました: __message__", "deployFailed": "デプロイが失敗しました: __message__",
"unusedConfigNodes": "使われていない設定ノードがあります。", "unusedConfigNodes": "使われていない設定ノードがあります。",
"unusedConfigNodesButton": "未使用の構成ノードを検索", "unusedConfigNodesLink": "設定を参照する",
"unknownNodesButton": "不明なノードを検索する",
"invalidNodesButton": "無効なノードを検索する",
"errors": { "errors": {
"noResponse": "サーバの応答がありません" "noResponse": "サーバの応答がありません"
}, },
@@ -505,29 +450,23 @@
"global": "グローバル", "global": "グローバル",
"workspace": "ワークスペース", "workspace": "ワークスペース",
"selectAll": "全てのノードを選択", "selectAll": "全てのノードを選択",
"selectNone": "選択を外す", "selectAllConnected": "接続された全てのノードを選択",
"selectAllConnected": "接続されたノードを選択",
"addRemoveNode": "ノードの選択、選択解除", "addRemoveNode": "ノードの選択、選択解除",
"editSelected": "選択したノードを編集", "editSelected": "選択したノードを編集",
"deleteSelected": "選択したノードや接続を削除", "deleteSelected": "選択したノードや接続を削除",
"deleteReconnect": "削除と再接続",
"importNode": "フローの読み込み", "importNode": "フローの読み込み",
"exportNode": "フローの書き出し", "exportNode": "フローの書き出し",
"nudgeNode": "選択したノードを移動(移動量小)", "nudgeNode": "選択したノードを移動(移動量小)",
"moveNode": "選択したノードを移動(移動量大)", "moveNode": "選択したノードを移動(移動量大)",
"toggleSidebar": "サイドバーの表示/非表示", "toggleSidebar": "サイドバーの表示/非表示",
"togglePalette": "パレットの表示/非表示", "togglePalette": "パレットの表示/非表示",
"copyNode": "ノードをコピー", "copyNode": "選択したノードをコピー",
"cutNode": "ノードを切り取り", "cutNode": "選択したノードを切り取り",
"pasteNode": "ノードを貼り付け", "pasteNode": "ノードを貼り付け",
"copyGroupStyle": "グループ様式をコピー",
"pasteGroupStyle": "グループ様式を貼り付け",
"undoChange": "変更操作を戻す", "undoChange": "変更操作を戻す",
"redoChange": "変更操作をやり直し",
"searchBox": "ノードを検索", "searchBox": "ノードを検索",
"managePalette": "パレットの管理", "managePalette": "パレットの管理",
"actionList": "動作一覧", "actionList": "動作一覧"
"splitWireWithLinks": "選択したワイヤーをlinkードで分離"
}, },
"library": { "library": {
"library": "ライブラリ", "library": "ライブラリ",
@@ -579,8 +518,7 @@
"nodeEnabled_plural": "ノードを有効化しました:", "nodeEnabled_plural": "ノードを有効化しました:",
"nodeDisabled": "ノードを無効化しました:", "nodeDisabled": "ノードを無効化しました:",
"nodeDisabled_plural": "ノードを無効化しました:", "nodeDisabled_plural": "ノードを無効化しました:",
"nodeUpgraded": "ノードモジュール __module__ をバージョン __version__ へ更新しました", "nodeUpgraded": "ノードモジュール __module__ をバージョン __version__ へ更新しました"
"unknownNodeRegistered": "ノードの読み込みエラー: <ul><li>__type__<br>__error__</li></ul>"
}, },
"editor": { "editor": {
"title": "パレットの管理", "title": "パレットの管理",
@@ -698,10 +636,13 @@
"globalConfig": "グローバル設定ノード", "globalConfig": "グローバル設定ノード",
"triggerAction": "アクションを実行", "triggerAction": "アクションを実行",
"find": "ワークスペース内を検索", "find": "ワークスペース内を検索",
"copyItemUrl": "要素のURLをコピー", "search": {
"copyURL2Clipboard": "URLをクリップボードにコピーしました", "configNodes": "設定ノード",
"showFlow": "表示", "unusedConfigNodes": "未使用の設定ノード",
"hideFlow": "非表示" "invalidNodes": "不正なノード",
"uknownNodes": "未知のノード",
"unusedSubflows": "未使用のサブフロー"
}
}, },
"help": { "help": {
"name": "ヘルプ", "name": "ヘルプ",
@@ -711,8 +652,7 @@
"showHelp": "ヘルプを表示", "showHelp": "ヘルプを表示",
"showInOutline": "アウトラインに表示", "showInOutline": "アウトラインに表示",
"showTopics": "トピックを表示", "showTopics": "トピックを表示",
"noHelp": "ヘルプのトピックが未選択", "noHelp": "ヘルプのトピックが未選択"
"changeLog": "更新履歴"
}, },
"config": { "config": {
"name": "設定ノードを表示", "name": "設定ノードを表示",
@@ -872,7 +812,7 @@
"pushFailed": "リモートに新しいコミットがあるため、プッシュに失敗しました。プルしてマージしてから、再度プッシュしてください。", "pushFailed": "リモートに新しいコミットがあるため、プッシュに失敗しました。プルしてマージしてから、再度プッシュしてください。",
"push": "プッシュ", "push": "プッシュ",
"pull": "プル", "pull": "プル",
"unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>", "unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>",
"showUnstagedChanges": "ステージングされていない変更を表示", "showUnstagedChanges": "ステージングされていない変更を表示",
"connectionFailed": "リモートリポジトリに接続できません: ", "connectionFailed": "リモートリポジトリに接続できません: ",
"pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>", "pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>",
@@ -923,20 +863,8 @@
"addTitle": "要素を追加" "addTitle": "要素を追加"
}, },
"search": { "search": {
"history": "検索履歴",
"clear": "全て削除",
"empty": "一致したものが見つかりませんでした", "empty": "一致したものが見つかりませんでした",
"addNode": "ノードを追加...", "addNode": "ノードを追加..."
"options": {
"configNodes": "設定ノード",
"unusedConfigNodes": "未使用の設定ノード",
"invalidNodes": "不正なノード",
"uknownNodes": "未知のノード",
"unusedSubflows": "未使用のサブフロー",
"hiddenFlows": "非表示のフロー",
"modifiedNodes": "修正したノードやフロー",
"thisFlow": "現在のフロー"
}
}, },
"expressionEditor": { "expressionEditor": {
"functions": "関数", "functions": "関数",
@@ -953,16 +881,10 @@
"errors": { "errors": {
"invalid-expr": "不正なJSONata式:\n __message__", "invalid-expr": "不正なJSONata式:\n __message__",
"invalid-msg": "不正なJSONメッセージ例:\n __message__", "invalid-msg": "不正なJSONメッセージ例:\n __message__",
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません", "context-unsupported": "$flowContext や $globalContextの\nコンテキスト機能をテストできません",
"env-unsupported": "$env関数はテストできません", "eval": "表現評価エラー:\n __message__"
"moment-unsupported": "$moment関数はテストできません",
"clone-unsupported": "$clone関数はテストできません",
"eval": "式評価エラー:\n __message__"
} }
}, },
"monaco": {
"setTheme": "テーマを設定:"
},
"jsEditor": { "jsEditor": {
"title": "JavaScriptエディタ" "title": "JavaScriptエディタ"
}, },
@@ -974,8 +896,6 @@
"format": "JSONフォーマット", "format": "JSONフォーマット",
"rawMode": "JSONを編集", "rawMode": "JSONを編集",
"uiMode": "ビジュアルエディタ", "uiMode": "ビジュアルエディタ",
"rawMode-readonly": "JSON",
"uiMode-readonly": "ビジュアル",
"insertAbove": "上に挿入", "insertAbove": "上に挿入",
"insertBelow": "下に挿入", "insertBelow": "下に挿入",
"addItem": "要素を追加", "addItem": "要素を追加",
@@ -1002,10 +922,7 @@
"quote": "引用", "quote": "引用",
"link": "リンク", "link": "リンク",
"horizontal-rule": "区切り線", "horizontal-rule": "区切り線",
"toggle-preview": "プレビュー表示切替え", "toggle-preview": "プレビュー表示切替え"
"mermaid": {
"summary": "Mermaid図"
}
}, },
"bufferEditor": { "bufferEditor": {
"title": "バッファエディタ", "title": "バッファエディタ",
@@ -1140,8 +1057,7 @@
"not-git": "Gitリポジトリではありません", "not-git": "Gitリポジトリではありません",
"no-resource": "リポジトリが見つかりません", "no-resource": "リポジトリが見つかりません",
"cant-get-ssh-key-path": "エラー! 選択したSSHキーのパスを取得できません。", "cant-get-ssh-key-path": "エラー! 選択したSSHキーのパスを取得できません。",
"unexpected_error": "予期しないエラー", "unexpected_error": "予期しないエラー"
"clearContext": "プロジェクトを切り替る際にコンテキストを初期化"
}, },
"delete": { "delete": {
"confirm": "プロジェクトを削除しても良いですか?" "confirm": "プロジェクトを削除しても良いですか?"
@@ -1188,15 +1104,6 @@
"preview": "UIプレビュー", "preview": "UIプレビュー",
"defaultValue": "デフォルト値" "defaultValue": "デフォルト値"
}, },
"tourGuide": {
"takeATour": "ツアーを開始",
"start": "開始",
"next": "次へ",
"welcomeTours": "ウェルカムツアー"
},
"diagnostics": {
"title": "システム情報"
},
"languages": { "languages": {
"de": "ドイツ語", "de": "ドイツ語",
"en-US": "英語", "en-US": "英語",
@@ -1205,186 +1112,5 @@
"ru": "ロシア語", "ru": "ロシア語",
"zh-CN": "中国語(簡体)", "zh-CN": "中国語(簡体)",
"zh-TW": "中国語(繁体)" "zh-TW": "中国語(繁体)"
},
"validator": {
"errors": {
"invalid-json": "JSONデータが不正: __error__",
"invalid-json-prop": "__prop__: JSONデータが不正: __error__",
"invalid-prop": "プロパティ式が不正",
"invalid-prop-prop": "__prop__: プロパティ式が不正",
"invalid-num": "数値が不正",
"invalid-num-prop": "__prop__: 数値が不正",
"invalid-regexp": "入力パターンが不正",
"invalid-regex-prop": "__prop__: 入力パターンが不正",
"missing-required-prop": "__prop__: プロパティが未設定",
"invalid-config": "__prop__: 設定ノードが不正",
"missing-config": "__prop__: 設定ノードが存在しません",
"validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
}
},
"contextMenu": {
"insert": "挿入",
"node": "ノード",
"junction": "分岐点",
"linkNodes": "Linkード"
},
"env-var": {
"environment": "環境変数",
"header": "大域環境変数",
"revert": "破棄"
},
"action-list": {
"toggle-show-tips": "ヒント表示切替",
"show-about": "Node-REDの説明を表示",
"show-welcome-tour": "ウェルカムツアー表示",
"show-next-tab": "次のタブを表示",
"show-previous-tab": "前のタブを表示",
"add-flow": "フローを追加",
"add-flow-to-right": "フローを右に追加",
"edit-flow": "フローを編集",
"remove-flow": "フローを削除",
"enable-flow": "フローを有効化",
"disable-flow": "フローを無効化",
"hide-flow": "フローを隠す",
"hide-other-flows": "他のフローを非表示",
"hide-all-flows": "全てのフローを非表示",
"show-all-flows": "全てのフローを表示",
"show-last-hidden-flow": "最後に非表示にしたフローを表示",
"list-modified-nodes": "修正したフローを表示",
"list-hidden-flows": "非表示フローを表示",
"list-flows": "フロー一覧",
"list-subflows": "サブフロー一覧",
"go-to-previous-location": "前の位置に移動",
"go-to-next-location": "次の位置に移動",
"copy-selection-to-internal-clipboard": "選択をクリップボードにコピー",
"cut-selection-to-internal-clipboard": "選択をクリップボードに切り取り",
"paste-from-internal-clipboard": "クリップボードから貼り付け",
"detach-selected-nodes": "選択ノードを接続から外す",
"delete-selection": "選択を削除",
"delete-selection-and-reconnect": "選択を削除し再接続",
"edit-selected-node": "選択したノードを編集",
"go-to-selection": "選択に移動",
"undo": "変更操作を戻す",
"redo": "変更操作をやり直し",
"select-all-nodes": "全てのノードを選択",
"select-none": "ノードを選択",
"enable-selected-nodes": "選択ノードを有効化",
"disable-selected-nodes": "選択ノードを無効化",
"toggle-show-grid": "グリッド表示切替",
"toggle-snap-grid": "ノードの配置補助切替",
"toggle-status": "ステータス表示切替",
"show-selected-node-labels": "選択したノードのラベルを表示",
"hide-selected-node-labels": "選択したノードのラベルを非表示",
"scroll-view-up": "上スクロール",
"scroll-view-right": "右スクロール",
"scroll-view-down": "下スクロール",
"scroll-view-left": "左スクロール",
"step-view-up": "一単位上スクロール",
"step-view-right": "一単位右スクロール",
"step-view-down": "一単位下スクロール",
"step-view-left": "一単位左スクロール",
"move-selection-up": "選択を上移動",
"move-selection-right": "選択を右移動",
"move-selection-down": "選択を下移動",
"move-selection-left": "選択を左移動",
"move-selection-forwards": "選択を前面に移動",
"move-selection-backwards": "選択を背面に移動",
"move-selection-to-front": "選択を最前面に移動",
"move-selection-to-back": "選択を最背面に移動",
"step-selection-up": "選択を一単位上移動",
"step-selection-right": "選択を一単位右移動",
"step-selection-down": "選択を一単位下移動",
"step-selection-left": "選択を一単位左移動",
"select-connected-nodes": "接続されたノードを選択",
"select-downstream-nodes": "後方に接続されたノードを選択",
"select-upstream-nodes": "前方に接続されたノードを選択",
"go-to-next-node": "次のノードに移動",
"go-to-previous-node": "前のノードに移動",
"go-to-next-sibling": "次の兄弟ノードに移動",
"go-to-previous-sibling": "前の兄弟ノードに移動",
"go-to-nearest-node-on-left": "最も近い左側ノードに移動",
"go-to-nearest-node-on-right": "最も近い右側ノードに移動",
"go-to-nearest-node-above": "最も近い上側ノードに移動",
"go-to-nearest-node-below": "最も近い下側ノードに移動",
"align-selection-to-grid": "選択を整列",
"align-selection-to-left": "選択を左揃え",
"align-selection-to-right": "選択を右揃え",
"align-selection-to-top": "選択を上揃え",
"align-selection-to-bottom": "選択を下揃え",
"align-selection-to-middle": "選択を上下中央揃え",
"align-selection-to-center": "選択を左右中央揃え",
"distribute-selection-horizontally": "選択を左右に整列",
"distribute-selection-vertically": "選択を上下に整列",
"wire-series-of-nodes": "ノードを一続きに接続",
"wire-node-to-multiple": "ノードを複数に接続",
"wire-multiple-to-node": "複数からノードへ接続",
"split-wire-with-link-nodes": "ワイヤーをlinkードで分割",
"generate-node-names": "ノード名を生成",
"show-user-settings": "ユーザ設定を表示",
"show-help": "ヘルプを表示",
"toggle-palette": "パレットの表示切替",
"show-event-log": "イベントログを表示",
"manage-palette": "パレットの管理",
"toggle-sidebar": "サイドバーの表示切替",
"show-info-tab": "ノード情報タブの表示",
"show-help-tab": "ノードヘルプタブの表示",
"show-config-tab": "設定ノードタブの表示",
"select-all-config-nodes": "全ての設定ノードを選択",
"delete-config-selection": "選択した設定ノードを削除",
"show-context-tab": "コンテキストデータタブを表示",
"create-subflow": "サブフローを作成",
"convert-to-subflow": "選択をサブフローに変換",
"group-selection": "選択をグループ化",
"ungroup-selection": "選択をグループ解除",
"merge-selection-to-group": "選択をグループにマージ",
"remove-selection-from-group": "選択をグループから削除",
"copy-group-style": "グループのスタイルをコピー",
"paste-group-style": "グループのスタイルを貼り付け",
"show-export-dialog": "書き出しダイアログを表示",
"show-import-dialog": "読み込みダイアログを表示",
"show-library-export-dialog": "ライブラリ書き出しダイアログを表示",
"show-library-import-dialog": "ライブラリ読み込みダイアログを表示",
"show-examples-import-dialog": "サンプル読み込みダイアログを表示",
"search": "検索",
"search-previous": "前を検索",
"search-next": "次を検索",
"show-action-list": "動作一覧を表示",
"confirm-edit-tray": "編集を完了",
"cancel-edit-tray": "編集をキャンセル",
"show-remote-diff": "リモートとの変更差分を表示",
"deploy-flows": "フローをデプロイ",
"restart-flows": "フローを再起動",
"set-deploy-type-to-full": "デプロイを「全て」に設定",
"set-deploy-type-to-modified-flows": "デプロイを「変更したフロー」に設定",
"set-deploy-type-to-modified-nodes": "デプロイを「変更したノード」に設定",
"show-debug-tab": "デバッグタブを表示",
"clear-debug-messages": "デバッグメッセージを削除",
"clear-filtered-debug-messages": "フィルタしたデバッグメッセージを削除",
"activate-selected-debug-nodes": "選択したデバッグノードを有効化",
"activate-all-debug-nodes": "全てのデバッグノードを有効化",
"activate-all-flow-debug-nodes": "フロー内の全デバッグノードを有効化",
"deactivate-selected-debug-nodes": "選択したデバッグノードを無効化",
"deactivate-all-debug-nodes": "全てのデバッグノードを無効化",
"deactivate-all-flow-debug-nodes": "フロー内の全デバッグノードを無効化",
"zoom-in": "ズームイン",
"zoom-out": "ズームアウト",
"zoom-reset": "ズームリセット",
"toggle-navigator": "ナビゲータ表示切替",
"show-system-info": "システム情報",
"split-wires-with-junctions": "分岐点によりワイヤーを分割",
"new-project": "新しいプロジェクト",
"open-project": "プロジェクトを開く",
"show-project-settings": "プロジェクト設定を表示",
"show-version-control-tab": "バージョンコントロールタブを表示",
"start-flows": "フローを開始",
"stop-flows": "フローを停止",
"copy-item-url": "要素のURLをコピー",
"copy-item-edit-url": "要素の編集URLをコピー",
"move-flow-to-start": "フローを先頭に移動",
"move-flow-to-end": "フローを末尾に移動",
"show-global-env": "大域環境変数を表示",
"lock-flow": "フローを固定",
"unlock-flow": "フローの固定を解除",
"show-node-help": "ノードのヘルプを表示"
} }
} }

View File

@@ -17,7 +17,7 @@
"tip14": "[shift] を押しながらノードを [click] すると、接続された全てのノードを選択できます。", "tip14": "[shift] を押しながらノードを [click] すると、接続された全てのノードを選択できます。",
"tip15": "[ctrl] を押しながらノードを [click] すると、選択/非選択を切り替えできます。", "tip15": "[ctrl] を押しながらノードを [click] すると、選択/非選択を切り替えできます。",
"tip16": "{{core:show-previous-tab}} や {{core:show-next-tab}} で、タブの切り替えができます。", "tip16": "{{core:show-previous-tab}} や {{core:show-next-tab}} で、タブの切り替えができます。",
"tip17": "ノードのプロティ設定画面にて {{core:confirm-edit-tray}} を押すと、変更を確定できます。また、 {{core:cancel-edit-tray}} を押すと、変更を取り消せます。", "tip17": "ノードのプロティ設定画面にて {{core:confirm-edit-tray}} を押すと、変更を確定できます。また、 {{core:cancel-edit-tray}} を押すと、変更を取り消せます。",
"tip18": "ノードを選択し、 {{core:edit-selected-node}} を押すとプロパティ設定画面が表示されます。" "tip18": "ノードを選択し、 {{core:edit-selected-node}} を押すとプロパティ設定画面が表示されます。"
} }
} }

View File

@@ -52,8 +52,8 @@
"desc": "文字列 `str` からパターン `pattern` を検索し、置換文字列 `replacement` に置き換えます。\n\n任意の引数 `limit` には、置換回数の上限値を指定します。" "desc": "文字列 `str` からパターン `pattern` を検索し、置換文字列 `replacement` に置き換えます。\n\n任意の引数 `limit` には、置換回数の上限値を指定します。"
}, },
"$now": { "$now": {
"args": "$[picture [, timezone]]", "args": "",
"desc": "ISO 8601互換形式の時刻を生成し、文字列として返します。pictureおよびtimezoneパラメータが指定されている場合、現在時刻を`$fromMillis()`関数の説明に従ってフォーマットします。" "desc": "ISO 8601互換形式の時刻を生成し、文字列として返します。"
}, },
"$base64encode": { "$base64encode": {
"args": "string", "args": "string",
@@ -200,8 +200,8 @@
"desc": "文字数が引数 `width` の絶対値以上となるよう、必要に応じて追加文字を付け足した `string` のコピーを返します。\n\n`width` が正の値の場合、文字列の右側に追加文字を付け足します。もし負の値の場合、文字列の左側に追加文字を付け足します。\n\n任意の引数 `char` には、本関数で用いる追加文字を指定します。もし追加文字を指定しない場合は、既定値として空白文字を使用します。" "desc": "文字数が引数 `width` の絶対値以上となるよう、必要に応じて追加文字を付け足した `string` のコピーを返します。\n\n`width` が正の値の場合、文字列の右側に追加文字を付け足します。もし負の値の場合、文字列の左側に追加文字を付け足します。\n\n任意の引数 `char` には、本関数で用いる追加文字を指定します。もし追加文字を指定しない場合は、既定値として空白文字を使用します。"
}, },
"$fromMillis": { "$fromMillis": {
"args": "number, [, picture [, timezone]]", "args": "number",
"desc": "Unixエポック(1 January, 1970 UTC)からの経過ミリ秒を表す数値を、`picture`の指定に従ってタイムスタンプの文字列に変換します。\n\n`picture`パラメータが指定されない場合、ISO 8601形式に変換します。\n\n`picture`を指定すると、指定した文字列に従って変換を行います。この変換はXPath F&O 3.1仕様におけるXPath/XQueryの2引数形式`format-dateTime`と同様です。`picture`パラメータはタイムスタンプの変換形式を定義し、その書式は`format-dateTime`と同じです。\n\n`timezone`を指定すると、指定タイムゾーンで変換します。`timezone`は'±HHMM'という形式で指定します。ここで、±は+もしくは-記号を表し、HHMMはUTCからの差分時間と分を表します。正の差分はUTCの東、負の差分は西のタイムゾーンとなります。" "desc": "Unixエポック(1 January, 1970 UTC)からの経過ミリ秒を表す数値を、ISO 8601形式のタイムスタンプの文字列に変換します。"
}, },
"$formatNumber": { "$formatNumber": {
"args": "number, picture [, options]", "args": "number, picture [, options]",

View File

@@ -56,7 +56,7 @@
"displayConfig": "설정노드 보기", "displayConfig": "설정노드 보기",
"import": "가져오기", "import": "가져오기",
"export": "내보내기", "export": "내보내기",
"search": "플로우 색", "search": "플로우 색",
"searchInput": "플로우 검색", "searchInput": "플로우 검색",
"subflows": "보조 플로우", "subflows": "보조 플로우",
"createSubflow": "보조 플로우 생성", "createSubflow": "보조 플로우 생성",
@@ -141,8 +141,7 @@
"create-default-package": "기본 패키지 파일 생성", "create-default-package": "기본 패키지 파일 생성",
"no-thanks": "괜찮습니다", "no-thanks": "괜찮습니다",
"create-default-project": "기본 프로젝트 파일 생성", "create-default-project": "기본 프로젝트 파일 생성",
"show-merge-conflicts": "병합 충돌 보여주기", "show-merge-conflicts": "병합 충돌 보여주기"
"unknownNodesButton": "알 수 없는 노드 검색"
} }
}, },
"clipboard": { "clipboard": {
@@ -204,9 +203,7 @@
"successfulRestart": "플로우 재시작을 성공했습니다", "successfulRestart": "플로우 재시작을 성공했습니다",
"deployFailed": "배포 실패 : __message__", "deployFailed": "배포 실패 : __message__",
"unusedConfigNodes": "사용되지 않는 설정노드가 있습니다", "unusedConfigNodes": "사용되지 않는 설정노드가 있습니다",
"unusedConfigNodesButton":"사용하지 않는 구성 노드 검색", "unusedConfigNodesLink": "여기를 클릭하면 볼 수 있습니다",
"unknownNodesButton":"알 수 없는 노드 검색",
"invalidNodesButton":"잘못된 노드 검색",
"errors": { "errors": {
"noResponse": "서버의 응답이 없습니다" "noResponse": "서버의 응답이 없습니다"
}, },

View File

View File

25
packages/node_modules/@node-red/editor-client/locales/ru/editor.json vendored Normal file → Executable file
View File

@@ -183,8 +183,7 @@
"create-default-package": "Создать файл пакета по умолчанию", "create-default-package": "Создать файл пакета по умолчанию",
"no-thanks": "Нет, спасибо", "no-thanks": "Нет, спасибо",
"create-default-project": "Создать файлы проекта по умолчанию", "create-default-project": "Создать файлы проекта по умолчанию",
"show-merge-conflicts": "Показать конфликты слияния", "show-merge-conflicts": "Показать конфликты слияния"
"unknownNodesButton": "Поиск неизвестных узлов"
} }
}, },
"clipboard": { "clipboard": {
@@ -278,9 +277,7 @@
"successfulRestart": "Потоки успешно перезапущены", "successfulRestart": "Потоки успешно перезапущены",
"deployFailed": "Развертывание не удалось: __message__", "deployFailed": "Развертывание не удалось: __message__",
"unusedConfigNodes":"У вас есть неиспользуемых узлы конфигурации.", "unusedConfigNodes":"У вас есть неиспользуемых узлы конфигурации.",
"unusedConfigNodesButton":"Поиск неиспользуемых узлов конфигурации", "unusedConfigNodesLink":"Нажмите здесь, чтобы их увидеть",
"unknownNodesButton":"Поиск неизвестных узлов",
"invalidNodesButton":"Поиск недопустимых узлов",
"errors": { "errors": {
"noResponse": "нет ответа от сервера" "noResponse": "нет ответа от сервера"
}, },
@@ -653,7 +650,14 @@
"empty": "пусто", "empty": "пусто",
"globalConfig": "Глобальные конфиг узлы", "globalConfig": "Глобальные конфиг узлы",
"triggerAction": "Вызвать действие", "triggerAction": "Вызвать действие",
"find": "Найти в рабочей области" "find": "Найти в рабочей области",
"search": {
"configNodes": "Узлы конфигурации",
"unusedConfigNodes": "Неиспользуемые узлы конфигурации",
"invalidNodes": "Недействительные узлы",
"uknownNodes": "Неизвестные узлы",
"unusedSubflows": "Неиспользуемые подпотоки"
}
}, },
"help": { "help": {
"name": "Справка", "name": "Справка",
@@ -884,14 +888,7 @@
}, },
"search": { "search": {
"empty": "Ничего не найдено", "empty": "Ничего не найдено",
"addNode": "добавить узел...", "addNode": "добавить узел..."
"options": {
"configNodes": "Узлы конфигурации",
"unusedConfigNodes": "Неиспользуемые узлы конфигурации",
"invalidNodes": "Недействительные узлы",
"uknownNodes": "Неизвестные узлы",
"unusedSubflows": "Неиспользуемые подпотоки"
}
}, },
"expressionEditor": { "expressionEditor": {
"functions": "Функции", "functions": "Функции",

View File

View File

View File

@@ -97,7 +97,7 @@
"rename": "重命名", "rename": "重命名",
"delete": "删除", "delete": "删除",
"keyboardShortcuts": "键盘快捷方式", "keyboardShortcuts": "键盘快捷方式",
"login": "登", "login": "登",
"logout": "退出", "logout": "退出",
"editPalette": "节点管理", "editPalette": "节点管理",
"other": "其他", "other": "其他",
@@ -122,16 +122,16 @@
"zoom-in": "放大" "zoom-in": "放大"
}, },
"user": { "user": {
"loggedInAs": "作为 __name__ 登", "loggedInAs": "作为 __name__ 登",
"username": "账号", "username": "账号",
"password": "密码", "password": "密码",
"login": "登", "login": "登",
"loginFailed": "登失败", "loginFailed": "登失败",
"notAuthorized": "未授权", "notAuthorized": "未授权",
"errors": { "errors": {
"settings": "设置信息需要登后才能访问", "settings": "设置信息需要登后才能访问",
"deploy": "改动需要登后才能部署", "deploy": "改动需要登后才能部署",
"notAuthorized": "此操作需要登后才能执行" "notAuthorized": "此操作需要登后才能执行"
} }
}, },
"notification": { "notification": {
@@ -182,8 +182,7 @@
"create-default-package": "创建默认的包文件", "create-default-package": "创建默认的包文件",
"no-thanks": "不了,谢谢", "no-thanks": "不了,谢谢",
"create-default-project": "创建默认项目文件", "create-default-project": "创建默认项目文件",
"show-merge-conflicts": "显示合并冲突", "show-merge-conflicts": "显示合并冲突"
"unknownNodesButton": "搜索未知节点"
} }
}, },
"clipboard": { "clipboard": {
@@ -226,7 +225,7 @@
"compact": "紧凑", "compact": "紧凑",
"formatted": "已格式化", "formatted": "已格式化",
"copy": "导出到剪贴板", "copy": "导出到剪贴板",
"export": "导出到库", "export": "到处到库",
"exportAs": "导出为", "exportAs": "导出为",
"overwrite": "替换", "overwrite": "替换",
"exists": "<p><b>\"__file__\"</b>已存在</p><p>是否要替换它?</p>" "exists": "<p><b>\"__file__\"</b>已存在</p><p>是否要替换它?</p>"
@@ -265,9 +264,7 @@
"successfulRestart": "成功重启流程", "successfulRestart": "成功重启流程",
"deployFailed": "部署失败: __message__", "deployFailed": "部署失败: __message__",
"unusedConfigNodes": "您有一些未使用的配置节点", "unusedConfigNodes": "您有一些未使用的配置节点",
"unusedConfigNodesButton":"搜索未使用的配置节点", "unusedConfigNodesLink": "点击此处查看它们",
"unknownNodesButton":"搜索未知节点",
"invalidNodesButton":"搜索无效节点",
"errors": { "errors": {
"noResponse": "服务器没有响应" "noResponse": "服务器没有响应"
}, },
@@ -617,7 +614,14 @@
"empty": "空的", "empty": "空的",
"globalConfig": "全局配置节点", "globalConfig": "全局配置节点",
"triggerAction": "触发动作", "triggerAction": "触发动作",
"find": "在工作区中查找" "find": "在工作区中查找",
"search": {
"configNodes": "配置节点",
"unusedConfigNodes": "未使用的配置节点",
"invalidNodes": "无效的节点",
"uknownNodes": "未知的节点",
"unusedSubflows": "未使用的子流程"
}
}, },
"help": { "help": {
"name": "帮助", "name": "帮助",
@@ -838,14 +842,7 @@
}, },
"search": { "search": {
"empty": "找不到匹配", "empty": "找不到匹配",
"addNode": "添加一个节点...", "addNode": "添加一个节点..."
"options": {
"configNodes": "配置节点",
"unusedConfigNodes": "未使用的配置节点",
"invalidNodes": "无效的节点",
"uknownNodes": "未知的节点",
"unusedSubflows": "未使用的子流程"
}
}, },
"expressionEditor": { "expressionEditor": {
"functions": "功能", "functions": "功能",

View File

@@ -182,8 +182,7 @@
"create-default-package": "創建默認的包文件", "create-default-package": "創建默認的包文件",
"no-thanks": "不了,謝謝", "no-thanks": "不了,謝謝",
"create-default-project": "創建默認項目文件", "create-default-project": "創建默認項目文件",
"show-merge-conflicts": "顯示合併衝突", "show-merge-conflicts": "顯示合併衝突"
"unknownNodesButton": "搜索未知節點"
} }
}, },
"clipboard": { "clipboard": {
@@ -265,9 +264,7 @@
"successfulRestart": "成功重啟流程", "successfulRestart": "成功重啟流程",
"deployFailed": "部署失敗: __message__", "deployFailed": "部署失敗: __message__",
"unusedConfigNodes": "您有一些未使用的配置節點", "unusedConfigNodes": "您有一些未使用的配置節點",
"unusedConfigNodesButton":"搜索未使用的配置節點", "unusedConfigNodesLink": "點擊此處查看它們",
"unknownNodesButton":"搜索未知節點",
"invalidNodesButton":"搜索無效節點",
"errors": { "errors": {
"noResponse": "伺服器沒有回應" "noResponse": "伺服器沒有回應"
}, },
@@ -617,7 +614,14 @@
"empty": "空的", "empty": "空的",
"globalConfig": "全局配置節點", "globalConfig": "全局配置節點",
"triggerAction": "觸發動作", "triggerAction": "觸發動作",
"find": "在工作區中查找" "find": "在工作區中查找",
"search": {
"configNodes": "配置節點",
"unusedConfigNodes": "未使用的配置節點",
"invalidNodes": "無效的節點",
"uknownNodes": "未知的節點",
"unusedSubflows": "未使用的子流程"
}
}, },
"help": { "help": {
"name": "幫助", "name": "幫助",
@@ -838,14 +842,7 @@
}, },
"search": { "search": {
"empty": "找不到匹配", "empty": "找不到匹配",
"addNode": "添加一個節點...", "addNode": "添加一個節點..."
"options": {
"configNodes": "配置節點",
"unusedConfigNodes": "未使用的配置節點",
"invalidNodes": "無效的節點",
"uknownNodes": "未知的節點",
"unusedSubflows": "未使用的子流程"
}
}, },
"expressionEditor": { "expressionEditor": {
"functions": "功能", "functions": "功能",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/editor-client", "name": "@node-red/editor-client",
"version": "3.1.0-beta.1", "version": "1.3.7",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -14,5 +14,5 @@
"name": "Dave Conway-Jones" "name": "Dave Conway-Jones"
} }
], ],
"main": "./index.js" "main": "./lib/index.js"
} }

View File

@@ -76,7 +76,7 @@ oop.inherits(NRJavaScriptWorker, Mirror);
(function() { (function() {
this.setOptions = function(options) { this.setOptions = function(options) {
o.options = { this.options = {
// undef: true, // undef: true,
// unused: true, // unused: true,
esversion: 9, esversion: 9,
@@ -98,7 +98,7 @@ oop.inherits(NRJavaScriptWorker, Mirror);
if (options) { if (options) {
for (var opt in options) { for (var opt in options) {
if (options.hasOwnProperty(opt)) { if (options.hasOwnProperty(opt)) {
o.options[opt] = options[opt]; this.options[opt] = options.opt;
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

View File

@@ -1 +0,0 @@
<svg width="50" height="5" viewBox="0, 0, 50, 5" xmlns="http://www.w3.org/2000/svg"><path d="M0 1H50V4H0Z" fill="#CCC"/></svg>

Before

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

View File

@@ -1 +0,0 @@
<svg width="5" height="50" viewBox="0, 0, 5, 50" xmlns="http://www.w3.org/2000/svg"><path d="M1 0H4V50H1Z" fill="#CCC"/></svg>

Before

Width:  |  Height:  |  Size: 127 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="512" width="512"><g transform="translate(0 -540.36)"><path fill="#8f0000" color="#000" d="M0 540.36h512v392H0z"/><rect ry="0" height="108.23" width="500.23" stroke="#fff" y="938.25" x="5.89" stroke-width="11.77" fill="#fff"/><path style="text-decoration-color:#000;isolation:auto;mix-blend-mode:normal;solid-color:#000;block-progression:tb;text-decoration-line:none;white-space:normal;text-indent:0;text-transform:none;text-decoration-style:solid" d="M122.88 305.82a4.46 4.46 0 0 0-4.38 4.42v.78c-2.23.1-4.04.54-5.33 1.43a10.5 10.5 0 0 0-3.18 3.87c-.71 1.3-1.3 2.41-2.15 3.2-.72.66-1.8 1.12-3.45 1.32a4.37 4.37 0 0 0-4.3-3.95H82.91a4.43 4.43 0 0 0-4.42 4.35v4.24a4.43 4.43 0 0 0 4.42 4.36h17.16a4.4 4.4 0 0 0 4.4-4.36v-1.6c9.72.14 12.46 2.6 15.59 5.33 3 2.62 6.66 5.38 15.43 5.5v.73a4.49 4.49 0 0 0 4.46 4.38h17.09c2.38 0 4.45-2 4.45-4.38v-4.24a4.49 4.49 0 0 0-4.45-4.38h-17.1c-2.38 0-4.45 2-4.45 4.38v.58c-8.1-.06-10.48-2.15-13.5-4.79-2.5-2.19-5.64-4.58-11.94-5.58 1.17-1.18 1.88-2.52 2.51-3.66.68-1.23 1.29-2.2 2.27-2.88.76-.52 1.98-.84 3.66-.94v.55c0 2.39 2 4.34 4.38 4.34h17.24a4.39 4.39 0 0 0 4.38-4.34v-4.24c0-2.38-2-4.42-4.38-4.42zm0 3h17.24c.8 0 1.38.62 1.38 1.42v4.24c0 .81-.57 1.34-1.38 1.34h-17.24c-.8 0-1.38-.53-1.38-1.34v-4.24c0-.8.57-1.42 1.38-1.42zm-39.96 11.02h17.16c.81 0 1.42.6 1.42 1.4v4.24c0 .81-.61 1.41-1.42 1.41H82.92c-.8 0-1.42-.6-1.42-1.4v-4.25c0-.8.61-1.4 1.42-1.4zm57.04 9.98h17.09c.8 0 1.45.57 1.45 1.38v4.17c0 .8-.65 1.45-1.45 1.45h-17.1c-.8 0-1.45-.65-1.45-1.45v-4.17c0-.8.65-1.38 1.46-1.38z" fill="#fff" color="#000" transform="matrix(4 0 0 4 -162 -450.91)"/><g fill="#8f0000"><path d="M91 954.34v8.45l-8 1.45v60.07H69.03l-28.53-47.1-.5.05v37.2l8 1.44v8.41H19v-8.4l7.45-1.45v-50.22L19 962.79v-8.46h21.48l28.37 47.1.15-.04v-37.15l-7-1.45v-8.45h29zM95 997.83q0-11.63 6.49-19.03 6.53-7.45 18.02-7.45 11.53 0 18.02 7.4 6.54 7.4 6.54 19.08v1q0 11.74-6.54 19.14-6.49 7.35-17.93 7.35-11.58 0-18.11-7.35-6.5-7.4-6.5-19.13v-1.01zm14.03 1q0 7.12 2.5 11.45 2.5 4.28 8.08 4.28 5.43 0 7.93-4.33 2.54-4.33 2.54-11.4v-1q0-6.92-2.54-11.3-2.55-4.37-8.03-4.37t-7.98 4.37-2.5 11.3v1zM184.48 1017.96a17.15 17.15 0 0 1-5.82 5.48 15.17 15.17 0 0 1-7.59 1.88c-6.4 0-11.4-2.35-14.95-7.03-3.52-4.67-5.13-10.86-5.13-18.55v-1c0-8.21 1.62-14.83 5.18-19.86 3.56-5.03 8.56-7.54 15-7.54 2.6 0 4.93.57 7.01 1.73a17.94 17.94 0 0 1 5.81 4.8v-18.64l-8-1.45v-8.46h22v65.13l6 1.44v8.43h-18.45l-1.06-6.36zm-19.49-18.22c0 4.55.63 8.14 2.14 10.77 1.54 2.6 4.04 3.9 7.5 3.9 2.05 0 3.83-.43 5.33-1.26 1.5-.83 3.07-2.03 4.03-3.6v-22.06a11.27 11.27 0 0 0-4.03-3.85 9.62 9.62 0 0 0-5.24-1.4c-3.43 0-5.92 1.53-7.5 4.57s-2.23 7.02-2.23 11.92v1.01zM233.7 1025.28c-7.5 0-13.5-2.4-17.98-7.21-4.48-4.81-6.73-10.91-6.73-18.32v-1.92c0-7.72 2.12-14.08 6.35-19.08 4.26-5 9.96-7.46 17.1-7.43 7.03 0 12.47 2.1 16.35 6.33a23.46 23.46 0 0 1 6.2 17.15v7.52h-31.43l-.1.41c.26 3.43 1.4 6.25 3.41 8.46 2.05 2.21 4.83 3.32 8.32 3.32 3.1 0 5.69-.3 7.74-.91 2.05-.64 4.29-1.64 6.73-2.98l3.8 8.65a27.59 27.59 0 0 1-8.37 4.28 35.28 35.28 0 0 1-11.4 1.73zm-1.25-43.16c-2.6 0-4.65.99-6.15 2.98s-2.44 4.6-2.8 7.83l.15.4H241v-1.41c0-2.98-.84-5.35-2.25-7.11-1.37-1.8-3.47-2.7-6.3-2.7zM291.99 1000.32h-27v-11h27zM331.88 954.34c7.95 0 14.18 1.82 18.7 5.47 4.52 3.63 6.4 8.64 6.4 15.05 0 3.52-.57 6.58-2.46 9.18-1.89 2.6-4.66 4.7-8.31 6.3 4.13 1.21 7.1 3.25 8.89 6.1a19.02 19.02 0 0 1 2.89 10.52v3.56c0 1.54.15 2.74.76 3.6.6.84 1.62 1.34 3.03 1.5l1.2.24v8.46h-6.73c-4.58 0-7.8-1.24-9.66-3.7s-2.6-5.66-2.6-9.57v-3.99c0-3.4-1.1-6.05-2.93-7.98-1.8-1.95-4.34-2.98-7.64-3.07H322v18.45l7 1.44v8.42h-29v-8.42l8-1.44v-50.22l-8-1.44v-8.46h31.89zm-9.95 30.85h9.71c3.91 0 6.84-.83 8.8-2.5s2.93-4.07 2.93-7.2c0-3.15-.98-5.65-2.93-7.5-1.92-1.9-4.78-2.84-8.56-2.84h-9.9v20.04zM412.99 993.32h-23v20h22.21l.63-8h10.2v18.99H368v-8.42l8-1.44v-50.22l-8-1.44v-8.47h54.95v19h-10.3l-.63-8H390v17h23v11zM462.48 954.36c8.55 0 15.6 2.71 21.14 8.19 5.55 5.45 8.36 12.42 8.36 20.98v11.58c0 8.59-2.81 15.63-8.36 21.08-5.54 5.41-12.59 8.12-21.14 8.12h-31.5v-8.41l7-1.52v-50.22l-7-1.37v-8.43l7.46-.08 24.04.08zm-10.5 10.76v48.4l9.77.02c5.03.02 8.98-1.7 11.83-5.1 2.85-3.39 4.4-7.8 4.4-13.28v-11.68c0-5.42-1.55-9.84-4.4-13.24-2.85-3.4-6.8-5.1-11.83-5.1l-9.77-.02z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,4 +0,0 @@
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg">
<path color="#000" fill="#8c101c" d="M0 0h32v32H0z"></path>
<path style="fill:#ffffff;stroke:#000000;stroke-width:0" d="M 24,16 8,24 8,8 Z" fill="none" stroke="#000" stroke-width="1.5"></path>
</svg>

Before

Width:  |  Height:  |  Size: 271 B

View File

@@ -1,4 +0,0 @@
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg">
<path color="#000" fill="#8c101c" d="M0 0h32v32H0z"></path>
<rect style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0;" width="15" height="15" x="8" y="8.5"></rect>
</svg>

Before

Width:  |  Height:  |  Size: 256 B

View File

@@ -13,23 +13,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ **/
/**
* An API for undo / redo history buffer
* @namespace RED.history
*/
RED.history = (function() { RED.history = (function() {
var undoHistory = []; var undoHistory = [];
var redoHistory = []; var redoHistory = [];
function nodeOrJunction(id) {
var node = RED.nodes.node(id);
if (node) {
return node;
}
return RED.nodes.junction(id);
}
function undoEvent(ev) { function undoEvent(ev) {
var i; var i;
var len; var len;
@@ -114,23 +101,6 @@ RED.history = (function() {
RED.nodes.removeLink(ev.links[i]); RED.nodes.removeLink(ev.links[i]);
} }
} }
if (ev.junctions) {
inverseEv.junctions = [];
for (i=0;i<ev.junctions.length;i++) {
inverseEv.junctions.push(ev.junctions[i]);
RED.nodes.removeJunction(ev.junctions[i]);
if (ev.junctions[i].g) {
var group = RED.nodes.group(ev.junctions[i].g);
var index = group.nodes.indexOf(ev.junctions[i]);
if (index !== -1) {
group.nodes.splice(index,1);
RED.group.markDirty(group);
}
}
}
}
if (ev.groups) { if (ev.groups) {
inverseEv.groups = []; inverseEv.groups = [];
for (i = ev.groups.length - 1;i>=0;i--) { for (i = ev.groups.length - 1;i>=0;i--) {
@@ -297,21 +267,6 @@ RED.history = (function() {
} }
} }
} }
if (ev.junctions) {
inverseEv.junctions = [];
for (i=0;i<ev.junctions.length;i++) {
inverseEv.junctions.push(ev.junctions[i]);
RED.nodes.addJunction(ev.junctions[i]);
if (ev.junctions[i].g) {
group = RED.nodes.group(ev.junctions[i].g);
if (group.nodes.indexOf(ev.junctions[i]) === -1) {
group.nodes.push(ev.junctions[i]);
}
RED.group.markDirty(group)
}
}
}
if (ev.links) { if (ev.links) {
inverseEv.links = []; inverseEv.links = [];
for (i=0;i<ev.links.length;i++) { for (i=0;i<ev.links.length;i++) {
@@ -378,8 +333,7 @@ RED.history = (function() {
if (ev.addToGroup) { if (ev.addToGroup) {
RED.group.removeFromGroup(ev.addToGroup,ev.nodes.map(function(n) { return n.n }),false); RED.group.removeFromGroup(ev.addToGroup,ev.nodes.map(function(n) { return n.n }),false);
inverseEv.removeFromGroup = ev.addToGroup; inverseEv.removeFromGroup = ev.addToGroup;
} } else if (ev.removeFromGroup) {
if (ev.removeFromGroup) {
RED.group.addToGroup(ev.removeFromGroup,ev.nodes.map(function(n) { return n.n })); RED.group.addToGroup(ev.removeFromGroup,ev.nodes.map(function(n) { return n.n }));
inverseEv.addToGroup = ev.removeFromGroup; inverseEv.addToGroup = ev.removeFromGroup;
} }
@@ -422,9 +376,6 @@ RED.history = (function() {
ev.node[i] = ev.changes[i]; ev.node[i] = ev.changes[i];
} }
} }
ev.node.dirty = true;
ev.node.changed = ev.changed;
var eventType; var eventType;
switch(ev.node.type) { switch(ev.node.type) {
case 'tab': eventType = "flows"; break; case 'tab': eventType = "flows"; break;
@@ -438,9 +389,7 @@ RED.history = (function() {
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) { if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) {
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled); $("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled);
} $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!ev.node.disabled);
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('locked')) {
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-locked',!!ev.node.locked);
} }
if (ev.subflow) { if (ev.subflow) {
inverseEv.subflow = {}; inverseEv.subflow = {};
@@ -515,6 +464,8 @@ RED.history = (function() {
inverseEv.links.push(ev.createdLinks[i]); inverseEv.links.push(ev.createdLinks[i]);
} }
} }
ev.node.dirty = true;
ev.node.changed = ev.changed;
} else if (ev.t == "createSubflow") { } else if (ev.t == "createSubflow") {
inverseEv = { inverseEv = {
t: "deleteSubflow", t: "deleteSubflow",
@@ -526,7 +477,6 @@ RED.history = (function() {
var z = ev.activeWorkspace; var z = ev.activeWorkspace;
var fullNodeList = RED.nodes.filterNodes({z:ev.subflow.subflow.id}); var fullNodeList = RED.nodes.filterNodes({z:ev.subflow.subflow.id});
fullNodeList = fullNodeList.concat(RED.nodes.groups(ev.subflow.subflow.id)) fullNodeList = fullNodeList.concat(RED.nodes.groups(ev.subflow.subflow.id))
fullNodeList = fullNodeList.concat(RED.nodes.junctions(ev.subflow.subflow.id))
fullNodeList.forEach(function(n) { fullNodeList.forEach(function(n) {
n.x += ev.subflow.offsetX; n.x += ev.subflow.offsetX;
n.y += ev.subflow.offsetY; n.y += ev.subflow.offsetY;
@@ -536,7 +486,7 @@ RED.history = (function() {
}); });
inverseEv.subflows = []; inverseEv.subflows = [];
for (i=0;i<ev.nodes.length;i++) { for (i=0;i<ev.nodes.length;i++) {
inverseEv.subflows.push(nodeOrJunction(ev.nodes[i])); inverseEv.subflows.push(RED.nodes.node(ev.nodes[i]));
RED.nodes.remove(ev.nodes[i]); RED.nodes.remove(ev.nodes[i]);
} }
} }
@@ -608,22 +558,11 @@ RED.history = (function() {
} else if (ev.t == "reorder") { } else if (ev.t == "reorder") {
inverseEv = { inverseEv = {
t: 'reorder', t: 'reorder',
order: RED.nodes.getWorkspaceOrder(),
dirty: RED.nodes.dirty() dirty: RED.nodes.dirty()
}; };
if (ev.workspaces) { if (ev.order) {
inverseEv.workspaces = { RED.workspaces.order(ev.order);
from: ev.workspaces.to,
to: ev.workspaces.from
}
RED.workspaces.order(ev.workspaces.from);
}
if (ev.nodes) {
inverseEv.nodes = {
z: ev.nodes.z,
from: ev.nodes.to,
to: ev.nodes.from
}
RED.nodes.setNodeOrder(ev.nodes.z,ev.nodes.from);
} }
} else if (ev.t == "createGroup") { } else if (ev.t == "createGroup") {
inverseEv = { inverseEv = {
@@ -650,12 +589,6 @@ RED.history = (function() {
ev.groups[i].nodes = []; ev.groups[i].nodes = [];
RED.nodes.addGroup(ev.groups[i]); RED.nodes.addGroup(ev.groups[i]);
RED.group.addToGroup(ev.groups[i],nodes); RED.group.addToGroup(ev.groups[i],nodes);
if (ev.groups[i].g) {
const parentGroup = RED.nodes.group(ev.groups[i].g)
if (parentGroup) {
RED.group.addToGroup(parentGroup, ev.groups[i])
}
}
} }
} }
} else if (ev.t == "addToGroup") { } else if (ev.t == "addToGroup") {
@@ -725,8 +658,6 @@ RED.history = (function() {
push: function(ev) { push: function(ev) {
undoHistory.push(ev); undoHistory.push(ev);
redoHistory = []; redoHistory = [];
RED.menu.setDisabled("menu-item-edit-undo", false);
RED.menu.setDisabled("menu-item-edit-redo", true);
}, },
pop: function() { pop: function() {
var ev = undoHistory.pop(); var ev = undoHistory.pop();
@@ -734,24 +665,13 @@ RED.history = (function() {
if (rev) { if (rev) {
redoHistory.push(rev); redoHistory.push(rev);
} }
RED.menu.setDisabled("menu-item-edit-undo", undoHistory.length === 0);
RED.menu.setDisabled("menu-item-edit-redo", redoHistory.length === 0);
}, },
peek: function() { peek: function() {
return undoHistory[undoHistory.length-1]; return undoHistory[undoHistory.length-1];
}, },
replace: function(ev) {
if (undoHistory.length === 0) {
RED.history.push(ev);
} else {
undoHistory[undoHistory.length-1] = ev;
}
},
clear: function() { clear: function() {
undoHistory = []; undoHistory = [];
redoHistory = []; redoHistory = [];
RED.menu.setDisabled("menu-item-edit-undo", true);
RED.menu.setDisabled("menu-item-edit-redo", true);
}, },
redo: function() { redo: function() {
var ev = redoHistory.pop(); var ev = redoHistory.pop();
@@ -761,8 +681,6 @@ RED.history = (function() {
undoHistory.push(uev); undoHistory.push(uev);
} }
} }
RED.menu.setDisabled("menu-item-edit-undo", undoHistory.length === 0);
RED.menu.setDisabled("menu-item-edit-redo", redoHistory.length === 0);
} }
} }

View File

@@ -1,156 +0,0 @@
RED.hooks = (function() {
var VALID_HOOKS = [
]
var hooks = { }
var labelledHooks = { }
function add(hookId, callback) {
var parts = hookId.split(".");
var id = parts[0], label = parts[1];
// if (VALID_HOOKS.indexOf(id) === -1) {
// throw new Error("Invalid hook '"+id+"'");
// }
if (label && labelledHooks[label] && labelledHooks[label][id]) {
throw new Error("Hook "+hookId+" already registered")
}
var hookItem = {cb:callback, previousHook: null, nextHook: null }
var tailItem = hooks[id];
if (tailItem === undefined) {
hooks[id] = hookItem;
} else {
while(tailItem.nextHook !== null) {
tailItem = tailItem.nextHook
}
tailItem.nextHook = hookItem;
hookItem.previousHook = tailItem;
}
if (label) {
labelledHooks[label] = labelledHooks[label]||{};
labelledHooks[label][id] = hookItem;
}
}
function remove(hookId) {
var parts = hookId.split(".");
var id = parts[0], label = parts[1];
if ( !label) {
throw new Error("Cannot remove hook without label: "+hookId)
}
if (labelledHooks[label]) {
if (id === "*") {
// Remove all hooks for this label
var hookList = Object.keys(labelledHooks[label]);
for (var i=0;i<hookList.length;i++) {
removeHook(hookList[i],labelledHooks[label][hookList[i]])
}
delete labelledHooks[label];
} else if (labelledHooks[label][id]) {
removeHook(id,labelledHooks[label][id])
delete labelledHooks[label][id];
if (Object.keys(labelledHooks[label]).length === 0){
delete labelledHooks[label];
}
}
}
}
function removeHook(id,hookItem) {
var previousHook = hookItem.previousHook;
var nextHook = hookItem.nextHook;
if (previousHook) {
previousHook.nextHook = nextHook;
} else {
hooks[id] = nextHook;
}
if (nextHook) {
nextHook.previousHook = previousHook;
}
hookItem.removed = true;
if (!previousHook && !nextHook) {
delete hooks[id];
}
}
function trigger(hookId, payload, done) {
var hookItem = hooks[hookId];
if (!hookItem) {
if (done) {
done();
}
return;
}
function callNextHook(err) {
if (!hookItem || err) {
if (done) { done(err) }
return err;
}
if (hookItem.removed) {
hookItem = hookItem.nextHook;
return callNextHook();
}
var callback = hookItem.cb;
if (callback.length === 1) {
try {
let result = callback(payload);
if (result === false) {
// Halting the flow
if (done) { done(false) }
return result;
}
hookItem = hookItem.nextHook;
return callNextHook();
} catch(e) {
console.warn(e);
if (done) { done(e);}
return e;
}
} else {
// There is a done callback
try {
callback(payload,function(result) {
if (result === undefined) {
hookItem = hookItem.nextHook;
callNextHook();
} else {
if (done) { done(result)}
}
})
} catch(e) {
console.warn(e);
if (done) { done(e) }
return e;
}
}
}
return callNextHook();
}
function clear() {
hooks = {}
labelledHooks = {}
}
function has(hookId) {
var parts = hookId.split(".");
var id = parts[0], label = parts[1];
if (label) {
return !!(labelledHooks[label] && labelledHooks[label][id])
}
return !!hooks[id]
}
return {
has: has,
clear: clear,
add: add,
remove: remove,
trigger: trigger
}
})();

View File

@@ -18,69 +18,53 @@ RED.i18n = (function() {
var apiRootUrl; var apiRootUrl;
function detectLanguage() {
return navigator.language
}
return { return {
init: function(options, done) { init: function(options, done) {
apiRootUrl = options.apiRootUrl||""; apiRootUrl = options.apiRootUrl||"";
var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage(); var preferredLanguage = localStorage.getItem("editor-language");
var opts = { var opts = {
compatibilityJSON: 'v3', resGetPath: apiRootUrl+'locales/__ns__?lng=__lng__',
backend: { dynamicLoad: false,
loadPath: apiRootUrl+'locales/__ns__?lng=__lng__', load:'current',
ns: {
namespaces: ["editor","node-red","jsonata","infotips"],
defaultNs: "editor"
}, },
lng: 'en-US',
// debug: true,
preload:['en-US'],
ns: ["editor","node-red","jsonata","infotips"],
defaultNS: "editor",
fallbackLng: ['en-US'], fallbackLng: ['en-US'],
returnObjects: true, useCookie: false,
keySeparator: ".", returnObjectTrees: true
nsSeparator: ":",
interpolation: {
unescapeSuffix: 'HTML',
escapeValue: false,
prefix: '__',
suffix: '__'
}
}; };
if (preferredLanguage) { if (preferredLanguage) {
opts.lng = preferredLanguage; opts.lng = preferredLanguage;
} }
i18n.init(opts,function() {
i18next.use(i18nextHttpBackend).init(opts,function() {
done(); done();
}); });
jqueryI18next.init(i18next, $, { handleName: 'i18n' });
RED["_"] = function() { RED["_"] = function() {
var v = i18next.t.apply(i18next,arguments); var v = i18n.t.apply(null,arguments);
if (typeof v === 'string') { if (typeof v === 'string') {
return v; return v;
} else { } else {
return arguments[0]; return arguments[0];
} }
} }
}, },
lang: function() { lang: function() {
// Gets the active message catalog language. This is based on what // Gets the active message catalog language. This is based on what
// locale the editor is using and what languages are available. // locale the editor is using and what languages are available.
// //
var preferredLangs = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages); var preferredLangs = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var knownLangs = RED.settings.theme("languages")||["en-US"]; var knownLangs = RED.settings.theme("languages")||["en-US"];
for (var i=0;i<preferredLangs.length;i++) { for (var i=0;i<preferredLangs.length;i++) {
if (knownLangs.indexOf(preferredLangs[i]) > -1) { if (knownLangs.indexOf(preferredLangs[i]) > -1) {
return preferredLangs[i] return preferredLangs[i]
} }
} }
return 'en-US' return 'end-US'
}, },
loadNodeCatalog: function(namespace,done) { loadNodeCatalog: function(namespace,done) {
var languageList = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages); var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length; var toLoad = languageList.length;
languageList.forEach(function(lang) { languageList.forEach(function(lang) {
$.ajax({ $.ajax({
@@ -90,7 +74,7 @@ RED.i18n = (function() {
cache: false, cache: false,
url: apiRootUrl+'nodes/'+namespace+'/messages?lng='+lang, url: apiRootUrl+'nodes/'+namespace+'/messages?lng='+lang,
success: function(data) { success: function(data) {
i18next.addResourceBundle(lang,namespace,data); i18n.addResourceBundle(lang,namespace,data);
toLoad--; toLoad--;
if (toLoad === 0) { if (toLoad === 0) {
done(); done();
@@ -102,7 +86,7 @@ RED.i18n = (function() {
}, },
loadNodeCatalogs: function(done) { loadNodeCatalogs: function(done) {
var languageList = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages); var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length; var toLoad = languageList.length;
languageList.forEach(function(lang) { languageList.forEach(function(lang) {
@@ -115,7 +99,7 @@ RED.i18n = (function() {
success: function(data) { success: function(data) {
var namespaces = Object.keys(data); var namespaces = Object.keys(data);
namespaces.forEach(function(ns) { namespaces.forEach(function(ns) {
i18next.addResourceBundle(lang,ns,data[ns]); i18n.addResourceBundle(lang,ns,data[ns]);
}); });
toLoad--; toLoad--;
if (toLoad === 0) { if (toLoad === 0) {
@@ -127,7 +111,7 @@ RED.i18n = (function() {
}, },
loadPluginCatalogs: function(done) { loadPluginCatalogs: function(done) {
var languageList = [localStorage.getItem("editor-language")|| detectLanguage()].concat(i18next.languages); var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length; var toLoad = languageList.length;
languageList.forEach(function(lang) { languageList.forEach(function(lang) {
@@ -140,7 +124,7 @@ RED.i18n = (function() {
success: function(data) { success: function(data) {
var namespaces = Object.keys(data); var namespaces = Object.keys(data);
namespaces.forEach(function(ns) { namespaces.forEach(function(ns) {
i18next.addResourceBundle(lang,ns,data[ns]); i18n.addResourceBundle(lang,ns,data[ns]);
}); });
toLoad--; toLoad--;
if (toLoad === 0) { if (toLoad === 0) {
@@ -149,7 +133,6 @@ RED.i18n = (function() {
} }
}); });
}) })
}, }
detectLanguage: detectLanguage
} }
})(); })();

View File

@@ -3,12 +3,16 @@
"alt-shift-p":"core:manage-palette", "alt-shift-p":"core:manage-palette",
"ctrl-f": "core:search", "ctrl-f": "core:search",
"ctrl-shift-f": "core:list-flows", "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-d": "core:deploy-flows",
"ctrl-g c": "core:show-config-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g h": "core:show-help-tab",
"ctrl-g i": "core:show-info-tab", "ctrl-g i": "core:show-info-tab",
"ctrl-g v": "core:show-version-control-tab", "ctrl-g h": "core:show-help-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g c": "core:show-config-tab",
"ctrl-g x": "core:show-context-tab", "ctrl-g x": "core:show-context-tab",
"ctrl-e": "core:show-export-dialog", "ctrl-e": "core:show-export-dialog",
"ctrl-i": "core:show-import-dialog", "ctrl-i": "core:show-import-dialog",
@@ -19,6 +23,7 @@
"ctrl-alt-r": "core:show-remote-diff", "ctrl-alt-r": "core:show-remote-diff",
"ctrl-alt-n": "core:new-project", "ctrl-alt-n": "core:new-project",
"ctrl-alt-o": "core:open-project", "ctrl-alt-o": "core:open-project",
"ctrl-g v": "core:show-version-control-tab",
"ctrl-shift-l": "core:show-event-log", "ctrl-shift-l": "core:show-event-log",
"ctrl-shift-p":"core:show-action-list" "ctrl-shift-p":"core:show-action-list"
}, },
@@ -31,9 +36,7 @@
}, },
"red-ui-workspace": { "red-ui-workspace": {
"backspace": "core:delete-selection", "backspace": "core:delete-selection",
"ctrl-backspace": "core:delete-selection-and-reconnect",
"delete": "core:delete-selection", "delete": "core:delete-selection",
"ctrl-delete": "core:delete-selection-and-reconnect",
"enter": "core:edit-selected-node", "enter": "core:edit-selected-node",
"ctrl-enter": "core:go-to-selection", "ctrl-enter": "core:go-to-selection",
"ctrl-c": "core:copy-selection-to-internal-clipboard", "ctrl-c": "core:copy-selection-to-internal-clipboard",
@@ -74,28 +77,6 @@
"right": "core:go-to-nearest-node-on-right", "right": "core:go-to-nearest-node-on-right",
"left": "core:go-to-nearest-node-on-left", "left": "core:go-to-nearest-node-on-left",
"up": "core:go-to-nearest-node-above", "up": "core:go-to-nearest-node-above",
"down": "core:go-to-nearest-node-below", "down": "core:go-to-nearest-node-below"
"alt-a g": "core:align-selection-to-grid",
"alt-a l": "core:align-selection-to-left",
"alt-a r": "core:align-selection-to-right",
"alt-a t": "core:align-selection-to-top",
"alt-a b": "core:align-selection-to-bottom",
"alt-a m": "core:align-selection-to-middle",
"alt-a c": "core:align-selection-to-center",
"alt-a h": "core:distribute-selection-horizontally",
"alt-a v": "core:distribute-selection-vertically",
"shift-f": "core:search-previous",
"f": "core:search-next",
"alt-l l": "core:split-wire-with-link-nodes",
"alt-w": "core:hide-flow",
"alt-shift-w": "core:show-last-hidden-flow",
"ctrl-+": "core:zoom-in",
"ctrl--": "core:zoom-out",
"ctrl-0": "core:zoom-reset"
},
"red-ui-editor-stack": {
"ctrl-enter": "core:confirm-edit-tray",
"ctrl-escape": "core:cancel-edit-tray"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,7 @@ var RED = (function() {
} }
function loadPlugins(done) { function loadPlugins(done) {
loader.reportProgress(RED._("event.loadPlugins",{count:""}), 17) loader.reportProgress(RED._("event.loadPlugins",{count:""}), 17)
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage(); var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
$.ajax({ $.ajax({
headers: { headers: {
@@ -176,7 +176,7 @@ var RED = (function() {
function loadNodes() { function loadNodes() {
loader.reportProgress(RED._("event.loadNodes",{count:""}), 30) loader.reportProgress(RED._("event.loadNodes",{count:""}), 30)
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage(); var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
$.ajax({ $.ajax({
headers: { headers: {
@@ -201,7 +201,6 @@ var RED = (function() {
RED.projects.refresh(function(activeProject) { RED.projects.refresh(function(activeProject) {
loadFlows(function() { loadFlows(function() {
RED.sidebar.info.refresh() RED.sidebar.info.refresh()
var showProjectWelcome = false;
if (!activeProject) { if (!activeProject) {
// Projects enabled but no active project // Projects enabled but no active project
RED.menu.setDisabled('menu-item-projects-open',true); RED.menu.setDisabled('menu-item-projects-open',true);
@@ -209,10 +208,10 @@ var RED = (function() {
if (activeProject === false) { if (activeProject === false) {
// User previously decline the migration to projects. // User previously decline the migration to projects.
} else { // null/undefined } else { // null/undefined
showProjectWelcome = true; RED.projects.showStartup();
} }
} }
completeLoad(showProjectWelcome); completeLoad();
}); });
}); });
} else { } else {
@@ -249,51 +248,8 @@ var RED = (function() {
RED.nodes.import(nodes.flows); RED.nodes.import(nodes.flows);
RED.nodes.dirty(false); RED.nodes.dirty(false);
RED.view.redraw(true); RED.view.redraw(true);
if (/^#(flow|node|group)\/.+$/.test(currentHash)) { if (/^#flow\/.+$/.test(currentHash)) {
const hashParts = currentHash.split('/') RED.workspaces.show(currentHash.substring(6),true);
const showEditDialog = hashParts.length > 2 && hashParts[2] === 'edit'
if (hashParts[0] === '#flow') {
RED.workspaces.show(hashParts[1], true);
if (showEditDialog) {
RED.workspaces.edit()
}
} else if (hashParts[0] === '#node') {
const nodeToShow = RED.nodes.node(hashParts[1])
if (nodeToShow) {
setTimeout(() => {
RED.view.reveal(nodeToShow.id)
window.location.hash = currentHash
if (showEditDialog) {
RED.editor.edit(nodeToShow)
}
}, 50)
}
} else if (hashParts[0] === '#group') {
const nodeToShow = RED.nodes.group(hashParts[1])
if (nodeToShow) {
RED.view.reveal(nodeToShow.id)
window.location.hash = currentHash
if (showEditDialog) {
RED.editor.editGroup(nodeToShow)
}
}
}
}
if (RED.workspaces.count() > 0) {
const hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
const workspaces = RED.nodes.getWorkspaceOrder();
if (RED.workspaces.active() === 0) {
for (let index = 0; index < workspaces.length; index++) {
const ws = workspaces[index];
if (!hiddenTabs[ws]) {
RED.workspaces.show(ws);
break;
}
}
}
if (RED.workspaces.active() === 0) {
RED.workspaces.show(workspaces[0]);
}
} }
} catch(err) { } catch(err) {
console.warn(err); console.warn(err);
@@ -311,7 +267,7 @@ var RED = (function() {
}); });
} }
function completeLoad(showProjectWelcome) { function completeLoad() {
var persistentNotifications = {}; var persistentNotifications = {};
RED.comms.subscribe("notification/#",function(topic,msg) { RED.comms.subscribe("notification/#",function(topic,msg) {
var parts = topic.split("/"); var parts = topic.split("/");
@@ -324,10 +280,6 @@ var RED = (function() {
// handled below // handled below
return; return;
} }
if (notificationId === "flows-run-state") {
// handled in editor-client/src/js/runtime.js
return;
}
if (notificationId === "project-update") { if (notificationId === "project-update") {
loader.start(RED._("event.loadingProject"), 0); loader.start(RED._("event.loadingProject"), 0);
RED.nodes.clear(); RED.nodes.clear();
@@ -348,8 +300,6 @@ var RED = (function() {
loader.end() loader.end()
RED.notify($("<p>").text(message)); RED.notify($("<p>").text(message));
RED.sidebar.info.refresh() RED.sidebar.info.refresh()
RED.menu.setDisabled('menu-item-projects-open',false);
RED.menu.setDisabled('menu-item-projects-settings',false);
}); });
}); });
return; return;
@@ -365,6 +315,7 @@ var RED = (function() {
id: notificationId id: notificationId
} }
if (notificationId === "runtime-state") { if (notificationId === "runtime-state") {
RED.events.emit("runtime-state",msg);
if (msg.error === "safe-mode") { if (msg.error === "safe-mode") {
options.buttons = [ options.buttons = [
{ {
@@ -390,14 +341,6 @@ var RED = (function() {
} else { } else {
options.buttons = [ options.buttons = [
{ {
text: RED._("notification.label.unknownNodesButton"),
class: "pull-left",
click: function() {
RED.actions.invoke("core:search", "type:unknown ");
}
},
{
class: "primary",
text: RED._("common.label.close"), text: RED._("common.label.close"),
click: function() { click: function() {
persistentNotifications[notificationId].hideNotification(); persistentNotifications[notificationId].hideNotification();
@@ -505,16 +448,16 @@ var RED = (function() {
} else if (persistentNotifications.hasOwnProperty(notificationId)) { } else if (persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId].close(); persistentNotifications[notificationId].close();
delete persistentNotifications[notificationId]; delete persistentNotifications[notificationId];
} if (notificationId === 'runtime-state') {
if (notificationId === 'runtime-state') { RED.events.emit("runtime-state",msg);
RED.events.emit("runtime-state",msg); }
} }
}); });
RED.comms.subscribe("status/#",function(topic,msg) { RED.comms.subscribe("status/#",function(topic,msg) {
var parts = topic.split("/"); var parts = topic.split("/");
var node = RED.nodes.node(parts[1]); var node = RED.nodes.node(parts[1]);
if (node) { if (node) {
if (msg.hasOwnProperty("text") && msg.text !== null && /^[@a-zA-Z]/.test(msg.text)) { if (msg.hasOwnProperty("text") && msg.text !== null && /^[a-zA-Z]/.test(msg.text)) {
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()}); msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
} }
node.status = msg; node.status = msg;
@@ -528,33 +471,22 @@ var RED = (function() {
var typeList; var typeList;
var info; var info;
if (topic == "notification/node/added") { if (topic == "notification/node/added") {
RED.settings.refreshSettings(function(err, data) { var addedTypes = [];
var addedTypes = []; msg.forEach(function(m) {
msg.forEach(function(m) { var id = m.id;
var id = m.id; RED.nodes.addNodeSet(m);
RED.nodes.addNodeSet(m); addedTypes = addedTypes.concat(m.types);
addedTypes = addedTypes.concat(m.types); RED.i18n.loadNodeCatalog(id, function() {
RED.i18n.loadNodeCatalog(id, function() { $.get('nodes/'+id, function(data) {
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage(); appendNodeConfig(data);
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes/'+id,
success: function(data) {
appendNodeConfig(data);
}
});
}); });
}); });
if (addedTypes.length) { });
typeList = "<ul><li>"+addedTypes.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>"; if (addedTypes.length) {
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success"); typeList = "<ul><li>"+addedTypes.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
} RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
loadIconList(); }
}) loadIconList();
} else if (topic == "notification/node/removed") { } else if (topic == "notification/node/removed") {
for (i=0;i<msg.length;i++) { for (i=0;i<msg.length;i++) {
m = msg[i]; m = msg[i];
@@ -567,29 +499,18 @@ var RED = (function() {
loadIconList(); loadIconList();
} else if (topic == "notification/node/enabled") { } else if (topic == "notification/node/enabled") {
if (msg.types) { if (msg.types) {
RED.settings.refreshSettings(function(err, data) { info = RED.nodes.getNodeSet(msg.id);
info = RED.nodes.getNodeSet(msg.id); if (info.added) {
if (info.added) { RED.nodes.enableNodeSet(msg.id);
RED.nodes.enableNodeSet(msg.id); typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
} else {
$.get('nodes/'+msg.id, function(data) {
appendNodeConfig(data);
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>"; typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success"); RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
} else { });
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage(); }
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes/'+msg.id,
success: function(data) {
appendNodeConfig(data);
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
}
});
}
});
} }
} else if (topic == "notification/node/disabled") { } else if (topic == "notification/node/disabled") {
if (msg.types) { if (msg.types) {
@@ -609,28 +530,22 @@ var RED = (function() {
$(".red-ui-header-toolbar").show(); $(".red-ui-header-toolbar").show();
RED.sidebar.show(":first", true);
RED.sidebar.show(":first");
setTimeout(function() { setTimeout(function() {
loader.end(); loader.end();
checkFirstRun(function() {
if (showProjectWelcome) {
RED.projects.showStartup();
}
});
},100); },100);
} }
function checkFirstRun(done) { function showAbout() {
if (RED.settings.theme("tours") === false) { $.get('red/about', function(data) {
done(); var aboutHeader = '<div style="text-align:center;">'+
return; '<img width="50px" src="red/images/node-red-icon.svg" />'+
} '</div>';
if (!RED.settings.get("editor.view.view-show-welcome-tours", true)) {
done(); RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data));
return; });
}
RED.actions.invoke("core:show-welcome-tour", RED.settings.get("editor.tours.welcome"), done);
} }
function buildMainMenu() { function buildMainMenu() {
@@ -642,25 +557,6 @@ var RED = (function() {
{id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"} {id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"}
]}); ]});
} }
menuOptions.push({id:"menu-item-edit-menu", label:RED._("menu.label.edit"), options: [
{id: "menu-item-edit-undo", label:RED._("keyboard.undoChange"), disabled: true, onselect: "core:undo"},
{id: "menu-item-edit-redo", label:RED._("keyboard.redoChange"), disabled: true, onselect: "core:redo"},
null,
{id: "menu-item-edit-cut", label:RED._("keyboard.cutNode"), onselect: "core:cut-selection-to-internal-clipboard"},
{id: "menu-item-edit-copy", label:RED._("keyboard.copyNode"), onselect: "core:copy-selection-to-internal-clipboard"},
{id: "menu-item-edit-paste", label:RED._("keyboard.pasteNode"), disabled: true, onselect: "core:paste-from-internal-clipboard"},
null,
{id: "menu-item-edit-copy-group-style", label:RED._("keyboard.copyGroupStyle"), onselect: "core:copy-group-style"},
{id: "menu-item-edit-paste-group-style", label:RED._("keyboard.pasteGroupStyle"), disabled: true, onselect: "core:paste-group-style"},
null,
{id: "menu-item-edit-select-all", label:RED._("keyboard.selectAll"), onselect: "core:select-all-nodes"},
{id: "menu-item-edit-select-connected", label:RED._("keyboard.selectAllConnected"), onselect: "core:select-connected-nodes"},
{id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"},
null,
{id: "menu-item-edit-split-wire-with-links", label:RED._("keyboard.splitWireWithLinks"), onselect: "core:split-wire-with-link-nodes"},
]});
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[ 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-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true}, {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
@@ -668,25 +564,6 @@ var RED = (function() {
{id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"}, {id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"},
null null
]}); ]});
menuOptions.push({id:"menu-item-arrange-menu", label:RED._("menu.label.arrange"), options: [
{id: "menu-item-view-tools-align-left", label:RED._("menu.label.alignLeft"), disabled: true, onselect: "core:align-selection-to-left"},
{id: "menu-item-view-tools-align-center", label:RED._("menu.label.alignCenter"), disabled: true, onselect: "core:align-selection-to-center"},
{id: "menu-item-view-tools-align-right", label:RED._("menu.label.alignRight"), disabled: true, onselect: "core:align-selection-to-right"},
null,
{id: "menu-item-view-tools-align-top", label:RED._("menu.label.alignTop"), disabled: true, onselect: "core:align-selection-to-top"},
{id: "menu-item-view-tools-align-middle", label:RED._("menu.label.alignMiddle"), disabled: true, onselect: "core:align-selection-to-middle"},
{id: "menu-item-view-tools-align-bottom", label:RED._("menu.label.alignBottom"), disabled: true, onselect: "core:align-selection-to-bottom"},
null,
{id: "menu-item-view-tools-distribute-horizontally", label:RED._("menu.label.distributeHorizontally"), disabled: true, onselect: "core:distribute-selection-horizontally"},
{id: "menu-item-view-tools-distribute-veritcally", label:RED._("menu.label.distributeVertically"), disabled: true, onselect: "core:distribute-selection-vertically"},
null,
{id: "menu-item-view-tools-move-to-back", label:RED._("menu.label.moveToBack"), disabled: true, onselect: "core:move-selection-to-back"},
{id: "menu-item-view-tools-move-to-front", label:RED._("menu.label.moveToFront"), disabled: true, onselect: "core:move-selection-to-front"},
{id: "menu-item-view-tools-move-backwards", label:RED._("menu.label.moveBackwards"), disabled: true, onselect: "core:move-selection-backwards"},
{id: "menu-item-view-tools-move-forwards", label:RED._("menu.label.moveForwards"), disabled: true, onselect: "core:move-selection-forwards"}
]});
menuOptions.push(null); menuOptions.push(null);
if (RED.settings.theme("menu.menu-item-import-library", true)) { 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"}); menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"});
@@ -747,6 +624,7 @@ var RED = (function() {
RED.user.init(); RED.user.init();
RED.notifications.init(); RED.notifications.init();
RED.library.init(); RED.library.init();
RED.keyboard.init();
RED.palette.init(); RED.palette.init();
RED.eventLog.init(); RED.eventLog.init();
@@ -770,21 +648,21 @@ var RED = (function() {
RED.search.init(); RED.search.init();
RED.actionList.init(); RED.actionList.init();
RED.editor.init(); RED.editor.init();
RED.diagnostics.init();
RED.diff.init(); RED.diff.init();
RED.deploy.init(RED.settings.theme("deployButton",null)); RED.deploy.init(RED.settings.theme("deployButton",null));
RED.keyboard.init(buildMainMenu); buildMainMenu();
RED.envVar.init();
RED.nodes.init(); RED.nodes.init();
RED.runtime.init()
RED.comms.connect(); RED.comms.connect();
$("#red-ui-main-container").show(); $("#red-ui-main-container").show();
RED.actions.add("core:show-about", showAbout);
loadPluginList(); loadPluginList();
} }
@@ -796,7 +674,7 @@ var RED = (function() {
$('<div id="red-ui-header-shade" class="hide"></div>').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-main-container" class="red-ui-sidebar-closed hide">'+
'<div id="red-ui-workspace"></div>'+ '<div id="red-ui-workspace"></div>'+
'<div id="red-ui-editor-stack" tabindex="-1"></div>'+ '<div id="red-ui-editor-stack"></div>'+
'<div id="red-ui-palette"></div>'+ '<div id="red-ui-palette"></div>'+
'<div id="red-ui-sidebar"></div>'+ '<div id="red-ui-sidebar"></div>'+
'<div id="red-ui-sidebar-separator"></div>'+ '<div id="red-ui-sidebar-separator"></div>'+
@@ -833,7 +711,7 @@ var RED = (function() {
throw new Error("RED already initialised"); throw new Error("RED already initialised");
} }
initialised = true; initialised = true;
if(window.ace) { window.ace.require("ace/ext/language_tools"); } ace.require("ace/ext/language_tools");
options = options || {}; options = options || {};
options.apiRootUrl = options.apiRootUrl || ""; options.apiRootUrl = options.apiRootUrl || "";
if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) { if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) {

View File

@@ -1,36 +0,0 @@
RED.runtime = (function() {
let state = ""
let settings = { ui: false, enabled: false };
const STOPPED = "stop"
const STARTED = "start"
const SAFE = "safe"
return {
init: function() {
// refresh the current runtime status from server
settings = Object.assign({}, settings, RED.settings.runtimeState);
RED.events.on("runtime-state", function(msg) {
if (msg.state) {
const currentState = state
state = msg.state
$(".red-ui-flow-node-button").toggleClass("red-ui-flow-node-button-stopped", state !== STARTED)
if(settings.enabled === true && settings.ui === true) {
RED.menu.setVisible("deploymenu-item-runtime-stop", state === STARTED)
RED.menu.setVisible("deploymenu-item-runtime-start", state !== STARTED)
}
// Do not notify the user about this event if:
// - This is the very first event we've received after loading the editor (currentState = '')
// - The state matches what we already thought was the case (state === currentState)
// - The event was triggered by a deploy (msg.deploy === true)
// - The event is a safe mode event - that gets notified separately
if (currentState !== '' && state !== currentState && !msg.deploy && state !== SAFE) {
RED.notify(RED._("notification.state.flows"+(state === STOPPED?'Stopped':'Started'), msg), "success")
}
}
});
},
get started() {
return state === STARTED
}
}
})()

View File

@@ -19,6 +19,7 @@ RED.settings = (function () {
var loadedSettings = {}; var loadedSettings = {};
var userSettings = {}; var userSettings = {};
var settingsDirty = false;
var pendingSave; var pendingSave;
var hasLocalStorage = function () { var hasLocalStorage = function () {
@@ -125,7 +126,7 @@ RED.settings = (function () {
load(done); load(done);
} }
var refreshSettings = function(done) { var load = function(done) {
$.ajax({ $.ajax({
headers: { headers: {
"Accept": "application/json" "Accept": "application/json"
@@ -135,23 +136,6 @@ RED.settings = (function () {
url: 'settings', url: 'settings',
success: function (data) { success: function (data) {
setProperties(data); setProperties(data);
done(null, data);
},
error: function(jqXHR,textStatus,errorThrown) {
if (jqXHR.status === 401) {
if (/[?&]access_token=(.*?)(?:$|&)/.test(window.location.search)) {
window.location.search = "";
}
RED.user.login(function() { refreshSettings(done); });
} else {
console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
}
}
});
}
var load = function(done) {
refreshSettings(function(err, data) {
if (!err) {
if (!RED.settings.user || RED.settings.user.anonymous) { if (!RED.settings.user || RED.settings.user.anonymous) {
RED.settings.remove("auth-tokens"); RED.settings.remove("auth-tokens");
} }
@@ -159,13 +143,22 @@ RED.settings = (function () {
console.groupCollapsed("Versions"); console.groupCollapsed("Versions");
console.log("jQuery",$().jquery) console.log("jQuery",$().jquery)
console.log("jQuery UI",$.ui.version); console.log("jQuery UI",$.ui.version);
if(window.ace) { console.log("ACE",ace.version); } console.log("ACE",ace.version);
if(window.monaco) { console.log("MONACO",monaco.version || "unknown"); }
console.log("D3",d3.version); console.log("D3",d3.version);
console.groupEnd(); console.groupEnd();
loadUserSettings(done); loadUserSettings(done);
},
error: function(jqXHR,textStatus,errorThrown) {
if (jqXHR.status === 401) {
if (/[?&]access_token=(.*?)(?:$|&)/.test(window.location.search)) {
window.location.search = "";
}
RED.user.login(function() { load(done); });
} else {
console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
}
} }
}) });
}; };
function loadUserSettings(done) { function loadUserSettings(done) {
@@ -226,28 +219,14 @@ RED.settings = (function () {
return defaultValue; return defaultValue;
} }
} }
function getLocal(key) {
return localStorage.getItem(key)
}
function setLocal(key, value) {
localStorage.setItem(key, value);
}
function removeLocal(key) {
localStorage.removeItem(key)
}
return { return {
init: init, init: init,
load: load, load: load,
loadUserSettings: loadUserSettings, loadUserSettings: loadUserSettings,
refreshSettings: refreshSettings,
set: set, set: set,
get: get, get: get,
remove: remove, remove: remove,
theme: theme, theme: theme
setLocal: setLocal,
getLocal: getLocal,
removeLocal: removeLocal
} }
})(); })();

View File

@@ -160,19 +160,18 @@ RED.actionList = (function() {
createDialog(); createDialog();
} }
dialog.slideDown(300); dialog.slideDown(300);
searchInput.searchBox('value',v); searchInput.searchBox('value',v)
searchResults.editableList('empty'); searchResults.editableList('empty');
results = []; results = [];
var actions = RED.actions.list(); var actions = RED.actions.list();
actions.sort(function(A,B) { actions.sort(function(A,B) {
var Akey = A.label; return A.id.localeCompare(B.id);
var Bkey = B.label;
return Akey.localeCompare(Bkey);
}); });
actions.forEach(function(action) { actions.forEach(function(action) {
action.label = action.id.replace(/:/,": ").replace(/-/g," ").replace(/(^| )./g,function() { return arguments[0].toUpperCase()});
action._label = action.label.toLowerCase(); action._label = action.label.toLowerCase();
searchResults.editableList('addItem',action); searchResults.editableList('addItem',action)
}); })
RED.events.emit("actionList:open"); RED.events.emit("actionList:open");
visible = true; visible = true;
} }

View File

@@ -1,67 +1,25 @@
RED.actions = (function() { RED.actions = (function() {
var actions = { var actions = {
}; }
function addAction(name,handler,options) { function addAction(name,handler) {
if (typeof handler !== 'function') { actions[name] = handler;
throw new Error("Action handler not a function");
}
if (actions[name]) {
throw new Error("Cannot override existing action");
}
actions[name] = {
handler: handler,
options: options,
};
} }
function removeAction(name) { function removeAction(name) {
delete actions[name]; delete actions[name];
} }
function getAction(name) { function getAction(name) {
return actions[name].handler; return actions[name];
} }
function getActionLabel(name) { function invokeAction(name,args) {
let def = actions[name]
if (!def) {
return ''
}
if (!def.label) {
var options = def.options;
var key = options ? options.label : undefined;
if (!key) {
key = "action-list." +name.replace(/^.*:/,"");
}
var label = RED._(key);
if (label === key) {
// no translation. convert `name` to description
label = name.replace(/(^.+:([a-z]))|(-([a-z]))/g, function() {
if (arguments[5] === 0) {
return arguments[2].toUpperCase();
} else {
return " "+arguments[4].toUpperCase();
}
});
}
def.label = label;
}
return def.label
}
function invokeAction() {
var args = Array.prototype.slice.call(arguments);
var name = args.shift();
if (actions.hasOwnProperty(name)) { if (actions.hasOwnProperty(name)) {
var handler = actions[name].handler; actions[name](args);
handler.apply(null, args);
} }
} }
function listActions() { function listActions() {
var result = []; var result = [];
Object.keys(actions).forEach(function(action) { Object.keys(actions).forEach(function(action) {
var def = actions[action];
var shortcut = RED.keyboard.getShortcut(action); var shortcut = RED.keyboard.getShortcut(action);
var isUser = false; var isUser = false;
if (shortcut) { if (shortcut) {
@@ -69,25 +27,19 @@ RED.actions = (function() {
} else { } else {
isUser = !!RED.keyboard.getUserShortcut(action); isUser = !!RED.keyboard.getUserShortcut(action);
} }
if (!def.label) {
def.label = getActionLabel(action)
}
result.push({ result.push({
id:action, id:action,
scope:shortcut?shortcut.scope:undefined, scope:shortcut?shortcut.scope:undefined,
key:shortcut?shortcut.key:undefined, key:shortcut?shortcut.key:undefined,
user:isUser, user:isUser
label: def.label, })
options: def.options, })
});
});
return result; return result;
} }
return { return {
add: addAction, add: addAction,
remove: removeAction, remove: removeAction,
get: getAction, get: getAction,
getLabel: getActionLabel,
invoke: invokeAction, invoke: invokeAction,
list: listActions list: listActions
} }

View File

@@ -71,7 +71,6 @@ RED.clipboard = (function() {
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
$( this ).dialog( "close" ); $( this ).dialog( "close" );
RED.view.focus();
} }
}, },
{ // red-ui-clipboard-dialog-download { // red-ui-clipboard-dialog-download
@@ -82,7 +81,6 @@ RED.clipboard = (function() {
var data = $("#red-ui-clipboard-dialog-export-text").val(); var data = $("#red-ui-clipboard-dialog-export-text").val();
downloadData("flows.json", data); downloadData("flows.json", data);
$( this ).dialog( "close" ); $( this ).dialog( "close" );
RED.view.focus();
} }
}, },
{ // red-ui-clipboard-dialog-export { // red-ui-clipboard-dialog-export
@@ -97,7 +95,6 @@ RED.clipboard = (function() {
$( this ).dialog( "close" ); $( this ).dialog( "close" );
copyText(flowData); copyText(flowData);
RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"}); RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"});
RED.view.focus();
} else { } else {
var flowToExport = $("#red-ui-clipboard-dialog-export-text").val(); var flowToExport = $("#red-ui-clipboard-dialog-export-text").val();
var selectedPath = activeLibraries[activeTab].getSelected(); var selectedPath = activeLibraries[activeTab].getSelected();
@@ -113,7 +110,6 @@ RED.clipboard = (function() {
contentType: "application/json; charset=utf-8" contentType: "application/json; charset=utf-8"
}).done(function() { }).done(function() {
$(dialog).dialog( "close" ); $(dialog).dialog( "close" );
RED.view.focus();
RED.notify(RED._("library.exportedToLibrary"),"success"); RED.notify(RED._("library.exportedToLibrary"),"success");
}).fail(function(xhr,textStatus,err) { }).fail(function(xhr,textStatus,err) {
if (xhr.status === 401) { if (xhr.status === 401) {
@@ -175,7 +171,6 @@ RED.clipboard = (function() {
} }
} }
$( this ).dialog( "close" ); $( this ).dialog( "close" );
RED.view.focus();
} }
}, },
{ // red-ui-clipboard-dialog-import-conflict { // red-ui-clipboard-dialog-import-conflict
@@ -208,7 +203,6 @@ RED.clipboard = (function() {
// console.table(pendingImportConfig.importNodes.map(function(n) { return {id:n.id,type:n.type,result:importMap[n.id]}})) // console.table(pendingImportConfig.importNodes.map(function(n) { return {id:n.id,type:n.type,result:importMap[n.id]}}))
RED.view.importNodes(newNodes, pendingImportConfig.importOptions); RED.view.importNodes(newNodes, pendingImportConfig.importOptions);
$( this ).dialog( "close" ); $( this ).dialog( "close" );
RED.view.focus();
} }
} }
], ],
@@ -423,10 +417,11 @@ RED.clipboard = (function() {
} }
} }
function showImportNodes(library = 'clipboard') { function showImportNodes(mode) {
if (disabled) { if (disabled) {
return; return;
} }
mode = mode || "clipboard";
dialogContainer.empty(); dialogContainer.empty();
dialogContainer.append($(importNodesDialog)); dialogContainer.append($(importNodesDialog));
@@ -503,13 +498,6 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport); $("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport);
$("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)}); $("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)});
if (RED.workspaces.active() === 0 || RED.workspaces.isLocked()) {
$("#red-ui-clipboard-dialog-import-opt-current").addClass('disabled').removeClass("selected");
$("#red-ui-clipboard-dialog-import-opt-new").addClass("selected");
} else {
$("#red-ui-clipboard-dialog-import-opt-current").removeClass('disabled').addClass("selected");
$("#red-ui-clipboard-dialog-import-opt-new").removeClass("selected");
}
$("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) { $("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) { if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
@@ -532,8 +520,8 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click"); $("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
}) })
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+library); tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
if (library === 'clipboard') { if (mode === 'clipboard') {
setTimeout(function() { setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus"); $("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100) },100)
@@ -557,16 +545,13 @@ RED.clipboard = (function() {
}); });
} }
/** function showExportNodes(mode) {
* Show the export dialog
* @params library which export destination to show
* @params mode whether to default to 'auto' (default) or 'flow'
**/
function showExportNodes(library = 'clipboard', mode = 'auto' ) {
if (disabled) { if (disabled) {
return; return;
} }
mode = mode || "clipboard";
dialogContainer.empty(); dialogContainer.empty();
dialogContainer.append($(exportNodesDialog)); dialogContainer.append($(exportNodesDialog));
@@ -626,6 +611,9 @@ RED.clipboard = (function() {
activeLibraries[tabId] = browser; activeLibraries[tabId] = browser;
}) })
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename); $("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)}); $("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable"); $("#red-ui-clipboard-dialog-export").button("enable");
@@ -648,6 +636,7 @@ RED.clipboard = (function() {
label: RED._("editor.types.json") label: RED._("editor.types.json")
}); });
var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({ var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({
data: [] data: []
}) })
@@ -656,12 +645,7 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select(); $("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select();
dialogContainer.i18n(); dialogContainer.i18n();
var format = RED.settings.flowFilePretty ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini"; var format = RED.settings.flowFilePretty ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini";
const userFormat = RED.settings.get("editor.dialog.export.pretty")
if (userFormat === false || userFormat === true) {
format = userFormat ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini";
}
$("#red-ui-clipboard-dialog-export-fmt-group > a").on("click", function(evt) { $("#red-ui-clipboard-dialog-export-fmt-group > a").on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
@@ -677,8 +661,7 @@ RED.clipboard = (function() {
var nodes = JSON.parse(flow); var nodes = JSON.parse(flow);
format = $(this).attr('id'); format = $(this).attr('id');
const pretty = format === "red-ui-clipboard-dialog-export-fmt-full"; if (format === 'red-ui-clipboard-dialog-export-fmt-full') {
if (pretty) {
flow = JSON.stringify(nodes,null,4); flow = JSON.stringify(nodes,null,4);
} else { } else {
flow = JSON.stringify(nodes); flow = JSON.stringify(nodes);
@@ -687,7 +670,6 @@ RED.clipboard = (function() {
setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50); setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50);
$("#red-ui-clipboard-dialog-export-text").trigger("focus"); $("#red-ui-clipboard-dialog-export-text").trigger("focus");
RED.settings.set("editor.dialog.export.pretty", pretty)
} }
}); });
@@ -718,15 +700,7 @@ RED.clipboard = (function() {
} else if (type === 'flow') { } else if (type === 'flow') {
var activeWorkspace = RED.workspaces.active(); var activeWorkspace = RED.workspaces.active();
nodes = RED.nodes.groups(activeWorkspace); nodes = RED.nodes.groups(activeWorkspace);
nodes = nodes.concat(RED.nodes.junctions(activeWorkspace));
nodes = nodes.concat(RED.nodes.filterNodes({z:activeWorkspace})); nodes = nodes.concat(RED.nodes.filterNodes({z:activeWorkspace}));
RED.nodes.eachConfig(function(n) {
if (n.z === RED.workspaces.active() && n._def.hasUsers === false) {
// Grab any config nodes scoped to this flow that don't
// require any flow-nodes to use them
nodes.push(n);
}
});
var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace); var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
nodes.unshift(parentNode); nodes.unshift(parentNode);
nodes = RED.nodes.createExportableNodeSet(nodes); nodes = RED.nodes.createExportableNodeSet(nodes);
@@ -757,33 +731,24 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-export").hide(); $("#red-ui-clipboard-dialog-export").hide();
$("#red-ui-clipboard-dialog-import-conflict").hide(); $("#red-ui-clipboard-dialog-import-conflict").hide();
if (RED.workspaces.active() === 0) { var selection = RED.workspaces.selection();
$("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected'); if (selection.length > 0) {
$("#red-ui-clipboard-dialog-export-rng-flow").addClass('disabled').removeClass('selected'); $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
$("#red-ui-clipboard-dialog-export-rng-full").trigger("click");
} else { } else {
var selection = RED.workspaces.selection(); selection = RED.view.selection();
if (selection.length > 0) { if (selection.nodes) {
$("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
} else { } else {
selection = RED.view.selection(); $("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected');
if (selection.nodes) { $("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
$("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
} else {
$("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
}
} }
} }
if (mode === 'flow' && !$("#red-ui-clipboard-dialog-export-rng-flow").hasClass('disabled')) {
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
}
if (format === "red-ui-clipboard-dialog-export-fmt-full") { if (format === "red-ui-clipboard-dialog-export-fmt-full") {
$("#red-ui-clipboard-dialog-export-fmt-full").trigger("click"); $("#red-ui-clipboard-dialog-export-fmt-full").trigger("click");
} else { } else {
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click"); $("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click");
} }
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+library); tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
var dialogHeight = 400; var dialogHeight = 400;
var winHeight = $(window).height(); var winHeight = $(window).height();
@@ -959,8 +924,7 @@ RED.clipboard = (function() {
if (truncated) { if (truncated) {
msg += "_truncated"; msg += "_truncated";
} }
var clipboardHidden = $('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo(document.body); $("#red-ui-clipboard-hidden").val(value).focus().select();
clipboardHidden.val(value).focus().select();
var result = document.execCommand("copy"); var result = document.execCommand("copy");
if (result && element) { if (result && element) {
var popover = RED.popover.create({ var popover = RED.popover.create({
@@ -974,13 +938,14 @@ RED.clipboard = (function() {
},1000); },1000);
popover.open(); popover.open();
} }
clipboardHidden.remove(); $("#red-ui-clipboard-hidden").val("");
if (currentFocus) { if (currentFocus) {
$(currentFocus).focus(); $(currentFocus).focus();
} }
return result; return result;
} }
function importNodes(nodesStr,addFlow) { function importNodes(nodesStr,addFlow) {
var newNodes = nodesStr; var newNodes = nodesStr;
if (typeof nodesStr === 'string') { if (typeof nodesStr === 'string') {
@@ -1000,7 +965,6 @@ RED.clipboard = (function() {
try { try {
RED.view.importNodes(newNodes, importOptions); RED.view.importNodes(newNodes, importOptions);
} catch(error) { } catch(error) {
console.log(error.importConfig)
// Thrown for import_conflict // Thrown for import_conflict
confirmImport(error.importConfig, newNodes, importOptions); confirmImport(error.importConfig, newNodes, importOptions);
} }
@@ -1256,6 +1220,8 @@ RED.clipboard = (function() {
init: function() { init: function() {
setupDialogs(); setupDialogs();
$('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
RED.actions.add("core:show-export-dialog",showExportNodes); RED.actions.add("core:show-export-dialog",showExportNodes);
RED.actions.add("core:show-import-dialog",showImportNodes); RED.actions.add("core:show-import-dialog",showImportNodes);
@@ -1278,17 +1244,15 @@ RED.clipboard = (function() {
RED.keyboard.add("#red-ui-drop-target", "escape" ,hideDropTarget); RED.keyboard.add("#red-ui-drop-target", "escape" ,hideDropTarget);
$('#red-ui-workspace-chart').on("dragenter",function(event) { $('#red-ui-workspace-chart').on("dragenter",function(event) {
if (!RED.workspaces.isLocked() && ( if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
$.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 || $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1)) {
$("#red-ui-drop-target").css({display:'table'}).focus(); $("#red-ui-drop-target").css({display:'table'}).focus();
} }
}); });
$('#red-ui-drop-target').on("dragover",function(event) { $('#red-ui-drop-target').on("dragover",function(event) {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 || if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1 || $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
RED.workspaces.isLocked()) {
event.preventDefault(); event.preventDefault();
} }
}) })
@@ -1296,29 +1260,27 @@ RED.clipboard = (function() {
hideDropTarget(); hideDropTarget();
}) })
.on("drop",function(event) { .on("drop",function(event) {
if (!RED.workspaces.isLocked()) { try {
try { if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { var data = event.originalEvent.dataTransfer.getData("text/plain");
var data = event.originalEvent.dataTransfer.getData("text/plain"); data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1); importNodes(data);
importNodes(data); } else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) { var files = event.originalEvent.dataTransfer.files;
var files = event.originalEvent.dataTransfer.files; if (files.length === 1) {
if (files.length === 1) { var file = files[0];
var file = files[0]; var reader = new FileReader();
var reader = new FileReader(); reader.onload = (function(theFile) {
reader.onload = (function(theFile) { return function(e) {
return function(e) { importNodes(e.target.result);
importNodes(e.target.result); };
}; })(file);
})(file); reader.readAsText(file);
reader.readAsText(file);
}
} }
} catch(err) {
// Ensure any errors throw above doesn't stop the drop target from
// being hidden.
} }
} catch(err) {
// Ensure any errors throw above doesn't stop the drop target from
// being hidden.
} }
hideDropTarget(); hideDropTarget();
event.preventDefault(); event.preventDefault();

View File

@@ -1,126 +0,0 @@
(function($) {
/**
* Attach to an <input type="text"> to provide auto-complete
*
* $("#node-red-text").autoComplete({
* search: function(value) { return ['a','b','c'] }
* })
*
* options:
*
* search: function(value, [done])
* A function that is passed the current contents of the input whenever
* it changes.
* The function must either return auto-complete options, or pass them
* to the optional 'done' parameter.
* If the function signature includes 'done', it must be used
* minLength: number
* If `minLength` is 0, pressing down arrow will show the list
*
* The auto-complete options should be an array of objects in the form:
* {
* value: String : the value to insert if selected
* label: String|DOM Element : the label to display in the dropdown.
* }
*
*/
$.widget( "nodered.autoComplete", {
_create: function() {
const that = this;
this.completionMenuShown = false;
this.options.minLength = parseInteger(this.options.minLength, 1, 0);
this.options.search = this.options.search || function() { return [] };
this.element.addClass("red-ui-autoComplete");
this.element.on("keydown.red-ui-autoComplete", function(evt) {
if ((evt.keyCode === 13 || evt.keyCode === 9) && that.completionMenuShown) {
var opts = that.menu.options();
that.element.val(opts[0].value);
that.menu.hide();
evt.preventDefault();
}
})
this.element.on("keyup.red-ui-autoComplete", function(evt) {
if (evt.keyCode === 13 || evt.keyCode === 9 || evt.keyCode === 27) {
// ENTER / TAB / ESCAPE
return
}
if (evt.keyCode === 8 || evt.keyCode === 46) {
// Delete/Backspace
if (!that.completionMenuShown) {
return;
}
}
that._updateCompletions(this.value);
});
},
_showCompletionMenu: function(completions) {
if (this.completionMenuShown) {
return;
}
this.menu = RED.popover.menu({
tabSelect: true,
width: 300,
maxHeight: 200,
class: "red-ui-autoComplete-container",
options: completions,
onselect: (opt) => { this.element.val(opt.value); this.element.focus(); this.element.trigger("change") },
onclose: () => { this.completionMenuShown = false; delete this.menu; this.element.focus()}
});
this.menu.show({
target: this.element
})
this.completionMenuShown = true;
},
_updateCompletions: function(val) {
const that = this;
if (val.trim().length < this.options.minLength) {
if (this.completionMenuShown) {
this.menu.hide();
}
return;
}
function displayResults(completions,requestId) {
if (requestId && requestId !== that.pendingRequest) {
// This request has been superseded
return
}
if (!completions || completions.length === 0) {
if (that.completionMenuShown) {
that.menu.hide();
}
return
}
if (that.completionMenuShown) {
that.menu.options(completions);
} else {
that._showCompletionMenu(completions);
}
}
if (this.options.search.length === 2) {
const requestId = 1+Math.floor(Math.random()*10000);
this.pendingRequest = requestId;
this.options.search(val,function(completions) { displayResults(completions,requestId);})
} else {
displayResults(this.options.search(val))
}
},
_destroy: function() {
this.element.removeClass("red-ui-autoComplete")
this.element.off("keydown.red-ui-autoComplete")
this.element.off("keyup.red-ui-autoComplete")
if (this.completionMenuShown) {
this.menu.hide();
}
}
});
function parseInteger(input, def, min, max) {
if(input == null) { return (def || 0); }
min = min == null ? Number.NEGATIVE_INFINITY : min;
max = max == null ? Number.POSITIVE_INFINITY : max;
let n = parseInt(input);
if(isNaN(n) || n < min || n > max) { n = def || 0; }
return n;
}
})(jQuery);

View File

@@ -1,4 +1,4 @@
RED.editor.colorPicker = RED.colorPicker = (function() { RED.colorPicker = (function() {
function create(options) { function create(options) {
var color = options.value; var color = options.value;
@@ -76,9 +76,6 @@ RED.editor.colorPicker = RED.colorPicker = (function() {
var focusTarget = colorInput; var focusTarget = colorInput;
colorInput.on("change", function (e) { colorInput.on("change", function (e) {
var color = colorInput.val(); var color = colorInput.val();
if (options.defaultValue && !color.match(/^([a-z]+|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3})$/)) {
color = options.defaultValue;
}
colorHiddenInput.val(color).trigger('change'); colorHiddenInput.val(color).trigger('change');
refreshDisplay(color); refreshDisplay(color);
}); });

View File

@@ -18,7 +18,7 @@
/** /**
* options: * options:
* - addButton : boolean|string - text for add label, default 'add' * - addButton : boolean|string - text for add label, default 'add'
* - buttons : array - list of custom buttons (objects with fields 'id', 'label', 'icon', 'title', 'click') * - buttons : array - list of custom buttons (objects with fields 'label', 'icon', 'title', 'click')
* - height : number|'auto' * - height : number|'auto'
* - resize : function - called when list as a whole is resized * - resize : function - called when list as a whole is resized
* - resizeItem : function(item) - called to resize individual item * - resizeItem : function(item) - called to resize individual item
@@ -94,7 +94,7 @@
} }
buttons.forEach(function(button) { buttons.forEach(function(button) {
var element = $('<button type="button" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px; margin-right: 5px;"></button>') var element = $('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px; margin-right: 5px;"></a>')
.appendTo(that.topContainer) .appendTo(that.topContainer)
.on("click", function(evt) { .on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
@@ -103,9 +103,6 @@
} }
}); });
if (button.id) {
element.attr("id", button.id);
}
if (button.title) { if (button.title) {
element.attr("title", button.title); element.attr("title", button.title);
} }
@@ -160,7 +157,7 @@
this.element.css("maxHeight",null); this.element.css("maxHeight",null);
} }
if (this.options.height !== 'auto') { if (this.options.height !== 'auto') {
this.uiContainer.css("overflow-y","auto"); this.uiContainer.css("overflow-y","scroll");
if (!isNaN(this.options.height)) { if (!isNaN(this.options.height)) {
this.uiHeight = this.options.height; this.uiHeight = this.options.height;
} }
@@ -417,9 +414,6 @@
} else { } else {
return null; return null;
} }
},
cancel: function() {
this.element.sortable("cancel");
} }
}); });
})(jQuery); })(jQuery);

View File

@@ -16,7 +16,6 @@
RED.menu = (function() { RED.menu = (function() {
var menuItems = {}; var menuItems = {};
let menuItemCount = 0
function createMenuItem(opt) { function createMenuItem(opt) {
var item; var item;
@@ -60,16 +59,15 @@ RED.menu = (function() {
item = $('<li class="red-ui-menu-divider"></li>'); item = $('<li class="red-ui-menu-divider"></li>');
} else { } else {
item = $('<li></li>'); item = $('<li></li>');
if (!opt.id) {
opt.id = 'red-ui-menu-item-'+(menuItemCount++)
}
if (opt.group) { if (opt.group) {
item.addClass("red-ui-menu-group-"+opt.group); item.addClass("red-ui-menu-group-"+opt.group);
} }
var linkContent = '<a '+(opt.id?'id="'+opt.id+'" ':'')+'tabindex="-1" href="#">'; var linkContent = '<a '+(opt.id?'id="'+opt.id+'" ':'')+'tabindex="-1" href="#">';
if (opt.toggle) { if (opt.toggle) {
linkContent += '<i class="fa fa-square'+(opt.direction!=='right'?" pull-left":"")+'"></i>'; linkContent += '<i class="fa fa-square pull-left"></i>';
linkContent += '<i class="fa fa-check-square'+(opt.direction!=='right'?" pull-left":"")+'"></i>'; linkContent += '<i class="fa fa-check-square pull-left"></i>';
} }
if (opt.icon !== undefined) { if (opt.icon !== undefined) {
@@ -79,27 +77,17 @@ RED.menu = (function() {
linkContent += '<i class="'+(opt.icon?opt.icon:'" style="display: inline-block;"')+'"></i> '; linkContent += '<i class="'+(opt.icon?opt.icon:'" style="display: inline-block;"')+'"></i> ';
} }
} }
let label = opt.label
if (!opt.label && typeof opt.onselect === 'string') {
label = RED.actions.getLabel(opt.onselect)
}
if (opt.sublabel) { if (opt.sublabel) {
linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+label+'</span>'+ 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>' '<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>'
} else { } else {
linkContent += '<span class="red-ui-menu-label"><span>'+label+'</span></span>' linkContent += '<span class="red-ui-menu-label">'+opt.label+'</span>'
} }
linkContent += '</a>'; linkContent += '</a>';
var link = $(linkContent).appendTo(item); var link = $(linkContent).appendTo(item);
opt.link = link;
if (typeof opt.onselect === 'string' || opt.shortcut) {
var shortcut = opt.shortcut || RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label"));
}
}
menuItems[opt.id] = opt; menuItems[opt.id] = opt;
@@ -131,45 +119,19 @@ RED.menu = (function() {
}); });
} }
if (opt.options) { if (opt.options) {
item.addClass("red-ui-menu-dropdown-submenu"+(opt.direction!=='right'?" pull-left":"")); item.addClass("red-ui-menu-dropdown-submenu pull-left");
var submenu = $('<ul id="'+opt.id+'-submenu" class="red-ui-menu-dropdown"></ul>').appendTo(item); var submenu = $('<ul id="'+opt.id+'-submenu" class="red-ui-menu-dropdown"></ul>').appendTo(item);
var hasIcons = false
var hasSubmenus = false
for (var i=0;i<opt.options.length;i++) { for (var i=0;i<opt.options.length;i++) {
if (opt.options[i]) {
if (opt.onpreselect && opt.options[i].onpreselect === undefined) {
opt.options[i].onpreselect = opt.onpreselect
}
if (opt.onpostselect && opt.options[i].onpostselect === undefined) {
opt.options[i].onpostselect = opt.onpostselect
}
opt.options[i].direction = opt.direction
hasIcons = hasIcons || (opt.options[i].icon);
hasSubmenus = hasSubmenus || (opt.options[i].options);
}
var li = createMenuItem(opt.options[i]); var li = createMenuItem(opt.options[i]);
if (li) { if (li) {
li.appendTo(submenu); li.appendTo(submenu);
} }
} }
if (!hasIcons) {
submenu.addClass("red-ui-menu-dropdown-noicons")
}
if (hasSubmenus) {
submenu.addClass("red-ui-menu-dropdown-submenus")
}
} }
if (opt.disabled) { if (opt.disabled) {
item.addClass("disabled"); item.addClass("disabled");
} }
if (opt.visible === false) {
item.addClass("hide");
}
} }
@@ -178,9 +140,7 @@ RED.menu = (function() {
} }
function createMenu(options) { function createMenu(options) {
var topMenu = $("<ul/>",{class:"red-ui-menu red-ui-menu-dropdown pull-right"}); var topMenu = $("<ul/>",{class:"red-ui-menu red-ui-menu-dropdown pull-right"});
if (options.direction) {
topMenu.addClass("red-ui-menu-dropdown-direction-"+options.direction)
}
if (options.id) { if (options.id) {
topMenu.attr({id:options.id+"-submenu"}); topMenu.attr({id:options.id+"-submenu"});
var menuParent = $("#"+options.id); var menuParent = $("#"+options.id);
@@ -206,22 +166,9 @@ RED.menu = (function() {
} }
var lastAddedSeparator = false; var lastAddedSeparator = false;
var hasSubmenus = false;
var hasIcons = false;
for (var i=0;i<options.options.length;i++) { for (var i=0;i<options.options.length;i++) {
var opt = options.options[i]; var opt = options.options[i];
if (opt) {
if (options.onpreselect && opt.onpreselect === undefined) {
opt.onpreselect = options.onpreselect
}
if (options.onpostselect && opt.onpostselect === undefined) {
opt.onpostselect = options.onpostselect
}
opt.direction = options.direction || 'left'
}
if (opt !== null || !lastAddedSeparator) { if (opt !== null || !lastAddedSeparator) {
hasIcons = hasIcons || (opt && opt.icon);
hasSubmenus = hasSubmenus || (opt && opt.options);
var li = createMenuItem(opt); var li = createMenuItem(opt);
if (li) { if (li) {
li.appendTo(topMenu); li.appendTo(topMenu);
@@ -229,21 +176,13 @@ RED.menu = (function() {
} }
} }
} }
if (!hasIcons) {
topMenu.addClass("red-ui-menu-dropdown-noicons")
}
if (hasSubmenus) {
topMenu.addClass("red-ui-menu-dropdown-submenus")
}
return topMenu; return topMenu;
} }
function triggerAction(id, args) { function triggerAction(id, args) {
var opt = menuItems[id]; var opt = menuItems[id];
var callback = opt.onselect; var callback = opt.onselect;
if (opt.onpreselect) {
opt.onpreselect.call(opt,args)
}
if (typeof opt.onselect === 'string') { if (typeof opt.onselect === 'string') {
callback = RED.actions.get(opt.onselect); callback = RED.actions.get(opt.onselect);
} }
@@ -252,9 +191,6 @@ RED.menu = (function() {
} else { } else {
console.log("No callback for",id,opt.onselect); console.log("No callback for",id,opt.onselect);
} }
if (opt.onpostselect) {
opt.onpostselect.call(opt,args)
}
} }
function isSelected(id) { function isSelected(id) {
@@ -306,14 +242,6 @@ RED.menu = (function() {
} }
} }
function setVisible(id,state) {
if (!state) {
$("#"+id).parent().addClass("hide");
} else {
$("#"+id).parent().removeClass("hide");
}
}
function addItem(id,opt) { function addItem(id,opt) {
var item = createMenuItem(opt); var item = createMenuItem(opt);
if (opt !== null && opt.group) { if (opt !== null && opt.group) {
@@ -348,32 +276,14 @@ RED.menu = (function() {
} }
} }
function refreshShortcuts() {
for (var id in menuItems) {
if (menuItems.hasOwnProperty(id)) {
var opt = menuItems[id];
if (typeof opt.onselect === "string" && opt.shortcutSpan) {
opt.shortcutSpan.remove();
delete opt.shortcutSpan;
var shortcut = RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(opt.link.find(".red-ui-menu-label"));
}
}
}
}
}
return { return {
init: createMenu, init: createMenu,
setSelected: setSelected, setSelected: setSelected,
isSelected: isSelected, isSelected: isSelected,
toggleSelected: toggleSelected, toggleSelected: toggleSelected,
setDisabled: setDisabled, setDisabled: setDisabled,
setVisible: setVisible,
addItem: addItem, addItem: addItem,
removeItem: removeItem, removeItem: removeItem,
setAction: setAction, setAction: setAction
refreshShortcuts: refreshShortcuts
} }
})(); })();

View File

@@ -13,138 +13,24 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ **/
/*
* RED.popover.create(options) - create a popover callout box
* RED.popover.tooltip(target,content, action) - add a tooltip to an element
* RED.popover.menu(options) - create a dropdown menu
* RED.popover.panel(content) - create a dropdown container element
*/
/*
* RED.popover.create(options)
*
* options
* - target : DOM element - the element to target with the popover
* - direction : string - position of the popover relative to target
* 'top', 'right'(default), 'bottom', 'left', 'inset-[top,right,bottom,left]'
* - trigger : string - what triggers the popover to be displayed
* 'hover' - display when hovering the target
* 'click' - display when target is clicked
* 'modal' - hmm not sure, need to find where we use that mode
* - content : string|function - contents of the popover. If a string, handled
* as raw HTML, so take care.
* If a function, can return a String to be added
* as text (not HTML), or a DOM element to append
* - delay : object - sets show/hide delays after mouseover/out events
* { show: 750, hide: 50 }
* - autoClose : number - delay before closing the popover in some cases
* if trigger is click - delay after mouseout
* else if trigger not hover/modal - delay after showing
* - width : number - width of popover, default 'auto'
* - maxWidth : number - max width of popover, default 'auto'
* - size : string - scale of popover. 'default', 'small'
* - offset : number - px offset from target
* - tooltip : boolean - if true, clicking on popover closes it
* - class : string - optional css class to apply to popover
* - interactive : if trigger is 'hover' and this is set to true, allow the mouse
* to move over the popover without hiding it.
*
* Returns the popover object with the following properties/functions:
* properties:
* - element : DOM element - the popover dom element
* functions:
* - setContent(content) - change the popover content. This only works if the
* popover is not currently displayed. It does not
* change the content of a visible popover.
* - open(instant) - show the popover. If 'instant' is true, don't fade in
* - close(instant) - hide the popover. If 'instant' is true, don't fade out
* - move(options) - move the popover. The options parameter can take many
* of the options detailed above including:
* target,direction,content,width,offset
* Other settings probably won't work because we haven't needed to change them
*/
/*
* RED.popover.tooltip(target,content, action)
*
* - target : DOM element - the element to apply the tooltip to
* - content : string - the text of the tooltip
* - action : string - *optional* the name of an Action this tooltip is tied to
* For example, it 'target' is a button that triggers a particular action.
* The tooltip will include the keyboard shortcut for the action
* if one is defined
*
*/
/*
* RED.popover.menu(options)
*
* options
* - options : array - list of menu options - see below for format
* - width : number - width of the menu. Default: 'auto'
* - class : string - class to apply to the menu container
* - maxHeight : number - maximum height of menu before scrolling items. Default: none
* - onselect : function(item) - called when a menu item is selected, if that item doesn't
* have its own onselect function
* - onclose : function(cancelled) - called when the menu is closed
* - disposeOnClose : boolean - by default, the menu is discarded when it closes
* and mustbe rebuilt to redisplay. Setting this to 'false'
* keeps the menu on the DOM so it can be shown again.
*
* Menu Options array:
* [
* label : string|DOM element - the label of the item. Can be custom DOM element
* onselect : function - called when the item is selected
* ]
*
* Returns the menu object with the following functions:
*
* - options([menuItems]) - if menuItems is undefined, returns the current items.
* otherwise, sets the current menu items
* - show(opts) - shows the menu. `opts` is an object of options. See RED.popover.panel.show(opts)
* for the full list of options. In most scenarios, this just needs:
* - target : DOM element - the element to display the menu below
* - hide(cancelled) - hide the menu
*/
/*
* RED.popover.panel(content)
* Create a UI panel that can be displayed relative to any target element.
* Handles auto-closing when mouse clicks outside the panel
*
* - 'content' - DOM element to display in the panel
*
* Returns the panel object with the following functions:
*
* properties:
* - container : DOM element - the panel element
*
* functions:
* - show(opts) - show the panel.
* opts:
* - onclose : function - called when the panel closes
* - closeButton : DOM element - if the panel is closeable by a click of a button,
* by providing a reference to it here, we can
* handle the events properly to hide the panel
* - target : DOM element - the element to display the panel relative to
* - align : string - should the panel align to the left or right edge of target
* default: 'right'
* - offset : Array - px offset to apply from the target. [width, height]
* - dispose : boolean - whether the panel should be removed from DOM when hidden
* default: true
* - hide(dispose) - hide the panel.
*/
RED.popover = (function() { RED.popover = (function() {
var deltaSizes = { var deltaSizes = {
"default": { "default": {
x: 12, top: 10,
y: 12 topTop: 30,
leftRight: 17,
leftLeft: 25,
leftBottom: 8,
leftTop: 11
}, },
"small": { "small": {
x:8, top: 6,
y:8 topTop: 20,
leftRight: 8,
leftLeft: 26,
leftBottom: 8,
leftTop: 9
} }
} }
function createPopover(options) { function createPopover(options) {
@@ -155,9 +41,7 @@ RED.popover = (function() {
var delay = options.delay || { show: 750, hide: 50 }; var delay = options.delay || { show: 750, hide: 50 };
var autoClose = options.autoClose; var autoClose = options.autoClose;
var width = options.width||"auto"; var width = options.width||"auto";
var maxWidth = options.maxWidth;
var size = options.size||"default"; var size = options.size||"default";
var popupOffset = options.offset || 0;
if (!deltaSizes[size]) { if (!deltaSizes[size]) {
throw new Error("Invalid RED.popover size value:",size); throw new Error("Invalid RED.popover size value:",size);
} }
@@ -165,8 +49,6 @@ RED.popover = (function() {
var timer = null; var timer = null;
var active; var active;
var div; var div;
var contentDiv;
var currentStyle;
var openPopup = function(instant) { var openPopup = function(instant) {
if (active) { if (active) {
@@ -176,10 +58,6 @@ RED.popover = (function() {
return; return;
} }
div = $('<div class="red-ui-popover"></div>'); div = $('<div class="red-ui-popover"></div>');
if (options.class) {
div.addClass(options.class);
}
contentDiv = $('<div class="red-ui-popover-content">').appendTo(div);
if (size !== "default") { if (size !== "default") {
div.addClass("red-ui-popover-size-"+size); div.addClass("red-ui-popover-size-"+size);
} }
@@ -189,23 +67,71 @@ RED.popover = (function() {
return; return;
} }
if (typeof result === 'string') { if (typeof result === 'string') {
contentDiv.text(result); div.text(result);
} else { } else {
contentDiv.append(result); div.append(result);
} }
} else { } else {
contentDiv.html(content); div.html(content);
}
if (width !== "auto") {
div.width(width);
} }
div.appendTo("body"); div.appendTo("body");
movePopup({target,direction,width,maxWidth}); var targetPos = target.offset();
var targetWidth = target.outerWidth();
var targetHeight = target.outerHeight();
var divHeight = div.height();
var divWidth = div.width();
var paddingRight = 10;
var viewportTop = $(window).scrollTop();
var viewportLeft = $(window).scrollLeft();
var viewportBottom = viewportTop + $(window).height();
var viewportRight = viewportLeft + $(window).width();
var top = 0;
var left = 0;
var d = direction;
if (d === 'right') {
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
} else if (d === 'left') {
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
} else if (d === 'bottom') {
top = targetPos.top+targetHeight+deltaSizes[size].top;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
if (left < 0) {
d = "right";
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
} else if (left+divWidth+paddingRight > viewportRight) {
d = "left";
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
}
} else if (top+divHeight > viewportBottom) {
d = 'top';
top = targetPos.top-deltaSizes[size].topTop-divHeight;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
}
} else if (d === 'top') {
top = targetPos.top-deltaSizes[size].topTop-divHeight;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
if (top < 0) {
d = 'bottom';
top = targetPos.top+targetHeight+deltaSizes[size].top;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
}
}
div.addClass('red-ui-popover-'+d).css({top: top, left: left});
if (existingPopover) { if (existingPopover) {
existingPopover.close(true); existingPopover.close(true);
} }
if (options.trigger !== 'manual') { target.data("red-ui-popover",res)
target.data("red-ui-popover",res)
}
if (options.tooltip) { if (options.tooltip) {
div.on("mousedown", function(evt) { div.on("mousedown", function(evt) {
closePopup(true); closePopup(true);
@@ -235,104 +161,6 @@ RED.popover = (function() {
} }
} }
} }
var movePopup = function(options) {
target = options.target || target;
direction = options.direction || direction || "right";
popupOffset = options.offset || popupOffset;
var transition = options.transition;
var width = options.width||"auto";
div.width(width);
if (options.maxWidth) {
div.css("max-width",options.maxWidth)
} else {
div.css("max-width", 'auto');
}
var targetPos = target[0].getBoundingClientRect();
var targetHeight = targetPos.height;
var targetWidth = targetPos.width;
var divHeight = div.outerHeight();
var divWidth = div.outerWidth();
var paddingRight = 10;
var viewportTop = $(window).scrollTop();
var viewportLeft = $(window).scrollLeft();
var viewportBottom = viewportTop + $(window).height();
var viewportRight = viewportLeft + $(window).width();
var top = 0;
var left = 0;
if (direction === 'right') {
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
} else if (direction === 'left') {
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
} else if (direction === 'bottom') {
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
if (left < 0) {
direction = "right";
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
} else if (left+divWidth+paddingRight > viewportRight) {
direction = "left";
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
}
} else if (top+divHeight > viewportBottom) {
direction = 'top';
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
}
} else if (direction === 'top') {
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
if (top < 0) {
direction = 'bottom';
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
}
} else if (/inset/.test(direction)) {
top = targetPos.top + targetHeight/2 - divHeight/2;
left = targetPos.left + targetWidth/2 - divWidth/2;
if (/bottom/.test(direction)) {
top = targetPos.top + targetHeight - divHeight-popupOffset;
}
if (/top/.test(direction)) {
top = targetPos.top+popupOffset;
}
if (/left/.test(direction)) {
left = targetPos.left+popupOffset;
}
if (/right/.test(direction)) {
left = targetPos.left + targetWidth - divWidth-popupOffset;
}
}
if (currentStyle) {
div.removeClass(currentStyle);
}
if (transition) {
div.css({
"transition": "0.6s ease",
"transition-property": "top,left,right,bottom"
})
}
currentStyle = 'red-ui-popover-'+direction;
div.addClass(currentStyle).css({top: top, left: left});
if (transition) {
setTimeout(function() {
div.css({
"transition": "none"
});
},600);
}
}
var closePopup = function(instant) { var closePopup = function(instant) {
$(document).off('mousedown.red-ui-popover'); $(document).off('mousedown.red-ui-popover');
if (!active) { if (!active) {
@@ -350,16 +178,6 @@ RED.popover = (function() {
} }
} }
target.on("remove", function (ev) {
if (timer) {
clearTimeout(timer);
}
if (active) {
active = false;
setTimeout(closePopup,delay.hide);
}
});
if (trigger === 'hover') { if (trigger === 'hover') {
target.on('mouseenter',function(e) { target.on('mouseenter',function(e) {
clearTimeout(timer); clearTimeout(timer);
@@ -418,10 +236,8 @@ RED.popover = (function() {
},autoClose); },autoClose);
} }
var res = { var res = {
get element() { return div },
setContent: function(_content) { setContent: function(_content) {
content = _content; content = _content;
return res; return res;
}, },
open: function (instant) { open: function (instant) {
@@ -433,10 +249,6 @@ RED.popover = (function() {
active = false; active = false;
closePopup(instant); closePopup(instant);
return res; return res;
},
move: function(options) {
movePopup(options);
return
} }
} }
return res; return res;
@@ -446,17 +258,18 @@ RED.popover = (function() {
return { return {
create: createPopover, create: createPopover,
tooltip: function(target,content, action) { tooltip: function(target,content, action) {
var label = function() { var label = content;
var label = content; if (action) {
if (action) { label = function() {
var label = content;
var shortcut = RED.keyboard.getShortcut(action); var shortcut = RED.keyboard.getShortcut(action);
if (shortcut && shortcut.key) { if (shortcut && shortcut.key) {
label = $('<span>'+content+' <span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span></span>'); label = $('<span>'+content+' <span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span></span>');
} }
return label;
} }
return label;
} }
var popover = RED.popover.create({ return RED.popover.create({
tooltip: true, tooltip: true,
target:target, target:target,
trigger: "hover", trigger: "hover",
@@ -465,19 +278,6 @@ RED.popover = (function() {
content: label, content: label,
delay: { show: 750, hide: 50 } delay: { show: 750, hide: 50 }
}); });
popover.setContent = function(newContent) {
content = newContent;
}
popover.setAction = function(newAction) {
action = newAction;
}
popover.delete = function() {
popover.close(true)
target.off("mouseenter");
target.off("mouseleave");
};
return popover;
}, },
menu: function(options) { menu: function(options) {
var list = $('<ul class="red-ui-menu"></ul>'); var list = $('<ul class="red-ui-menu"></ul>');
@@ -486,47 +286,20 @@ RED.popover = (function() {
} }
var menuOptions = options.options || []; var menuOptions = options.options || [];
var first; var first;
menuOptions.forEach(function(opt) {
var container = RED.popover.panel(list); var item = $('<li>').appendTo(list);
if (options.width) { var link = $('<a href="#"></a>').text(opt.label).appendTo(item);
container.container.width(options.width); link.on("click", function(evt) {
} evt.preventDefault();
if (options.class) { if (opt.onselect) {
container.container.addClass(options.class); opt.onselect();
}
if (options.maxHeight) {
container.container.css({
"max-height": options.maxHeight,
"overflow-y": 'auto'
})
}
var menu = {
options: function(opts) {
if (opts === undefined) {
return menuOptions
} }
menuOptions = opts || []; menu.hide();
list.empty(); })
menuOptions.forEach(function(opt) { if (!first) { first = link}
var item = $('<li>').appendTo(list); })
var link = $('<a href="#"></a>').appendTo(item); var container = RED.popover.panel(list);
if (typeof opt.label == "string") { var menu = {
link.text(opt.label)
} else if (opt.label){
opt.label.appendTo(link);
}
link.on("click", function(evt) {
evt.preventDefault();
if (opt.onselect) {
opt.onselect();
} else if (options.onselect) {
options.onselect(opt);
}
menu.hide();
})
if (!first) { first = link}
})
},
show: function(opts) { show: function(opts) {
$(document).on("keydown.red-ui-menu", function(evt) { $(document).on("keydown.red-ui-menu", function(evt) {
var currentItem = list.find(":focus").parent(); var currentItem = list.find(":focus").parent();
@@ -535,9 +308,11 @@ RED.popover = (function() {
// DOWN // DOWN
if (currentItem.length > 0) { if (currentItem.length > 0) {
if (currentItem.index() === menuOptions.length-1) { if (currentItem.index() === menuOptions.length-1) {
console.log("WARP TO TOP")
// Wrap to top of list // Wrap to top of list
list.children().first().children().first().focus(); list.children().first().children().first().focus();
} else { } else {
console.log("GO DOWN ONE")
currentItem.next().children().first().focus(); currentItem.next().children().first().focus();
} }
} else { } else {
@@ -548,9 +323,11 @@ RED.popover = (function() {
// UP // UP
if (currentItem.length > 0) { if (currentItem.length > 0) {
if (currentItem.index() === 0) { if (currentItem.index() === 0) {
console.log("WARP TO BOTTOM")
// Wrap to bottom of list // Wrap to bottom of list
list.children().last().children().first().focus(); list.children().last().children().first().focus();
} else { } else {
console.log("GO UP ONE")
currentItem.prev().children().first().focus(); currentItem.prev().children().first().focus();
} }
} else { } else {
@@ -560,11 +337,6 @@ RED.popover = (function() {
// ESCAPE // ESCAPE
evt.preventDefault(); evt.preventDefault();
menu.hide(true); menu.hide(true);
} else if (evt.keyCode === 9 && options.tabSelect) {
// TAB - with tabSelect enabled
evt.preventDefault();
currentItem.find("a").trigger("click");
} }
evt.stopPropagation(); evt.stopPropagation();
}) })
@@ -584,7 +356,6 @@ RED.popover = (function() {
} }
} }
} }
menu.options(menuOptions);
return menu; return menu;
}, },
panel: function(content) { panel: function(content) {
@@ -592,6 +363,7 @@ RED.popover = (function() {
panel.css({ display: "none" }); panel.css({ display: "none" });
panel.appendTo(document.body); panel.appendTo(document.body);
content.appendTo(panel); content.appendTo(panel);
var closeCallback;
function hide(dispose) { function hide(dispose) {
$(document).off("mousedown.red-ui-popover-panel-close"); $(document).off("mousedown.red-ui-popover-panel-close");
@@ -606,26 +378,22 @@ RED.popover = (function() {
} }
function show(options) { function show(options) {
var closeCallback = options.onclose; var closeCallback = options.onclose;
var closeButton = options.closeButton;
var target = options.target; var target = options.target;
var align = options.align || "right"; var align = options.align || "right";
var offset = options.offset || [0,0]; var offset = options.offset || [0,0];
var xPos = options.x;
var yPos = options.y;
var isAbsolutePosition = (xPos !== undefined && yPos !== undefined)
var pos = isAbsolutePosition?{left:xPos, top: yPos}:target.offset(); var pos = target.offset();
var targetWidth = isAbsolutePosition?0:target.width(); var targetWidth = target.width();
var targetHeight = isAbsolutePosition?0:target.outerHeight(); var targetHeight = target.height();
var panelHeight = panel.height(); var panelHeight = panel.height();
var panelWidth = panel.width(); var panelWidth = panel.width();
var top = (targetHeight+pos.top) + offset[1]; var top = (targetHeight+pos.top) + offset[1];
if (top+panelHeight-$(document).scrollTop() > $(window).height()) { if (top+panelHeight > $(window).height()) {
top -= (top+panelHeight)-$(window).height() + 5; top -= (top+panelHeight)-$(window).height() + 5;
} }
if (top < 0) { if (top < 0) {
panel.height(panelHeight+top) panelHeight.height(panelHeight+top)
top = 0; top = 0;
} }
if (align === "right") { if (align === "right") {
@@ -652,8 +420,7 @@ RED.popover = (function() {
}); });
$(document).on("mousedown.red-ui-popover-panel-close", function(event) { $(document).on("mousedown.red-ui-popover-panel-close", function(event) {
var hitCloseButton = closeButton && $(event.target).closest(closeButton).length; if(!$(event.target).closest(panel).length && !$(event.target).closest(".red-ui-editor-dialog").length) {
if(!hitCloseButton && !$(event.target).closest(panel).length && !$(event.target).closest(".red-ui-editor-dialog").length) {
if (closeCallback) { if (closeCallback) {
closeCallback(); closeCallback();
} }

View File

@@ -105,8 +105,8 @@
} }
}); });
this.element.on("keydown",function(e) { this.element.on("keydown",function(e) {
if (!menuShown && e.keyCode === 40 && $(this).val() === '') { if (!menuShown && e.keyCode === 40) {
//DOWN (only show menu if search field is emty) //DOWN
showMenu(); showMenu();
} }
}); });

View File

@@ -38,7 +38,6 @@ RED.tabs = (function() {
if (options.vertical) { if (options.vertical) {
wrapper.addClass("red-ui-tabs-vertical"); wrapper.addClass("red-ui-tabs-vertical");
} }
if (options.addButton) { if (options.addButton) {
wrapper.addClass("red-ui-tabs-add"); wrapper.addClass("red-ui-tabs-add");
var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper); var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
@@ -76,8 +75,6 @@ RED.tabs = (function() {
}); });
} }
if (options.searchButton) { if (options.searchButton) {
// This is soft-deprecated as we don't use this in the core anymore
// We no use the `menu` option to provide a drop-down list of actions
wrapper.addClass("red-ui-tabs-search"); wrapper.addClass("red-ui-tabs-search");
var searchButton = $('<div class="red-ui-tab-button red-ui-tabs-search"><a href="#"><i class="fa fa-list-ul"></i></a></div>').appendTo(wrapper); var searchButton = $('<div class="red-ui-tab-button red-ui-tabs-search"><a href="#"><i class="fa fa-list-ul"></i></a></div>').appendTo(wrapper);
searchButton.find('a').on("click", function(evt) { searchButton.find('a').on("click", function(evt) {
@@ -97,74 +94,6 @@ RED.tabs = (function() {
} }
} }
if (options.menu) {
wrapper.addClass("red-ui-tabs-menu");
var menuButton = $('<div class="red-ui-tab-button red-ui-tabs-menu"><a href="#"><i class="fa fa-caret-down"></i></a></div>').appendTo(wrapper);
var menuButtonLink = menuButton.find('a')
var menuOpen = false;
var menu;
menuButtonLink.on("click", function(evt) {
evt.stopPropagation();
evt.preventDefault();
if (menuOpen) {
menu.remove();
menuOpen = false;
return;
}
menuOpen = true;
var menuOptions = [];
if (typeof options.searchButton === 'function') {
menuOptions = options.menu()
} else if (Array.isArray(options.menu)) {
menuOptions = options.menu;
} else if (typeof options.menu === 'function') {
menuOptions = options.menu();
}
menu = RED.menu.init({options: menuOptions});
menu.attr("id",options.id+"-menu");
menu.css({
position: "absolute"
})
menu.appendTo("body");
var elementPos = menuButton.offset();
menu.css({
top: (elementPos.top+menuButton.height()-2)+"px",
left: (elementPos.left - menu.width() + menuButton.width())+"px"
})
$(".red-ui-menu.red-ui-menu-dropdown").hide();
$(document).on("click.red-ui-tabmenu", function(evt) {
$(document).off("click.red-ui-tabmenu");
menuOpen = false;
menu.remove();
});
menu.show();
})
}
if (options.contextmenu) {
wrapper.on('contextmenu', function(evt) {
let clickedTab
let target = evt.target
while(target.nodeName !== 'A' && target.nodeName !== 'UL' && target.nodeName !== 'BODY') {
target = target.parentNode
}
if (target.nodeName === 'A') {
const href = target.getAttribute('href')
if (href) {
clickedTab = tabs[href.slice(1)]
}
}
evt.preventDefault()
evt.stopPropagation()
RED.contextMenu.show({
x:evt.clientX-5,
y:evt.clientY-5,
options: options.contextmenu(clickedTab)
})
return false
})
}
var scrollLeft; var scrollLeft;
var scrollRight; var scrollRight;
@@ -183,14 +112,14 @@ RED.tabs = (function() {
// Assume this is wheel event which might not trigger // Assume this is wheel event which might not trigger
// the scroll event, so do things manually // the scroll event, so do things manually
var sl = scrollContainer.scrollLeft(); var sl = scrollContainer.scrollLeft();
sl += evt.originalEvent.deltaY; sl -= evt.originalEvent.deltaY;
scrollContainer.scrollLeft(sl); scrollContainer.scrollLeft(sl);
} }
}) })
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a"); scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
scrollLeft.on('mousedown',function(evt) {scrollEventHandler(evt, evt.shiftKey?('-='+scrollContainer.scrollLeft()):'-=150') }).on('click',function(evt){ evt.preventDefault();}); scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') }).on('click',function(evt){ evt.preventDefault();});
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a"); scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,evt.shiftKey?('+='+(scrollContainer[0].scrollWidth - scrollContainer.width()-scrollContainer.scrollLeft())):'+=150') }).on('click',function(evt){ evt.preventDefault();}); scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();});
} }
if (options.collapsible) { if (options.collapsible) {
@@ -408,12 +337,6 @@ RED.tabs = (function() {
if (link.length === 0) { if (link.length === 0) {
return; return;
} }
if (link.parent().hasClass("hide-tab")) {
link.parent().removeClass("hide-tab").removeClass("hide");
if (options.onshow) {
options.onshow(tabs[link.attr('href').slice(1)])
}
}
if (!link.parent().hasClass("active")) { if (!link.parent().hasClass("active")) {
ul.children().removeClass("active"); ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"}); ul.children().css({"transition": "width 100ms"});
@@ -439,13 +362,13 @@ RED.tabs = (function() {
} }
} }
function activatePreviousTab() { function activatePreviousTab() {
var previous = findPreviousVisibleTab(); var previous = ul.find("li.active").prev();
if (previous.length > 0) { if (previous.length > 0) {
activateTab(previous.find("a")); activateTab(previous.find("a"));
} }
} }
function activateNextTab() { function activateNextTab() {
var next = findNextVisibleTab(); var next = ul.find("li.active").next();
if (next.length > 0) { if (next.length > 0) {
activateTab(next.find("a")); activateTab(next.find("a"));
} }
@@ -455,9 +378,7 @@ RED.tabs = (function() {
if (options.vertical) { if (options.vertical) {
return; return;
} }
var allTabs = ul.find("li.red-ui-tab"); var tabs = ul.find("li.red-ui-tab");
var tabs = allTabs.filter(":not(.hide-tab)");
var hiddenTabs = allTabs.filter(".hide-tab");
var width = wrapper.width(); var width = wrapper.width();
var tabCount = tabs.length; var tabCount = tabs.length;
var tabWidth; var tabWidth;
@@ -467,7 +388,7 @@ RED.tabs = (function() {
var visibleCount = collapsedButtonsRow.children(":visible").length; var visibleCount = collapsedButtonsRow.children(":visible").length;
tabWidth = width - collapsedButtonsRow.width()-10; tabWidth = width - collapsedButtonsRow.width()-10;
var maxTabWidth = 198; var maxTabWidth = 198;
var minTabWidth = 120; var minTabWidth = 80;
if (tabWidth <= minTabWidth || (tabWidth < maxTabWidth && visibleCount > 5)) { if (tabWidth <= minTabWidth || (tabWidth < maxTabWidth && visibleCount > 5)) {
// The tab is too small. Hide the next button to make room // The tab is too small. Hide the next button to make room
// Start at the end of the button row, -1 for the menu button // Start at the end of the button row, -1 for the menu button
@@ -525,7 +446,6 @@ RED.tabs = (function() {
// } // }
tabs.css({width:currentTabWidth}); tabs.css({width:currentTabWidth});
hiddenTabs.css({width:"0px"});
if (tabWidth < 50) { if (tabWidth < 50) {
// ul.find(".red-ui-tab-close").hide(); // ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide(); ul.find(".red-ui-tab-icon").hide();
@@ -566,19 +486,12 @@ RED.tabs = (function() {
} }
var li = ul.find("a[href='#"+id+"']").parent(); var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("active")) { if (li.hasClass("active")) {
var tab = findPreviousVisibleTab(li); var tab = li.prev();
if (tab.length === 0) { if (tab.length === 0) {
tab = findNextVisibleTab(li); tab = li.next();
}
if (tab.length > 0) {
activateTab(tab.find("a"));
} else {
if (options.onchange) {
options.onchange(null);
}
} }
activateTab(tab.find("a"));
} }
li.remove(); li.remove();
if (tabs[id].pinned) { if (tabs[id].pinned) {
pinnedTabsCount--; pinnedTabsCount--;
@@ -594,75 +507,6 @@ RED.tabs = (function() {
} }
} }
function findPreviousVisibleTab(li) {
if (!li) {
li = ul.find("li.active");
}
var previous = li.prev();
while(previous.length > 0 && previous.hasClass("hide-tab")) {
previous = previous.prev();
}
return previous;
}
function findNextVisibleTab(li) {
if (!li) {
li = ul.find("li.active");
}
var next = li.next();
while(next.length > 0 && next.hasClass("hide-tab")) {
next = next.next();
}
return next;
}
function showTab(id) {
if (tabs[id]) {
var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("hide-tab")) {
li.removeClass("hide-tab").removeClass("hide");
if (ul.find("li.red-ui-tab:not(.hide-tab)").length === 1) {
activateTab(li.find("a"))
}
updateTabWidths();
if (options.onshow) {
options.onshow(tabs[id])
}
}
}
}
function hideTab(id) {
if (tabs[id]) {
var li = ul.find("a[href='#"+id+"']").parent();
if (!li.hasClass("hide-tab")) {
if (li.hasClass("active")) {
var tab = findPreviousVisibleTab(li);
if (tab.length === 0) {
tab = findNextVisibleTab(li);
}
if (tab.length > 0) {
activateTab(tab.find("a"));
} else {
if (options.onchange) {
options.onchange(null);
}
}
}
li.removeClass("active");
li.one("transitionend", function(evt) {
li.addClass("hide");
updateTabWidths();
if (options.onhide) {
options.onhide(tabs[id])
}
setTimeout(function() {
updateScroll()
},200)
})
li.addClass("hide-tab");
li.css({width:0})
}
}
}
var tabAPI = { var tabAPI = {
addTab: function(tab,targetIndex) { addTab: function(tab,targetIndex) {
if (options.onselect) { if (options.onselect) {
@@ -692,7 +536,7 @@ RED.tabs = (function() {
} }
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li); var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
if (tab.icon) { if (tab.icon) {
$('<i>',{class:"red-ui-tab-icon", style:"mask-image: url("+tab.icon+"); -webkit-mask-image: url("+tab.icon+");"}).appendTo(link); $('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
} else if (tab.iconClass) { } else if (tab.iconClass) {
$('<i>',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link); $('<i>',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link);
} }
@@ -819,7 +663,6 @@ RED.tabs = (function() {
link.on("click", function(evt) { evt.preventDefault(); }) link.on("click", function(evt) { evt.preventDefault(); })
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); }) link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })
$('<span class="red-ui-tabs-fade"></span>').appendTo(li);
if (tab.closeable) { if (tab.closeable) {
li.addClass("red-ui-tabs-closeable") li.addClass("red-ui-tabs-closeable")
@@ -829,31 +672,17 @@ RED.tabs = (function() {
event.preventDefault(); event.preventDefault();
removeTab(tab.id); removeTab(tab.id);
}); });
RED.popover.tooltip(closeLink,RED._("workspace.closeFlow"));
} }
// if (tab.hideable) {
// li.addClass("red-ui-tabs-closeable")
// var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
// closeLink.append('<i class="fa fa-eye" />');
// closeLink.append('<i class="fa fa-eye-slash" />');
// closeLink.on("click",function(event) {
// event.preventDefault();
// hideTab(tab.id);
// });
// RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
// }
var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li); var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
if (options.onselect) { if (options.onselect) {
$('<i class="red-ui-tabs-badge-changed fa fa-circle"></i>').appendTo(badges);
$('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges); $('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges);
} }
// link.attr("title",tab.label);
RED.popover.tooltip(link,function() { return RED.utils.sanitize(tab.label); });
if (options.onadd) { if (options.onadd) {
options.onadd(tab); options.onadd(tab);
} }
link.attr("title",tab.label);
if (ul.find("li.red-ui-tab").length == 1) { if (ul.find("li.red-ui-tab").length == 1) {
activateTab(link); activateTab(link);
} }
@@ -954,40 +783,22 @@ RED.tabs = (function() {
previousTab: activatePreviousTab, previousTab: activatePreviousTab,
resize: updateTabWidths, resize: updateTabWidths,
count: function() { count: function() {
return ul.find("li.red-ui-tab:not(.hide)").length; return ul.find("li.red-ui-tab").length;
}, },
activeIndex: function() { activeIndex: function() {
return ul.find("li.active").index() return ul.find("li.active").index()
},
getTabIndex: function (id) {
return ul.find("a[href='#"+id+"']").parent().index()
}, },
contains: function(id) { contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0; return ul.find("a[href='#"+id+"']").length > 0;
}, },
showTab: showTab,
hideTab: hideTab,
renameTab: function(id,label) { renameTab: function(id,label) {
tabs[id].label = label; tabs[id].label = label;
var tab = ul.find("a[href='#"+id+"']"); var tab = ul.find("a[href='#"+id+"']");
tab.attr("title",label);
tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label)); tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
updateTabWidths(); updateTabWidths();
}, },
listTabs: function() {
return $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
},
selection: getSelection, selection: getSelection,
clearSelection: function() {
if (options.onselect) {
var selection = ul.find("li.red-ui-tab.selected");
if (selection.length > 0) {
selection.removeClass("selected");
selectionChanged();
}
}
},
order: function(order) { order: function(order) {
preferredOrder = order; preferredOrder = order;
var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));

View File

@@ -48,7 +48,7 @@
}); });
this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"></button>'); this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"></button>');
if (enabledLabel || disabledLabel) { if (enabledLabel || disabledLabel) {
this.buttonLabel = $("<span>").appendTo(this.button).css("margin-left", "5px"); this.buttonLabel = $("<span>").appendTo(this.button);
} }
if (this.options.class) { if (this.options.class) {

View File

@@ -21,13 +21,9 @@
* - multi : boolean - if true, .selected will return an array of results * - multi : boolean - if true, .selected will return an array of results
* otherwise, returns the first selected item * otherwise, returns the first selected item
* - sortable: boolean/string - TODO: see editableList * - sortable: boolean/string - TODO: see editableList
* - selectable: boolean - default true - whether individual items can be selected
* - rootSortable: boolean - if 'sortable' is set, then setting this to * - rootSortable: boolean - if 'sortable' is set, then setting this to
* false, prevents items being sorted to the * false, prevents items being sorted to the
* top level of the tree * top level of the tree
* - autoSelect: boolean - default true - triggers item selection when navigating
* list by keyboard. If the list has checkboxed items
* you probably want to set this to false
* *
* methods: * methods:
* - data(items) - clears existing items and replaces with new data * - data(items) - clears existing items and replaces with new data
@@ -45,7 +41,6 @@
* sublabel: 'Local', // a sub-label for the item * sublabel: 'Local', // a sub-label for the item
* icon: 'fa fa-rocket', // (optional) icon for the item * icon: 'fa fa-rocket', // (optional) icon for the item
* checkbox: true/false, // (optional) if present, display checkbox accordingly * checkbox: true/false, // (optional) if present, display checkbox accordingly
* radio: 'group-name', // (optional) if present, display radio box - using group-name to set radio group
* selected: true/false, // (optional) whether the item is selected or not * selected: true/false, // (optional) whether the item is selected or not
* children: [] | function(done,item) // (optional) an array of child items, or a function * children: [] | function(done,item) // (optional) an array of child items, or a function
* // that will call the `done` callback with an array * // that will call the `done` callback with an array
@@ -54,7 +49,6 @@
* deferBuild: true/false, // don't build any ui elements for the item's children * deferBuild: true/false, // don't build any ui elements for the item's children
* until it is expanded by the user. * until it is expanded by the user.
* element: // custom dom element to use for the item - ignored if `label` is set * element: // custom dom element to use for the item - ignored if `label` is set
* collapsible: true/false, // prevent a parent item from being collapsed. default true.
* } * }
* ] * ]
* *
@@ -95,100 +89,77 @@
$.widget( "nodered.treeList", { $.widget( "nodered.treeList", {
_create: function() { _create: function() {
var that = this; var that = this;
var autoSelect = true;
if (that.options.autoSelect === false) {
autoSelect = false;
}
this.element.addClass('red-ui-treeList'); this.element.addClass('red-ui-treeList');
this.element.attr("tabIndex",0); this.element.attr("tabIndex",0);
var wrapper = $('<div>',{class:'red-ui-treeList-container'}).appendTo(this.element); var wrapper = $('<div>',{class:'red-ui-treeList-container'}).appendTo(this.element);
this.element.on('keydown', function(evt) { this.element.on('keydown', function(evt) {
var focussed = that._topList.find(".focus").parent().data('data'); var selected = that._topList.find(".selected").parent().data('data');
if (!focussed && (evt.keyCode === 40 || evt.keyCode === 38)) { if (!selected && (evt.keyCode === 40 || evt.keyCode === 38)) {
if (that._data[0]) { that.select(that._data[0]);
if (autoSelect) {
that.select(that._data[0]);
} else {
that._topList.find(".focus").removeClass("focus")
}
that._data[0].treeList.label.addClass('focus')
}
return; return;
} }
var target; var target;
switch(evt.keyCode) { switch(evt.keyCode) {
case 32: // SPACE
case 13: // ENTER case 13: // ENTER
if (!that.options.selectable) { return }
if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
return
}
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (focussed.checkbox) { if (selected.children) {
focussed.treeList.checkbox.trigger("click"); if (selected.treeList.container.hasClass("expanded")) {
} else if (focussed.radio) { selected.treeList.collapse()
focussed.treeList.radio.trigger("click");
} else if (focussed.children) {
if (focussed.treeList.container.hasClass("expanded")) {
focussed.treeList.collapse()
} else { } else {
focussed.treeList.expand() selected.treeList.expand()
} }
} else { } else {
that._trigger("confirm",null,focussed) that._trigger("confirm",null,selected)
} }
break; break;
case 37: // LEFT case 37: // LEFT
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (focussed.children&& focussed.treeList.container.hasClass("expanded")) { if (selected.children&& selected.treeList.container.hasClass("expanded")) {
focussed.treeList.collapse() selected.treeList.collapse()
} else if (focussed.parent) { } else if (selected.parent) {
target = focussed.parent; target = selected.parent;
} }
break; break;
case 38: // UP case 38: // UP
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
target = that._getPreviousSibling(focussed); target = that._getPreviousSibling(selected);
if (target) { if (target) {
target = that._getLastDescendant(target); target = that._getLastDescendant(target);
} }
if (!target && focussed.parent) { if (!target && selected.parent) {
target = focussed.parent; target = selected.parent;
} }
break; break;
case 39: // RIGHT case 39: // RIGHT
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (focussed.children) { if (selected.children) {
if (!focussed.treeList.container.hasClass("expanded")) { if (!selected.treeList.container.hasClass("expanded")) {
focussed.treeList.expand() selected.treeList.expand()
} }
} }
break break
case 40: //DOWN case 40: //DOWN
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (focussed.children && Array.isArray(focussed.children) && focussed.children.length > 0 && focussed.treeList.container.hasClass("expanded")) { if (selected.children && Array.isArray(selected.children) && selected.children.length > 0 && selected.treeList.container.hasClass("expanded")) {
target = focussed.children[0]; target = selected.children[0];
} else { } else {
target = that._getNextSibling(focussed); target = that._getNextSibling(selected);
while (!target && focussed.parent) { while (!target && selected.parent) {
focussed = focussed.parent; selected = selected.parent;
target = that._getNextSibling(focussed); target = that._getNextSibling(selected);
} }
} }
break break
} }
if (target) { if (target) {
if (autoSelect) { that.select(target);
that.select(target);
} else {
that._topList.find(".focus").removeClass("focus")
}
target.treeList.label.addClass('focus')
} }
}); });
this._data = []; this._data = [];
@@ -342,7 +313,7 @@
if (child.depth !== parent.depth+1) { if (child.depth !== parent.depth+1) {
child.depth = parent.depth+1; child.depth = parent.depth+1;
// var labelPaddingWidth = ((child.gutter ? child.gutter[0].offsetWidth + 2 : 0) + (child.depth * 20)); // var labelPaddingWidth = ((child.gutter ? child.gutter[0].offsetWidth + 2 : 0) + (child.depth * 20));
var labelPaddingWidth = (((child.gutter&&!child.gutter.hasClass("red-ui-treeList-gutter-float"))?child.gutter.width()+2:0)+(child.depth*20)); var labelPaddingWidth = ((child.gutter?child.gutter.width()+2:0)+(child.depth*20));
child.treeList.labelPadding.width(labelPaddingWidth+'px'); child.treeList.labelPadding.width(labelPaddingWidth+'px');
if (child.element) { if (child.element) {
$(child.element).css({ $(child.element).css({
@@ -491,9 +462,6 @@
container.addClass("expanded"); container.addClass("expanded");
} }
item.treeList.collapse = function() { item.treeList.collapse = function() {
if (item.collapsible === false) {
return
}
if (!item.children) { if (!item.children) {
return; return;
} }
@@ -564,12 +532,10 @@
}).appendTo(label) }).appendTo(label)
} }
var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
var labelPaddingWidth = ((item.gutter&&!item.gutter.hasClass("red-ui-treeList-gutter-float"))?item.gutter.width()+2:0)+(depth*20); // var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20)
item.treeList.labelPadding = $('<span>').css({ item.treeList.labelPadding = $('<span>').css({
display: "inline-block", display: "inline-block",
"flex-shrink": 0,
width: labelPaddingWidth+'px' width: labelPaddingWidth+'px'
}).appendTo(label); }).appendTo(label);
@@ -615,7 +581,7 @@
// Already a parent because we've got the angle-right icon // Already a parent because we've got the angle-right icon
return; return;
} }
$('<i class="fa fa-angle-right" />').toggleClass("hide",item.collapsible === false).appendTo(treeListIcon); $('<i class="fa fa-angle-right" />').appendTo(treeListIcon);
treeListIcon.on("click.red-ui-treeList-expand", function(e) { treeListIcon.on("click.red-ui-treeList-expand", function(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@@ -666,46 +632,6 @@
label.on("click", function(e) { label.on("click", function(e) {
e.stopPropagation(); e.stopPropagation();
cb.trigger("click"); cb.trigger("click");
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
})
}
item.treeList.select = function(v) {
if (v !== item.selected) {
cb.trigger("click");
}
}
item.treeList.checkbox = cb;
selectWrapper.appendTo(label)
} else if (item.radio) {
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>');
var cb = $('<input class="red-ui-treeList-radio" type="radio">').prop('name', item.radio).prop('checked',item.selected).appendTo(selectWrapper);
cb.on('click', function(e) {
e.stopPropagation();
});
cb.on('change', function(e) {
item.selected = this.checked;
that._selected.forEach(function(selectedItem) {
if (selectedItem.radio === item.radio) {
selectedItem.treeList.label.removeClass("selected");
selectedItem.selected = false;
that._selected.delete(selectedItem);
}
})
if (item.selected) {
that._selected.add(item);
} else {
that._selected.delete(item);
}
label.toggleClass("selected",this.checked);
that._trigger("select",e,item);
})
if (!item.children) {
label.on("click", function(e) {
e.stopPropagation();
cb.trigger("click");
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
}) })
} }
item.treeList.select = function(v) { item.treeList.select = function(v) {
@@ -714,7 +640,6 @@
} }
} }
selectWrapper.appendTo(label) selectWrapper.appendTo(label)
item.treeList.radio = cb;
} else { } else {
label.on("click", function(e) { label.on("click", function(e) {
if (!that.options.multi) { if (!that.options.multi) {
@@ -722,14 +647,10 @@
} }
label.addClass("selected"); label.addClass("selected");
that._selected.add(item); that._selected.add(item);
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
that._trigger("select",e,item) that._trigger("select",e,item)
}) })
label.on("dblclick", function(e) { label.on("dblclick", function(e) {
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
if (!item.children) { if (!item.children) {
that._trigger("confirm",e,item); that._trigger("confirm",e,item);
} }
@@ -877,9 +798,6 @@
if (item.treeList.label) { if (item.treeList.label) {
item.treeList.label.addClass("selected"); item.treeList.label.addClass("selected");
} }
that._topList.find(".focus").removeClass("focus");
if (triggerEvent !== false) { if (triggerEvent !== false) {
this._trigger("select",null,item) this._trigger("select",null,item)
} }
@@ -887,9 +805,6 @@
clearSelection: function() { clearSelection: function() {
this._selected.forEach(function(item) { this._selected.forEach(function(item) {
item.selected = false; item.selected = false;
if (item.treeList.checkbox) {
item.treeList.checkbox.prop('checked',false)
}
if (item.treeList.label) { if (item.treeList.label) {
item.treeList.label.removeClass("selected") item.treeList.label.removeClass("selected")
} }

View File

@@ -53,120 +53,8 @@
} }
return icon; return icon;
} }
var autoComplete = function(options) {
function getMatch(value, searchValue) {
const idx = value.toLowerCase().indexOf(searchValue.toLowerCase());
const len = idx > -1 ? searchValue.length : 0;
return {
index: idx,
found: idx > -1,
pre: value.substring(0,idx),
match: value.substring(idx,idx+len),
post: value.substring(idx+len),
}
}
function generateSpans(match) {
const els = [];
if(match.pre) { els.push($('<span/>').text(match.pre)); }
if(match.match) { els.push($('<span/>',{style:"font-weight: bold; color: var(--red-ui-text-color-link);"}).text(match.match)); }
if(match.post) { els.push($('<span/>').text(match.post)); }
return els;
}
return function(val) {
var matches = [];
options.forEach(opt => {
const optVal = opt.value;
const optSrc = (opt.source||[]).join(",");
const valMatch = getMatch(optVal, val);
const srcMatch = getMatch(optSrc, val);
if (valMatch.found || srcMatch.found) {
const element = $('<div>',{style: "display: flex"});
const valEl = $('<div/>',{style:"font-family: var(--red-ui-monospace-font); white-space:nowrap; overflow: hidden; flex-grow:1"});
valEl.append(generateSpans(valMatch));
valEl.appendTo(element);
if (optSrc) {
const optEl = $('<div>').css({ "font-size": "0.8em" });
optEl.append(generateSpans(srcMatch));
optEl.appendTo(element);
}
matches.push({
value: optVal,
label: element,
i: (valMatch.found ? valMatch.index : srcMatch.index)
});
}
})
matches.sort(function(A,B){return A.i-B.i})
return matches;
}
}
// This is a hand-generated list of completions for the core nodes (based on the node help html).
var msgCompletions = [
{ value: "payload" },
{ value: "topic", source: ["mqtt","inject","rbe"] },
{ value: "action", source: ["mqtt"] },
{ value: "complete", source: ["join"] },
{ value: "contentType", source: ["mqtt"] },
{ value: "cookies", source: ["http request","http response"] },
{ value: "correlationData", source: ["mqtt"] },
{ value: "delay", source: ["delay","trigger"] },
{ value: "encoding", source: ["file"] },
{ value: "error", source: ["catch"] },
{ value: "error.message", source: ["catch"] },
{ value: "error.source", source: ["catch"] },
{ value: "error.source.id", source: ["catch"] },
{ value: "error.source.type", source: ["catch"] },
{ value: "error.source.name", source: ["catch"] },
{ value: "filename", source: ["file","file in"] },
{ value: "flush", source: ["delay"] },
{ value: "followRedirects", source: ["http request"] },
{ value: "headers", source: ["http response","http request"] },
{ value: "host", source: ["tcp request","http request"] },
{ value: "ip", source: ["udp out"] },
{ value: "kill", source: ["exec"] },
{ value: "messageExpiryInterval", source: ["mqtt"] },
{ value: "method", source: ["http request"] },
{ value: "options", source: ["xml"] },
{ value: "parts", source: ["split","join","batch","sort"] },
{ value: "pid", source: ["exec"] },
{ value: "port", source: ["tcp request"," udp out"] },
{ value: "qos", source: ["mqtt"] },
{ value: "rate", source: ["delay"] },
{ value: "rejectUnauthorized", source: ["http request"] },
{ value: "req", source: ["http in"]},
{ value: "req.body", source: ["http in"]},
{ value: "req.headers", source: ["http in"]},
{ value: "req.query", source: ["http in"]},
{ value: "req.params", source: ["http in"]},
{ value: "req.cookies", source: ["http in"]},
{ value: "req.files", source: ["http in"]},
{ value: "requestTimeout", source: ["http request"] },
{ value: "reset", source: ["delay","trigger","join","rbe"] },
{ value: "responseCookies", source: ["http request"] },
{ value: "responseTopic", source: ["mqtt"] },
{ value: "responseUrl", source: ["http request"] },
{ value: "restartTimeout", source: ["join"] },
{ value: "retain", source: ["mqtt"] },
{ value: "schema", source: ["json"] },
{ value: "select", source: ["html"] },
{ value: "statusCode", source: ["http response","http request"] },
{ value: "status", source: ["status"] },
{ value: "status.text", source: ["status"] },
{ value: "status.source", source: ["status"] },
{ value: "status.source.type", source: ["status"] },
{ value: "status.source.id", source: ["status"] },
{ value: "status.source.name", source: ["status"] },
{ value: "target", source: ["link call"] },
{ value: "template", source: ["template"] },
{ value: "toFront", source: ["delay"] },
{ value: "url", source: ["http request"] },
{ value: "userProperties", source: ["mqtt"] },
{ value: "_session", source: ["websocket out","tcp out"] },
]
var allOptions = { var allOptions = {
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)}, msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression},
flow: {value:"flow",label:"flow.",hasValue:true, flow: {value:"flow",label:"flow.",hasValue:true,
options:[], options:[],
validate:RED.utils.validatePropertyExpression, validate:RED.utils.validatePropertyExpression,
@@ -198,8 +86,6 @@
} }
RED.editor.editJSON({ RED.editor.editJSON({
value: value, value: value,
stateId: RED.editor.generateViewStateId("typedInput", that, "json"),
focus: true,
complete: function(v) { complete: function(v) {
var value = v; var value = v;
try { try {
@@ -222,8 +108,6 @@
var that = this; var that = this;
RED.editor.editExpression({ RED.editor.editExpression({
value: this.value().replace(/\t/g,"\n"), value: this.value().replace(/\t/g,"\n"),
stateId: RED.editor.generateViewStateId("typedInput", that, "jsonata"),
focus: true,
complete: function(v) { complete: function(v) {
that.value(v.replace(/\n/g,"\t")); that.value(v.replace(/\n/g,"\t"));
} }
@@ -238,8 +122,6 @@
var that = this; var that = this;
RED.editor.editBuffer({ RED.editor.editBuffer({
value: this.value(), value: this.value(),
stateId: RED.editor.generateViewStateId("typedInput", that, "bin"),
focus: true,
complete: function(v) { complete: function(v) {
that.value(v); that.value(v);
} }
@@ -383,47 +265,6 @@
} }
} }
}; };
// For a type with options, check value is a valid selection
// If !opt.multiple, returns the valid option object
// if opt.multiple, returns an array of valid option objects
// If not valid, returns null;
function isOptionValueValid(opt, currentVal) {
if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
return {value:currentVal}
} else if (op.value === currentVal) {
return op;
}
}
} else {
// Check to see if value is a valid csv of
// options.
var currentValues = {};
var selected = [];
currentVal.split(",").forEach(function(v) {
if (v) {
currentValues[v] = true;
}
});
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
var val = typeof op === "string" ? op : op.value;
if (currentValues.hasOwnProperty(val)) {
delete currentValues[val];
selected.push(typeof op === "string" ? {value:op} : op.value)
}
}
if (!$.isEmptyObject(currentValues)) {
return null;
}
return selected
}
}
var nlsd = false; var nlsd = false;
$.widget( "nodered.typedInput", { $.widget( "nodered.typedInput", {
@@ -457,8 +298,7 @@
} }
nlsd = true; nlsd = true;
var that = this; var that = this;
this.identifier = this.element.attr('id') || "TypedInput-"+Math.floor(Math.random()*100);
if (this.options.debug) { console.log(this.identifier,"Create",{defaultType:this.options.default, value:this.element.val()}) }
this.disarmClick = false; this.disarmClick = false;
this.input = $('<input class="red-ui-typedInput-input" type="text"></input>'); this.input = $('<input class="red-ui-typedInput-input" type="text"></input>');
this.input.insertAfter(this.element); this.input.insertAfter(this.element);
@@ -488,8 +328,6 @@
}); });
this.defaultInputType = this.input.attr('type'); this.defaultInputType = this.input.attr('type');
// Used to remember selections per-type to restore them when switching between types
this.oldValues = {};
this.uiSelect.addClass("red-ui-typedInput-container"); this.uiSelect.addClass("red-ui-typedInput-container");
@@ -501,7 +339,7 @@
this.options.types = this.options.types||Object.keys(allOptions); this.options.types = this.options.types||Object.keys(allOptions);
} }
this.selectTrigger = $('<button type="button" class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect); this.selectTrigger = $('<button class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
$('<i class="red-ui-typedInput-icon fa fa-caret-down"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger); $('<i class="red-ui-typedInput-icon fa fa-caret-down"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger); this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
@@ -542,9 +380,6 @@
that.element.trigger('paste',evt); that.element.trigger('paste',evt);
}); });
this.input.on('keydown', function(evt) { this.input.on('keydown', function(evt) {
if (that.typeMap[that.propertyType].autoComplete) {
return
}
if (evt.keyCode >= 37 && evt.keyCode <= 40) { if (evt.keyCode >= 37 && evt.keyCode <= 40) {
evt.stopPropagation(); evt.stopPropagation();
} }
@@ -570,11 +405,11 @@
}) })
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
this.optionSelectTrigger = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect); this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger); this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
// RED.popover.tooltip(this.optionSelectLabel,function() { RED.popover.tooltip(this.optionSelectLabel,function() {
// return that.optionValue; return that.optionValue;
// }); });
this.optionSelectTrigger.on("click", function(event) { this.optionSelectTrigger.on("click", function(event) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@@ -591,11 +426,9 @@
that.uiSelect.addClass('red-ui-typedInput-focus'); that.uiSelect.addClass('red-ui-typedInput-focus');
}); });
this.optionExpandButton = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect); this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton); this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
this.type(this.options.default||this.typeList[0].value);
this.type(this.typeField.val() || this.options.default||this.typeList[0].value);
this.typeChanged = !!this.options.default;
}catch(err) { }catch(err) {
console.log(err.stack); console.log(err.stack);
} }
@@ -675,7 +508,7 @@
if (opt.icon.indexOf("<") === 0) { if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(op); $(opt.icon).prependTo(op);
} else if (opt.icon.indexOf("/") !== -1) { } else if (opt.icon.indexOf("/") !== -1) {
$('<i>',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+");"}).prependTo(op); $('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px; height: 18px;"}).prependTo(op);
} else { } else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op); $('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op);
} }
@@ -746,7 +579,7 @@
var height = relativeTo.height(); var height = relativeTo.height();
var menuHeight = menu.height(); var menuHeight = menu.height();
var top = (height+pos.top); var top = (height+pos.top);
if (top+menuHeight-$(document).scrollTop() > $(window).height()) { if (top+menuHeight > $(window).height()) {
top -= (top+menuHeight)-$(window).height()+5; top -= (top+menuHeight)-$(window).height()+5;
} }
if (top < 0) { if (top < 0) {
@@ -843,7 +676,6 @@
var that = this; var that = this;
var currentType = this.type(); var currentType = this.type();
this.typeMap = {}; this.typeMap = {};
var firstCall = (this.typeList === undefined);
this.typeList = types.map(function(opt) { this.typeList = types.map(function(opt) {
var result; var result;
if (typeof opt === 'string') { if (typeof opt === 'string') {
@@ -856,10 +688,8 @@
}); });
if (this.typeList.length < 2) { if (this.typeList.length < 2) {
this.selectTrigger.attr("tabindex", -1) this.selectTrigger.attr("tabindex", -1)
this.selectTrigger.on("mousedown.red-ui-typedInput-focus-block", function(evt) { evt.preventDefault(); })
} else { } else {
this.selectTrigger.attr("tabindex", 0) this.selectTrigger.attr("tabindex", 0)
this.selectTrigger.off("mousedown.red-ui-typedInput-focus-block")
} }
this.selectTrigger.toggleClass("disabled", this.typeList.length === 1); this.selectTrigger.toggleClass("disabled", this.typeList.length === 1);
this.selectTrigger.find(".fa-caret-down").toggle(this.typeList.length > 1) this.selectTrigger.find(".fa-caret-down").toggle(this.typeList.length > 1)
@@ -868,19 +698,10 @@
} }
this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) }); this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) });
if (currentType && !this.typeMap.hasOwnProperty(currentType)) { if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
if (!firstCall) { this.type(this.typeList[0].value);
this.type(this.typeList[0].value);
}
} else { } else {
this.propertyType = null; this.propertyType = null;
if (!firstCall) { this.type(currentType);
this.type(currentType);
}
}
if (this.typeList.length === 1 && !this.typeList[0].icon && (!this.typeList[0].label || this.typeList[0].showLabel === false)) {
this.selectTrigger.hide()
} else {
this.selectTrigger.show()
} }
}, },
width: function(desiredWidth) { width: function(desiredWidth) {
@@ -891,10 +712,7 @@
}, },
value: function(value) { value: function(value) {
var that = this; var that = this;
// If the default type has been set to an invalid type, then on first var opt = this.typeMap[this.propertyType];
// creation, the current propertyType will not exist. Default to an
// empty object on the assumption the corrent type will be set shortly
var opt = this.typeMap[this.propertyType] || {};
if (!arguments.length) { if (!arguments.length) {
var v = this.input.val(); var v = this.input.val();
if (opt.export) { if (opt.export) {
@@ -902,38 +720,27 @@
} }
return v; return v;
} else { } else {
if (this.options.debug) { console.log(this.identifier,"----- SET VALUE ------",value) }
var selectedOption = []; var selectedOption = [];
var valueToCheck = value;
if (opt.options) { if (opt.options) {
if (opt.hasValue && opt.parse) { var checkValues = [value];
var parts = opt.parse(value);
if (this.options.debug) { console.log(this.identifier,"new parse",parts) }
value = parts.value;
valueToCheck = parts.option || parts.value;
}
var checkValues = [valueToCheck];
if (opt.multiple) { if (opt.multiple) {
selectedOption = []; selectedOption = [];
checkValues = valueToCheck.split(","); checkValues = value.split(",");
} }
checkValues.forEach(function(valueToCheck) { checkValues.forEach(function(value) {
for (var i=0;i<opt.options.length;i++) { for (var i=0;i<opt.options.length;i++) {
var op = opt.options[i]; var op = opt.options[i];
if (typeof op === "string") { if (typeof op === "string") {
if (op === valueToCheck || op === ""+valueToCheck) { if (op === value || op === ""+value) {
selectedOption.push(that.activeOptions[op]); selectedOption.push(that.activeOptions[op]);
break; break;
} }
} else if (op.value === valueToCheck) { } else if (op.value === value) {
selectedOption.push(op); selectedOption.push(op);
break; break;
} }
} }
}) })
if (this.options.debug) { console.log(this.identifier,"set value to",value) }
this.input.val(value); this.input.val(value);
if (!opt.multiple) { if (!opt.multiple) {
if (selectedOption.length === 0) { if (selectedOption.length === 0) {
@@ -958,64 +765,9 @@
return this.propertyType; return this.propertyType;
} else { } else {
var that = this; var that = this;
if (this.options.debug) { console.log(this.identifier,"----- SET TYPE -----",type) }
var previousValue = null;
var opt = this.typeMap[type]; var opt = this.typeMap[type];
if (opt && this.propertyType !== type) { if (opt && this.propertyType !== type) {
// If previousType is !null, then this is a change of the type, rather than the initialisation
var previousType = this.typeMap[this.propertyType];
previousValue = this.input.val();
if (previousType && this.typeChanged) {
if (this.options.debug) { console.log(this.identifier,"typeChanged",{previousType,previousValue}) }
if (previousType.options && opt.hasValue !== true) {
this.oldValues[previousType.value] = previousValue;
} else if (previousType.hasValue === false) {
this.oldValues[previousType.value] = previousValue;
} else {
this.oldValues["_"] = previousValue;
}
if ((opt.options && opt.hasValue !== true) || opt.hasValue === false) {
if (this.oldValues.hasOwnProperty(opt.value)) {
if (this.options.debug) { console.log(this.identifier,"restored previous (1)",this.oldValues[opt.value]) }
this.input.val(this.oldValues[opt.value]);
} else if (opt.options) {
// No old value for the option type.
// It is possible code has called 'value' then 'type'
// to set the selected option. This is what the Inject/Switch/Change
// nodes did before 2.1.
// So we need to be careful to not reset the value if it is a valid option.
var validOptions = isOptionValueValid(opt,previousValue);
if (this.options.debug) { console.log(this.identifier,{previousValue,opt,validOptions}) }
if ((previousValue || previousValue === '') && validOptions) {
if (this.options.debug) { console.log(this.identifier,"restored previous (2)") }
this.input.val(previousValue);
} else {
if (typeof opt.default === "string") {
if (this.options.debug) { console.log(this.identifier,"restored previous (3)",opt.default) }
this.input.val(opt.default);
} else if (Array.isArray(opt.default)) {
if (this.options.debug) { console.log(this.identifier,"restored previous (4)",opt.default.join(",")) }
this.input.val(opt.default.join(","))
} else {
if (this.options.debug) { console.log(this.identifier,"restored previous (5)") }
this.input.val("");
}
}
} else {
if (this.options.debug) { console.log(this.identifier,"restored default/blank",opt.default||"") }
this.input.val(opt.default||"")
}
} else {
if (this.options.debug) { console.log(this.identifier,"restored old/default/blank") }
this.input.val(this.oldValues.hasOwnProperty("_")?this.oldValues["_"]:(opt.default||""))
}
if (previousType.autoComplete) {
this.input.autoComplete("destroy");
}
}
this.propertyType = type; this.propertyType = type;
this.typeChanged = true;
if (this.typeField) { if (this.typeField) {
this.typeField.val(type); this.typeField.val(type);
} }
@@ -1026,7 +778,10 @@
$(opt.icon).prependTo(this.selectLabel); $(opt.icon).prependTo(this.selectLabel);
} }
else if (opt.icon.indexOf("/") !== -1) { else if (opt.icon.indexOf("/") !== -1) {
$('<i>',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+"); margin-right: 4px;height: 18px;width:13px"}).prependTo(this.selectLabel); image = new Image();
image.name = opt.icon;
image.src = mapDeprecatedIcon(opt.icon);
$('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
} }
else { else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon,style:"min-width: 13px; margin-right: 4px;"}).prependTo(this.selectLabel); $('<i>',{class:"red-ui-typedInput-icon "+opt.icon,style:"min-width: 13px; margin-right: 4px;"}).prependTo(this.selectLabel);
@@ -1081,12 +836,22 @@
var op; var op;
if (!opt.hasValue) { if (!opt.hasValue) {
// Check the value is valid for the available options var validValue = false;
var validValues = isOptionValueValid(opt,this.input.val()); var currentVal = this.input.val();
if (!opt.multiple) { if (!opt.multiple) {
if (validValues) { for (var i=0;i<opt.options.length;i++) {
that._updateOptionSelectLabel(validValues) op = opt.options[i];
} else { if (typeof op === "string" && op === currentVal) {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
validValue = true;
break;
}
}
if (!validValue) {
op = opt.options[0]; op = opt.options[0];
if (typeof op === "string") { if (typeof op === "string") {
this.value(op); this.value(op);
@@ -1097,19 +862,27 @@
} }
} }
} else { } else {
if (!validValues) { // Check to see if value is a valid csv of
validValues = (opt.default || []).map(function(v) { // options.
return typeof v === "string"?v:v.value var currentValues = {};
}); currentVal.split(",").forEach(function(v) {
this.value(validValues.join(",")); if (v) {
currentValues[v] = true;
}
});
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
delete currentValues[op.value||op];
}
if (!$.isEmptyObject(currentValues)) {
// Invalid, set to default/empty
this.value((opt.default||[]).join(","));
} }
that._updateOptionSelectLabel(validValues);
} }
} else { } else {
var selectedOption = this.optionValue||opt.options[0]; var selectedOption = this.optionValue||opt.options[0];
if (opt.parse) { if (opt.parse) {
var selectedOptionObj = typeof selectedOption === "string"?{value:selectedOption}:selectedOption var parts = opt.parse(this.input.val(),selectedOption);
var parts = opt.parse(this.input.val(),selectedOptionObj);
if (parts.option) { if (parts.option) {
selectedOption = parts.option; selectedOption = parts.option;
if (!this.activeOptions.hasOwnProperty(selectedOption)) { if (!this.activeOptions.hasOwnProperty(selectedOption)) {
@@ -1133,7 +906,6 @@
this._updateOptionSelectLabel(this.activeOptions[selectedOption]); this._updateOptionSelectLabel(this.activeOptions[selectedOption]);
} }
} else if (selectedOption) { } else if (selectedOption) {
if (this.options.debug) { console.log(this.identifier,"HERE",{optionValue:selectedOption.value}) }
this.optionValue = selectedOption.value; this.optionValue = selectedOption.value;
this._updateOptionSelectLabel(selectedOption); this._updateOptionSelectLabel(selectedOption);
} else { } else {
@@ -1166,6 +938,8 @@
this.input.attr('type',this.defaultInputType) this.input.attr('type',this.defaultInputType)
} }
if (opt.hasValue === false) { if (opt.hasValue === false) {
this.oldValue = this.input.val();
this.input.val("");
this.elementDiv.hide(); this.elementDiv.hide();
this.valueLabelContainer.hide(); this.valueLabelContainer.hide();
} else if (opt.valueLabel) { } else if (opt.valueLabel) {
@@ -1178,14 +952,12 @@
this.elementDiv.hide(); this.elementDiv.hide();
opt.valueLabel.call(this,this.valueLabelContainer,this.input.val()); opt.valueLabel.call(this,this.valueLabelContainer,this.input.val());
} else { } else {
if (this.oldValue !== undefined) {
this.input.val(this.oldValue);
delete this.oldValue;
}
this.valueLabelContainer.hide(); this.valueLabelContainer.hide();
this.elementDiv.show(); this.elementDiv.show();
if (opt.autoComplete) {
this.input.autoComplete({
search: opt.autoComplete,
minLength: 0
})
}
} }
if (this.optionExpandButton) { if (this.optionExpandButton) {
if (opt.expand) { if (opt.expand) {
@@ -1270,9 +1042,6 @@
}, },
disabled: function() { disabled: function() {
return this.uiSelect.attr("disabled") === "disabled"; return this.uiSelect.attr("disabled") === "disabled";
},
focus: function() {
this.input.focus();
} }
}); });
})(jQuery); })(jQuery);

View File

@@ -1,246 +0,0 @@
RED.contextMenu = (function () {
let menu;
function disposeMenu() {
$(document).off("mousedown.red-ui-workspace-context-menu");
if (menu) {
menu.remove();
}
menu = null;
}
function show(options) {
if (menu) {
menu.remove()
}
let menuItems = []
if (options.options) {
menuItems = options.options
} else if (options.type === 'workspace') {
const selection = RED.view.selection()
const noSelection = !selection || Object.keys(selection).length === 0
const hasSelection = (selection.nodes && selection.nodes.length > 0);
const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
const hasLinks = wireLinks.length > 0;
const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
const canDelete = hasSelection || hasLinks
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
const canEdit = !RED.workspaces.isLocked()
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
const isAllGroups = hasSelection && selection.nodes.filter(n => n.type !== 'group').length === 0
const hasGroup = hasSelection && selection.nodes.filter(n => n.type === 'group' ).length > 0
const offset = $("#red-ui-workspace-chart").offset()
let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()
if (RED.view.snapGrid) {
const gridSize = RED.view.gridSize()
addX = gridSize * Math.floor(addX / gridSize)
addY = gridSize * Math.floor(addY / gridSize)
}
menuItems.push(
{ onselect: 'core:show-action-list', onpostselect: function () { } }
)
const insertOptions = []
menuItems.push({ label: RED._("contextMenu.insert"), options: insertOptions })
insertOptions.push(
{
label: RED._("contextMenu.node"),
onselect: function () {
RED.view.showQuickAddDialog({
position: [addX, addY],
touchTrigger: true,
splice: isSingleLink ? selection.links[0] : undefined,
// spliceMultiple: isMultipleLinks
})
},
disabled: !canEdit
},
(hasLinks) ? { // has least 1 wire selected
label: RED._("contextMenu.junction"),
onselect: 'core:split-wires-with-junctions',
disabled: !canEdit || !hasLinks
} : {
label: RED._("contextMenu.junction"),
onselect: function () {
const nn = {
_def: { defaults: {} },
type: 'junction',
z: RED.workspaces.active(),
id: RED.nodes.id(),
x: addX,
y: addY,
w: 0, h: 0,
outputs: 1,
inputs: 1,
dirty: true,
moved: true
}
const junction = RED.nodes.addJunction(nn);
const historyEvent = {
dirty: RED.nodes.dirty(),
t: 'add',
junctions: [junction]
}
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.view.select({nodes: [junction] });
RED.view.redraw(true)
},
disabled: !canEdit
},
{
label: RED._("contextMenu.linkNodes"),
onselect: 'core:split-wire-with-link-nodes',
disabled: !canEdit || !hasLinks
},
null,
{ onselect: 'core:show-import-dialog', label: RED._('common.label.import')},
{ onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') }
)
if (hasSelection && canEdit) {
const nodeOptions = []
if (!hasMultipleSelection && !isGroup) {
nodeOptions.push(
{ onselect: 'core:show-node-help' },
null
)
}
nodeOptions.push(
{ onselect: 'core:enable-selected-nodes' },
{ onselect: 'core:disable-selected-nodes' },
null,
{ onselect: 'core:show-selected-node-labels' },
{ onselect: 'core:hide-selected-node-labels' }
)
menuItems.push({
label: RED._('sidebar.info.node'),
options: nodeOptions
})
menuItems.push({
label: RED._('sidebar.info.group'),
options: [
{ onselect: 'core:group-selection' },
{ onselect: 'core:ungroup-selection', disabled: !hasGroup },
]
})
if (hasGroup) {
menuItems[menuItems.length - 1].options.push(
{ onselect: 'core:merge-selection-to-group', label: RED._("menu.label.groupMergeSelection") }
)
}
if (canRemoveFromGroup) {
menuItems[menuItems.length - 1].options.push(
{ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") }
)
}
menuItems[menuItems.length - 1].options.push(
null,
{ onselect: 'core:copy-group-style', disabled: !hasGroup },
{ onselect: 'core:paste-group-style', disabled: !hasGroup}
)
}
if (canEdit && hasMultipleSelection) {
menuItems.push({
label: RED._('menu.label.arrange'),
options: [
{ label:RED._("menu.label.alignLeft"), onselect: "core:align-selection-to-left"},
{ label:RED._("menu.label.alignCenter"), onselect: "core:align-selection-to-center"},
{ label:RED._("menu.label.alignRight"), onselect: "core:align-selection-to-right"},
null,
{ label:RED._("menu.label.alignTop"), onselect: "core:align-selection-to-top"},
{ label:RED._("menu.label.alignMiddle"), onselect: "core:align-selection-to-middle"},
{ label:RED._("menu.label.alignBottom"), onselect: "core:align-selection-to-bottom"},
null,
{ label:RED._("menu.label.distributeHorizontally"), onselect: "core:distribute-selection-horizontally"},
{ label:RED._("menu.label.distributeVertically"), onselect: "core:distribute-selection-vertically"}
]
})
}
menuItems.push(
null,
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 },
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
null,
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !canEdit || !hasSelection },
{ onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !canEdit || !RED.view.clipboard() },
{ onselect: 'core:delete-selection', disabled: !canEdit || !canDelete },
{ onselect: 'core:delete-selection-and-reconnect', label: RED._('keyboard.deleteReconnect'), disabled: !canEdit || !canDelete },
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
{ onselect: 'core:select-all-nodes' },
)
}
var direction = "right";
var MENU_WIDTH = 500; // can not use menu width here
if ((options.x -$(document).scrollLeft()) >
($(window).width() -MENU_WIDTH)) {
direction = "left";
}
menu = RED.menu.init({
direction: direction,
onpreselect: function() {
disposeMenu()
},
onpostselect: function () {
RED.view.focus()
},
options: menuItems
});
menu.attr("id", "red-ui-workspace-context-menu");
menu.css({
position: "absolute"
})
menu.appendTo("body");
// TODO: prevent the menu from overflowing the window.
var top = options.y
var left = options.x
if (top + menu.height() - $(document).scrollTop() > $(window).height()) {
top -= (top + menu.height()) - $(window).height() + 22;
}
if (left + menu.width() - $(document).scrollLeft() > $(window).width()) {
left -= (left + menu.width()) - $(window).width() + 18;
}
menu.css({
top: top + "px",
left: left + "px"
})
$(".red-ui-menu.red-ui-menu-dropdown").hide();
$(document).on("mousedown.red-ui-workspace-context-menu", function (evt) {
if (menu && menu[0].contains(evt.target)) {
return
}
disposeMenu()
});
menu.show();
// set focus to first item so that pressing escape key closes the menu
$("#red-ui-workspace-context-menu :first(ul) > a").trigger("focus")
}
// Allow escape key hook and other editor events to close context menu
RED.keyboard.add("red-ui-workspace-context-menu", "escape", function () { RED.contextMenu.hide() })
RED.events.on("editor:open", function () { RED.contextMenu.hide() });
RED.events.on("search:open", function () { RED.contextMenu.hide() });
RED.events.on("type-search:open", function () { RED.contextMenu.hide() });
RED.events.on("actionList:open", function () { RED.contextMenu.hide() });
RED.events.on("view:selection-changed", function () { RED.contextMenu.hide() });
return {
show: show,
hide: disposeMenu
}
})()

View File

@@ -63,18 +63,16 @@ RED.deploy = (function() {
'</a>'+ '</a>'+
'<a id="red-ui-header-button-deploy-options" class="red-ui-deploy-button" href="#"><i class="fa fa-caret-down"></i></a>'+ '<a id="red-ui-header-button-deploy-options" class="red-ui-deploy-button" href="#"><i class="fa fa-caret-down"></i></a>'+
'</span></li>').prependTo(".red-ui-header-toolbar"); '</span></li>').prependTo(".red-ui-header-toolbar");
const mainMenuItems = [ RED.menu.init({id:"red-ui-header-button-deploy-options",
{id:"deploymenu-item-full",toggle:"deploy-type",icon:"red/images/deploy-full.svg",label:RED._("deploy.full"),sublabel:RED._("deploy.fullDesc"),selected: true, onselect:function(s) { if(s){changeDeploymentType("full")}}}, options: [
{id:"deploymenu-item-flow",toggle:"deploy-type",icon:"red/images/deploy-flows.svg",label:RED._("deploy.modifiedFlows"),sublabel:RED._("deploy.modifiedFlowsDesc"), onselect:function(s) {if(s){changeDeploymentType("flows")}}}, {id:"deploymenu-item-full",toggle:"deploy-type",icon:"red/images/deploy-full.svg",label:RED._("deploy.full"),sublabel:RED._("deploy.fullDesc"),selected: true, onselect:function(s) { if(s){changeDeploymentType("full")}}},
{id:"deploymenu-item-node",toggle:"deploy-type",icon:"red/images/deploy-nodes.svg",label:RED._("deploy.modifiedNodes"),sublabel:RED._("deploy.modifiedNodesDesc"),onselect:function(s) { if(s){changeDeploymentType("nodes")}}}, {id:"deploymenu-item-flow",toggle:"deploy-type",icon:"red/images/deploy-flows.svg",label:RED._("deploy.modifiedFlows"),sublabel:RED._("deploy.modifiedFlowsDesc"), onselect:function(s) {if(s){changeDeploymentType("flows")}}},
null {id:"deploymenu-item-node",toggle:"deploy-type",icon:"red/images/deploy-nodes.svg",label:RED._("deploy.modifiedNodes"),sublabel:RED._("deploy.modifiedNodesDesc"),onselect:function(s) { if(s){changeDeploymentType("nodes")}}},
] null,
if (RED.settings.runtimeState && RED.settings.runtimeState.ui === true) { {id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"},
mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:RED._("deploy.startFlows"),sublabel:RED._("deploy.startFlowsDesc"),onselect:"core:start-flows", visible:false})
mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:RED._("deploy.stopFlows"),sublabel:RED._("deploy.stopFlowsDesc"),onselect:"core:stop-flows", visible:false}) ]
} });
mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"})
RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems });
} else if (type == "simple") { } else if (type == "simple") {
var label = options.label || RED._("deploy.deploy"); var label = options.label || RED._("deploy.deploy");
var icon = 'red/images/deploy-full-o.svg'; var icon = 'red/images/deploy-full-o.svg';
@@ -102,10 +100,6 @@ RED.deploy = (function() {
RED.actions.add("core:deploy-flows",save); RED.actions.add("core:deploy-flows",save);
if (type === "default") { if (type === "default") {
if (RED.settings.runtimeState && RED.settings.runtimeState.ui === true) {
RED.actions.add("core:stop-flows",function() { stopStartFlows("stop") });
RED.actions.add("core:start-flows",function() { stopStartFlows("start") });
}
RED.actions.add("core:restart-flows",restart); RED.actions.add("core:restart-flows",restart);
RED.actions.add("core:set-deploy-type-to-full",function() { RED.menu.setSelected("deploymenu-item-full",true);}); RED.actions.add("core:set-deploy-type-to-full",function() { RED.menu.setSelected("deploymenu-item-full",true);});
RED.actions.add("core:set-deploy-type-to-modified-flows",function() { RED.menu.setSelected("deploymenu-item-flow",true); }); RED.actions.add("core:set-deploy-type-to-modified-flows",function() { RED.menu.setSelected("deploymenu-item-flow",true); });
@@ -276,73 +270,18 @@ RED.deploy = (function() {
function sanitize(html) { function sanitize(html) {
return html.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;") return html.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")
} }
function restart() {
function shadeShow() { var startTime = Date.now();
$(".red-ui-deploy-button-content").css('opacity',0);
$(".red-ui-deploy-button-spinner").show();
var deployWasEnabled = !$("#red-ui-header-button-deploy").hasClass("disabled");
$("#red-ui-header-button-deploy").addClass("disabled");
deployInflight = true;
$("#red-ui-header-shade").show(); $("#red-ui-header-shade").show();
$("#red-ui-editor-shade").show(); $("#red-ui-editor-shade").show();
$("#red-ui-palette-shade").show(); $("#red-ui-palette-shade").show();
$("#red-ui-sidebar-shade").show(); $("#red-ui-sidebar-shade").show();
}
function shadeHide() {
$("#red-ui-header-shade").hide();
$("#red-ui-editor-shade").hide();
$("#red-ui-palette-shade").hide();
$("#red-ui-sidebar-shade").hide();
}
function deployButtonSetBusy(){
$(".red-ui-deploy-button-content").css('opacity',0);
$(".red-ui-deploy-button-spinner").show();
$("#red-ui-header-button-deploy").addClass("disabled");
}
function deployButtonClearBusy(){
$(".red-ui-deploy-button-content").css('opacity',1);
$(".red-ui-deploy-button-spinner").hide();
}
function stopStartFlows(state) {
const startTime = Date.now()
const deployWasEnabled = !$("#red-ui-header-button-deploy").hasClass("disabled")
deployInflight = true
deployButtonSetBusy()
shadeShow()
$.ajax({
url:"flows/state",
type: "POST",
data: {state: state}
}).done(function(data,textStatus,xhr) {
if (deployWasEnabled) {
$("#red-ui-header-button-deploy").removeClass("disabled")
}
}).fail(function(xhr,textStatus,err) {
if (deployWasEnabled) {
$("#red-ui-header-button-deploy").removeClass("disabled")
}
if (xhr.status === 401) {
RED.notify(RED._("notification.error", { message: RED._("user.notAuthorized") }), "error")
} else if (xhr.responseText) {
const errorDetail = { message: err ? (err + "") : "" }
try {
errorDetail.message = JSON.parse(xhr.responseText).message
} finally {
errorDetail.message = errorDetail.message || xhr.responseText
}
RED.notify(RED._("notification.error", errorDetail), "error")
} else {
RED.notify(RED._("notification.error", { message: RED._("deploy.errors.noResponse") }), "error")
}
}).always(function() {
const delta = Math.max(0, 300 - (Date.now() - startTime))
setTimeout(function () {
deployButtonClearBusy()
shadeHide()
deployInflight = false
}, delta);
});
}
function restart() {
var startTime = Date.now();
var deployWasEnabled = !$("#red-ui-header-button-deploy").hasClass("disabled");
deployInflight = true;
deployButtonSetBusy();
$.ajax({ $.ajax({
url:"flows", url:"flows",
type: "POST", type: "POST",
@@ -368,287 +307,204 @@ RED.deploy = (function() {
RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error"); RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error");
} }
}).always(function() { }).always(function() {
deployInflight = false;
var delta = Math.max(0,300-(Date.now()-startTime)); var delta = Math.max(0,300-(Date.now()-startTime));
setTimeout(function() { setTimeout(function() {
deployButtonClearBusy(); $(".red-ui-deploy-button-content").css('opacity',1);
deployInflight = false; $(".red-ui-deploy-button-spinner").hide();
$("#red-ui-header-shade").hide();
$("#red-ui-editor-shade").hide();
$("#red-ui-palette-shade").hide();
$("#red-ui-sidebar-shade").hide();
},delta); },delta);
}); });
} }
function save(skipValidation, force) { function save(skipValidation,force) {
if ($("#red-ui-header-button-deploy").hasClass("disabled")) { if (!$("#red-ui-header-button-deploy").hasClass("disabled")) {
return; //deploy is disabled if (!RED.user.hasPermission("flows.write")) {
} RED.notify(RED._("user.errors.deploy"),"error");
if ($("#red-ui-header-shade").is(":visible")) {
return; //deploy is shaded
}
if (!RED.user.hasPermission("flows.write")) {
RED.notify(RED._("user.errors.deploy"), "error");
return;
}
let hasUnusedConfig = false;
if (!skipValidation) {
let hasUnknown = false;
let hasInvalid = false;
const unknownNodes = [];
const invalidNodes = [];
RED.nodes.eachConfig(function (node) {
if (node.valid === undefined) {
RED.editor.validateNode(node);
}
if (!node.valid && !node.d) {
invalidNodes.push(getNodeInfo(node));
}
if (node.type === "unknown") {
if (unknownNodes.indexOf(node.name) == -1) {
unknownNodes.push(node.name);
}
}
});
RED.nodes.eachNode(function (node) {
if (!node.valid && !node.d) {
invalidNodes.push(getNodeInfo(node));
}
if (node.type === "unknown") {
if (unknownNodes.indexOf(node.name) == -1) {
unknownNodes.push(node.name);
}
}
});
hasUnknown = unknownNodes.length > 0;
hasInvalid = invalidNodes.length > 0;
const unusedConfigNodes = [];
RED.nodes.eachConfig(function (node) {
if ((node._def.hasUsers !== false) && (node.users.length === 0)) {
unusedConfigNodes.push(getNodeInfo(node));
hasUnusedConfig = true;
}
});
let showWarning = false;
let notificationMessage;
let notificationButtons = [];
let notification;
if (hasUnknown && !ignoreDeployWarnings.unknown) {
showWarning = true;
notificationMessage = "<p>" + RED._('deploy.confirm.unknown') + "</p>" +
'<ul class="red-ui-deploy-dialog-confirm-list"><li>' + cropList(unknownNodes).map(function (n) { return sanitize(n) }).join("</li><li>") + "</li></ul><p>" +
RED._('deploy.confirm.confirm') +
"</p>";
notificationButtons = [
{
text: RED._("deploy.unknownNodesButton"),
class: "pull-left",
click: function() {
notification.close();
RED.actions.invoke("core:search","type:unknown ");
}
},
{
id: "red-ui-deploy-dialog-confirm-deploy-deploy",
text: RED._("deploy.confirm.button.confirm"),
class: "primary",
click: function () {
save(true);
notification.close();
}
}
];
} else if (hasInvalid && !ignoreDeployWarnings.invalid) {
showWarning = true;
invalidNodes.sort(sortNodeInfo);
notificationMessage = "<p>" + RED._('deploy.confirm.improperlyConfigured') + "</p>" +
'<ul class="red-ui-deploy-dialog-confirm-list"><li>' + cropList(invalidNodes.map(function (A) { return sanitize((A.tab ? "[" + A.tab + "] " : "") + A.label + " (" + A.type + ")") })).join("</li><li>") + "</li></ul><p>" +
RED._('deploy.confirm.confirm') +
"</p>";
notificationButtons = [
{
text: RED._("deploy.invalidNodesButton"),
class: "pull-left",
click: function() {
notification.close();
RED.actions.invoke("core:search","is:invalid ");
}
},
{
id: "red-ui-deploy-dialog-confirm-deploy-deploy",
text: RED._("deploy.confirm.button.confirm"),
class: "primary",
click: function () {
save(true);
notification.close();
}
}
];
}
if (showWarning) {
notificationButtons.unshift(
{
text: RED._("common.label.cancel"),
click: function () {
notification.close();
}
}
);
notification = RED.notify(notificationMessage, {
modal: true,
fixed: true,
buttons: notificationButtons
});
return; return;
} }
} if (!skipValidation) {
var hasUnknown = false;
var hasInvalid = false;
var hasUnusedConfig = false;
const nns = RED.nodes.createCompleteNodeSet(); var unknownNodes = [];
const startTime = Date.now(); var invalidNodes = [];
deployButtonSetBusy(); RED.nodes.eachNode(function(node) {
const data = { flows: nns }; if (!node.valid && !node.d) {
if (!force) { invalidNodes.push(getNodeInfo(node));
data.rev = RED.nodes.version(); }
} if (node.type === "unknown") {
if (unknownNodes.indexOf(node.name) == -1) {
unknownNodes.push(node.name);
}
}
});
hasUnknown = unknownNodes.length > 0;
hasInvalid = invalidNodes.length > 0;
deployInflight = true; var unusedConfigNodes = [];
shadeShow(); RED.nodes.eachConfig(function(node) {
$.ajax({ if ((node._def.hasUsers !== false) && (node.users.length === 0)) {
url: "flows", unusedConfigNodes.push(getNodeInfo(node));
type: "POST", hasUnusedConfig = true;
data: JSON.stringify(data), }
contentType: "application/json; charset=utf-8", });
headers: {
"Node-RED-Deployment-Type": deploymentType var showWarning = false;
} var notificationMessage;
}).done(function (data, textStatus, xhr) { var notificationButtons = [];
RED.nodes.dirty(false); var notification;
RED.nodes.version(data.rev); if (hasUnknown && !ignoreDeployWarnings.unknown) {
RED.nodes.originalFlow(nns); showWarning = true;
if (hasUnusedConfig) { notificationMessage = "<p>"+RED._('deploy.confirm.unknown')+"</p>"+
let notification; '<ul class="red-ui-deploy-dialog-confirm-list"><li>'+cropList(unknownNodes).map(function(n) { return sanitize(n) }).join("</li><li>")+"</li></ul><p>"+
const opts = { RED._('deploy.confirm.confirm')+
type: "success", "</p>";
fixed: false,
timeout: 6000, notificationButtons= [
buttons: [
{ {
text: RED._("deploy.unusedConfigNodesButton"), id: "red-ui-deploy-dialog-confirm-deploy-deploy",
class: "pull-left", text: RED._("deploy.confirm.button.confirm"),
click: function() {
notification.close();
RED.actions.invoke("core:search","is:config is:unused ");
}
},
{
text: RED._("common.label.close"),
class: "primary", class: "primary",
click: function () { click: function() {
save(true); save(true);
notification.close(); notification.close();
} }
} }
] ];
} else if (hasInvalid && !ignoreDeployWarnings.invalid) {
showWarning = true;
invalidNodes.sort(sortNodeInfo);
notificationMessage = "<p>"+RED._('deploy.confirm.improperlyConfigured')+"</p>"+
'<ul class="red-ui-deploy-dialog-confirm-list"><li>'+cropList(invalidNodes.map(function(A) { return sanitize( (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")")})).join("</li><li>")+"</li></ul><p>"+
RED._('deploy.confirm.confirm')+
"</p>";
notificationButtons= [
{
id: "red-ui-deploy-dialog-confirm-deploy-deploy",
text: RED._("deploy.confirm.button.confirm"),
class: "primary",
click: function() {
save(true);
notification.close();
}
}
];
} }
notification = RED.notify( if (showWarning) {
'<p>' + RED._("deploy.successfulDeploy") + '</p>' + notificationButtons.unshift(
'<p>' + RED._("deploy.unusedConfigNodes") + '</p>', opts); {
} else { text: RED._("common.label.cancel"),
RED.notify('<p>' + RED._("deploy.successfulDeploy") + '</p>', "success"); click: function() {
} notification.close();
const flowsToLock = new Set() }
function ensureUnlocked(id) { }
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null); );
const isLocked = flow ? flow.locked : false; notification = RED.notify(notificationMessage,{
if (flow && isLocked) { modal: true,
flow.locked = false; fixed: true,
flowsToLock.add(flow) buttons:notificationButtons
});
return;
} }
} }
RED.nodes.eachNode(function (node) {
ensureUnlocked(node.z) var nns = RED.nodes.createCompleteNodeSet();
if (node.changed) {
node.dirty = true; var startTime = Date.now();
node.changed = false; $(".red-ui-deploy-button-content").css('opacity',0);
$(".red-ui-deploy-button-spinner").show();
$("#red-ui-header-button-deploy").addClass("disabled");
var data = {flows:nns};
if (!force) {
data.rev = RED.nodes.version();
}
deployInflight = true;
$("#red-ui-header-shade").show();
$("#red-ui-editor-shade").show();
$("#red-ui-palette-shade").show();
$("#red-ui-sidebar-shade").show();
$.ajax({
url:"flows",
type: "POST",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
headers: {
"Node-RED-Deployment-Type":deploymentType
} }
if (node.moved) { }).done(function(data,textStatus,xhr) {
node.dirty = true; RED.nodes.dirty(false);
node.moved = false; RED.nodes.version(data.rev);
RED.nodes.originalFlow(nns);
if (hasUnusedConfig) {
RED.notify(
'<p>'+RED._("deploy.successfulDeploy")+'</p>'+
'<p>'+RED._("deploy.unusedConfigNodes")+' <a href="#" onclick="RED.sidebar.config.show(true); return false;">'+RED._("deploy.unusedConfigNodesLink")+'</a></p>',"success",false,6000);
} else {
RED.notify('<p>'+RED._("deploy.successfulDeploy")+'</p>',"success");
} }
if (node.credentials) { RED.nodes.eachNode(function(node) {
delete node.credentials; if (node.changed) {
} node.dirty = true;
}); node.changed = false;
RED.nodes.eachGroup(function (node) { }
ensureUnlocked(node.z) if (node.moved) {
if (node.changed) { node.dirty = true;
node.dirty = true; node.moved = false;
node.changed = false; }
} if(node.credentials) {
if (node.moved) { delete node.credentials;
node.dirty = true; }
node.moved = false; });
} RED.nodes.eachConfig(function (confNode) {
}) confNode.changed = false;
RED.nodes.eachJunction(function (node) { if (confNode.credentials) {
ensureUnlocked(node.z) delete confNode.credentials;
if (node.changed) { }
node.dirty = true; });
node.changed = false; RED.nodes.eachSubflow(function(subflow) {
} subflow.changed = false;
if (node.moved) { });
node.dirty = true; RED.nodes.eachWorkspace(function(ws) {
node.moved = false;
}
})
RED.nodes.eachConfig(function (confNode) {
if (confNode.z) {
ensureUnlocked(confNode.z)
}
confNode.changed = false;
if (confNode.credentials) {
delete confNode.credentials;
}
});
RED.nodes.eachSubflow(function (subflow) {
subflow.changed = false;
});
RED.nodes.eachWorkspace(function (ws) {
if (ws.changed || ws.added) {
ensureUnlocked(ws.z)
ws.changed = false; ws.changed = false;
delete ws.added });
RED.events.emit("flows:change", ws) // Once deployed, cannot undo back to a clean state
RED.history.markAllDirty();
RED.view.redraw();
RED.events.emit("deploy");
}).fail(function(xhr,textStatus,err) {
RED.nodes.dirty(true);
$("#red-ui-header-button-deploy").removeClass("disabled");
if (xhr.status === 401) {
RED.notify(RED._("deploy.deployFailed",{message:RED._("user.notAuthorized")}),"error");
} else if (xhr.status === 409) {
resolveConflict(nns, true);
} else if (xhr.responseText) {
RED.notify(RED._("deploy.deployFailed",{message:xhr.responseText}),"error");
} else {
RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error");
} }
}); }).always(function() {
flowsToLock.forEach(flow => {
flow.locked = true
})
// Once deployed, cannot undo back to a clean state
RED.history.markAllDirty();
RED.view.redraw();
RED.events.emit("deploy");
}).fail(function (xhr, textStatus, err) {
RED.nodes.dirty(true);
$("#red-ui-header-button-deploy").removeClass("disabled");
if (xhr.status === 401) {
RED.notify(RED._("deploy.deployFailed", { message: RED._("user.notAuthorized") }), "error");
} else if (xhr.status === 409) {
resolveConflict(nns, true);
} else if (xhr.responseText) {
RED.notify(RED._("deploy.deployFailed", { message: xhr.responseText }), "error");
} else {
RED.notify(RED._("deploy.deployFailed", { message: RED._("deploy.errors.noResponse") }), "error");
}
}).always(function () {
const delta = Math.max(0, 300 - (Date.now() - startTime));
setTimeout(function () {
deployInflight = false; deployInflight = false;
deployButtonClearBusy() var delta = Math.max(0,300-(Date.now()-startTime));
shadeHide() setTimeout(function() {
}, delta); $(".red-ui-deploy-button-content").css('opacity',1);
}); $(".red-ui-deploy-button-spinner").hide();
$("#red-ui-header-shade").hide();
$("#red-ui-editor-shade").hide();
$("#red-ui-palette-shade").hide();
$("#red-ui-sidebar-shade").hide();
},delta);
});
}
} }
return { return {
init: init, init: init,

View File

@@ -1,61 +0,0 @@
RED.diagnostics = (function () {
function init() {
if (RED.settings.get('diagnostics.ui', true) === false) {
return;
}
RED.actions.add("core:show-system-info", function () { show(); });
}
function show() {
$.ajax({
headers: {
"Accept": "application/json"
},
cache: false,
url: 'diagnostics',
success: function (data) {
var json = JSON.stringify(data || {}, "", 4);
if (json === "{}") {
json = "{\n\n}";
}
RED.editor.editJSON({
title: RED._('diagnostics.title'),
value: json,
requireValid: true,
readOnly: true,
toolbarButtons: [
{
text: RED._('clipboard.export.copy'),
icon: 'fa fa-copy',
click: function () {
RED.clipboard.copyText(json, $(this), RED._('clipboard.copyMessageValue'))
}
},
{
text: RED._('clipboard.download'),
icon: 'fa fa-download',
click: function () {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json));
element.setAttribute('download', "system-info.json");
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
},
]
});
},
error: function (jqXHR, textStatus, errorThrown) {
console.log("Unexpected error loading system info:", jqXHR.status, textStatus, errorThrown);
}
});
}
return {
init: init,
};
})();

View File

@@ -554,8 +554,6 @@ RED.diff = (function() {
color: "#DDAA99", color: "#DDAA99",
defaults:{name:{value:""}} defaults:{name:{value:""}}
} }
} else if (node.type === "group") {
def = RED.group.def;
} else { } else {
def = {}; def = {};
} }
@@ -765,15 +763,16 @@ RED.diff = (function() {
} }
} }
if (node.hasOwnProperty('x')) { if (node.hasOwnProperty('x')) {
if (localNode) { if (localNode) {
if (localNode.x !== node.x || localNode.y !== node.y || localNode.w !== node.w || localNode.h !== node.h ) { if (localNode.x !== node.x || localNode.y !== node.y) {
localChanged = true; localChanged = true;
localChanges++; localChanges++;
} }
} }
if (remoteNode) { if (remoteNode) {
if (remoteNode.x !== node.x || remoteNode.y !== node.y|| remoteNode.w !== node.w || remoteNode.h !== node.h) { if (remoteNode.x !== node.x || remoteNode.y !== node.y) {
remoteChanged = true; remoteChanged = true;
remoteChanges++; remoteChanges++;
} }
@@ -791,12 +790,7 @@ RED.diff = (function() {
localCell.addClass("red-ui-diff-status-"+(localChanged?"changed":"unchanged")); localCell.addClass("red-ui-diff-status-"+(localChanged?"changed":"unchanged"));
$('<span class="red-ui-diff-status">'+(localChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(localCell); $('<span class="red-ui-diff-status">'+(localChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(localCell);
element = $('<span class="red-ui-diff-list-element"></span>').appendTo(localCell); element = $('<span class="red-ui-diff-list-element"></span>').appendTo(localCell);
var localPosition = {x:localNode.x,y:localNode.y}; propertyElements['local.position'] = RED.utils.createObjectElement({x:localNode.x,y:localNode.y},
if (localNode.hasOwnProperty('w')) {
localPosition.w = localNode.w;
localPosition.h = localNode.h;
}
propertyElements['local.position'] = RED.utils.createObjectElement(localPosition,
{ {
path: "position", path: "position",
exposeApi: true, exposeApi: true,
@@ -817,12 +811,7 @@ RED.diff = (function() {
if (remoteNode) { if (remoteNode) {
$('<span class="red-ui-diff-status">'+(remoteChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(remoteCell); $('<span class="red-ui-diff-status">'+(remoteChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(remoteCell);
element = $('<span class="red-ui-diff-list-element"></span>').appendTo(remoteCell); element = $('<span class="red-ui-diff-list-element"></span>').appendTo(remoteCell);
var remotePosition = {x:remoteNode.x,y:remoteNode.y}; propertyElements['remote.position'] = RED.utils.createObjectElement({x:remoteNode.x,y:remoteNode.y},
if (remoteNode.hasOwnProperty('w')) {
remotePosition.w = remoteNode.w;
remotePosition.h = remoteNode.h;
}
propertyElements['remote.position'] = RED.utils.createObjectElement(remotePosition,
{ {
path: "position", path: "position",
exposeApi: true, exposeApi: true,
@@ -894,11 +883,11 @@ RED.diff = (function() {
} }
} }
} }
var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='w'&&p!=='h'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))}); var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))});
if (def.defaults) { if (def.defaults) {
properties = properties.concat(Object.keys(def.defaults)); properties = properties.concat(Object.keys(def.defaults));
} }
if (node.type !== 'tab' && node.type !== "group") { if (node.type !== 'tab') {
properties = properties.concat(['inputLabels','outputLabels']); properties = properties.concat(['inputLabels','outputLabels']);
} }
if ( ((localNode && localNode.hasOwnProperty('icon')) || (remoteNode && remoteNode.hasOwnProperty('icon'))) && if ( ((localNode && localNode.hasOwnProperty('icon')) || (remoteNode && remoteNode.hasOwnProperty('icon'))) &&
@@ -1387,7 +1376,6 @@ RED.diff = (function() {
function mergeDiff(diff) { function mergeDiff(diff) {
//console.log(diff); //console.log(diff);
var selectedTab = RED.workspaces.active();
var appliedDiff = applyDiff(diff); var appliedDiff = applyDiff(diff);
var newConfig = appliedDiff.config; var newConfig = appliedDiff.config;
@@ -1438,7 +1426,6 @@ RED.diff = (function() {
RED.view.redraw(true); RED.view.redraw(true);
RED.palette.refresh(); RED.palette.refresh();
RED.workspaces.refresh(); RED.workspaces.refresh();
RED.workspaces.show(selectedTab, true);
RED.sidebar.config.refresh(); RED.sidebar.config.refresh();
} }

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,6 @@
var definition = { var definition = {
show: function(options) { show: function(options) {
var value = options.value; var value = options.value;
var onCancel = options.cancel;
var onComplete = options.complete; var onComplete = options.complete;
var type = "_buffer" var type = "_buffer"
if ($("script[data-template-name='"+type+"']").length === 0) { if ($("script[data-template-name='"+type+"']").length === 0) {
@@ -61,14 +60,12 @@
var trayOptions = { var trayOptions = {
title: options.title, title: options.title,
focusElement: options.focusElement,
width: "inherit", width: "inherit",
buttons: [ buttons: [
{ {
id: "node-dialog-cancel", id: "node-dialog-cancel",
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
if (onCancel) { onCancel(); }
RED.tray.close(); RED.tray.close();
} }
}, },
@@ -77,8 +74,7 @@
text: RED._("common.label.done"), text: RED._("common.label.done"),
class: "primary", class: "primary",
click: function() { click: function() {
bufferStringEditor.saveView(); onComplete(JSON.stringify(bufferBinValue));
if (onComplete) { onComplete(JSON.stringify(bufferBinValue),null,bufferStringEditor); }
RED.tray.close(); RED.tray.close();
} }
} }
@@ -90,20 +86,19 @@
} }
}, },
open: function(tray) { open: function(tray) {
var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
bufferStringEditor = RED.editor.createEditor({ bufferStringEditor = RED.editor.createEditor({
id: 'red-ui-editor-type-buffer-str', id: 'red-ui-editor-type-buffer-str',
value: value||"", value: "",
stateId: RED.editor.generateViewStateId("buffer", options, ""),
focus: true,
mode:"ace/mode/text" mode:"ace/mode/text"
}); });
bufferStringEditor.getSession().setValue(value||"",-1);
bufferBinEditor = RED.editor.createEditor({ bufferBinEditor = RED.editor.createEditor({
id: 'red-ui-editor-type-buffer-bin', id: 'red-ui-editor-type-buffer-bin',
value: "", value: "",
stateId: false,
focus: false,
mode:"ace/mode/text", mode:"ace/mode/text",
readOnly: true readOnly: true
}); });

View File

@@ -1,115 +0,0 @@
/**
* 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.
**/
/**
* @namespace RED.editor.codeEditor
*/
RED.editor.codeEditor = (function() {
const MONACO = "monaco";
const ACE = "ace";
const defaultEditor = MONACO;
const DEFAULT_SETTINGS = { lib: defaultEditor, options: {} };
var selectedCodeEditor = null;
var initialised = false;
function init() {
var codeEditorSettings = RED.editor.codeEditor.settings;
var editorChoice = codeEditorSettings.lib === MONACO ? MONACO : ACE;
try {
var browser = RED.utils.getBrowserInfo();
selectedCodeEditor = RED.editor.codeEditor[editorChoice];
//fall back to default code editor if there are any issues
if (!selectedCodeEditor || (editorChoice === MONACO && (browser.ie || !window.monaco))) {
selectedCodeEditor = RED.editor.codeEditor[defaultEditor];
}
initialised = selectedCodeEditor.init();
} catch (error) {
selectedCodeEditor = null;
console.warn("Problem initialising '" + editorChoice + "' code editor", error);
}
if(!initialised) {
selectedCodeEditor = RED.editor.codeEditor[defaultEditor];
initialised = selectedCodeEditor.init();
}
$('<div id="red-ui-image-drop-target"><div data-i18n="[append]workspace.dropImageHere"><i class="fa fa-download"></i><br></div></div>').appendTo('#red-ui-editor');
$("#red-ui-image-drop-target").hide();
}
function create(options) {
//TODO: (quandry - for consideration)
// Below, I had to create a hidden element if options.id || options.element is not in the DOM
// I have seen 1 node calling `this.editor = RED.editor.createEditor()` with an
// invalid (non existing html element selector) (e.g. node-red-contrib-components does this)
// This causes monaco to throw an error when attempting to hook up its events to the dom & the rest of the 'oneditperapre'
// code is thus skipped.
// In ACE mode, creating an ACE editor (with an invalid ID) allows the editor to be created (but obviously there is no UI)
// Because one (or more) contrib nodes have left this bad code in place, how would we handle this?
// For compatibility, I have decided to create a hidden element so that at least an editor is created & errors do not occur.
// IMO, we should warn and exit as it is a coding error by the contrib author.
if (!options) {
console.warn("createEditor() options are missing");
options = {};
}
var editor = null;
if (this.editor.type === MONACO) {
// compatibility (see above note)
if (!options.element && !options.id) {
options.id = 'node-backwards-compatability-dummy-editor';
}
options.element = options.element || $("#" + options.id)[0];
if (!options.element) {
console.warn("createEditor() options.element or options.id is not valid", options);
$("#dialog-form").append('<div id="' + options.id + '" style="display: none;" />');
}
editor = this.editor.create(options);
} else {
editor = this.editor.create(options);//fallback to ACE
}
if (options.mode === "ace/mode/markdown") {
RED.editor.customEditTypes['_markdown'].postInit(editor, options);
}
return editor;
}
return {
init: init,
/**
* Get editor settings object
* @memberof RED.editor.codeEditor
*/
get settings() {
return RED.settings.get('codeEditor') || DEFAULT_SETTINGS;
},
/**
* Get user selected code editor
* @return {string} Returns
* @memberof RED.editor.codeEditor
*/
get editor() {
return selectedCodeEditor;
},
/**
* Create a editor ui component
* @param {object} options - the editor options
* @memberof RED.editor.codeEditor
*/
create: create
}
})();

View File

@@ -1,205 +0,0 @@
/*
* 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.
**/
/**
* @namespace RED.editor.codeEditor.ace
*/
RED.editor.codeEditor.ace = (function() {
const type = "ace";
var initialised = false;
var initOptions = {};
function init(options) {
initOptions = options || {};
initialised = true;
return initialised;
}
function create(options) {
var editorSettings = RED.editor.codeEditor.settings || {};
var el = options.element || $("#"+options.id)[0];
var toolbarRow = $("<div>").appendTo(el);
el = $("<div>").appendTo(el).addClass("red-ui-editor-text-container")[0];
var editor = window.ace.edit(el);
editor.setTheme(editorSettings.theme || initOptions.theme || "ace/theme/tomorrow");
var session = editor.getSession();
session.on("changeAnnotation", function () {
var annotations = session.getAnnotations() || [];
var i = annotations.length;
var len = annotations.length;
while (i--) {
if (/doctype first\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); }
else if (/Unexpected End of file\. Expected/.test(annotations[i].text)) { annotations.splice(i, 1); }
}
if (len > annotations.length) { session.setAnnotations(annotations); }
});
if (options.mode) {
session.setMode(options.mode);
}
if (options.foldStyle) {
session.setFoldStyle(options.foldStyle);
} else {
session.setFoldStyle('markbeginend');
}
if (options.options) {
editor.setOptions(options.options);
} else {
editor.setOptions({
enableBasicAutocompletion:true,
enableSnippets:true,
tooltipFollowsMouse: false
});
}
if (options.readOnly) {
editor.setOption('readOnly',options.readOnly);
editor.container.classList.add("ace_read-only");
}
if (options.hasOwnProperty('lineNumbers')) {
editor.renderer.setOption('showGutter',options.lineNumbers);
}
editor.$blockScrolling = Infinity;
if (options.value) {
session.setValue(options.value,-1);
}
if (options.globals) {
setTimeout(function() {
if (!!session.$worker) {
session.$worker.send("setOptions", [{globals: options.globals, maxerr:1000}]);
}
},100);
}
if (!options.stateId && options.stateId !== false) {
options.stateId = RED.editor.generateViewStateId("ace", options, (options.mode || options.title).split("/").pop());
}
if (options.mode === 'ace/mode/markdown') {
$(el).addClass("red-ui-editor-text-container-toolbar");
editor.toolbar = RED.editor.customEditTypes['_markdown'].buildToolbar(toolbarRow,editor);
if (options.expandable !== false) {
var expandButton = $('<button type="button" class="red-ui-button" style="float: right;"><i class="fa fa-expand"></i></button>').appendTo(editor.toolbar);
RED.popover.tooltip(expandButton, RED._("markdownEditor.expand"));
expandButton.on("click", function(e) {
e.preventDefault();
var value = editor.getValue();
RED.editor.editMarkdown({
value: value,
width: "Infinity",
stateId: options.stateId,
focus: true,
cancel: function () {
editor.focus();
},
complete: function(v,cursor) {
editor.setValue(v, -1);
setTimeout(function() {
editor.restoreView();
editor.focus();
},300);
}
})
});
}
var helpButton = $('<button type="button" class="red-ui-editor-text-help red-ui-button red-ui-button-small"><i class="fa fa-question"></i></button>').appendTo($(el).parent());
RED.popover.create({
target: helpButton,
trigger: 'click',
size: "small",
direction: "left",
content: RED._("markdownEditor.format"),
autoClose: 50
});
session.setUseWrapMode(true);
}
editor._destroy = editor.destroy;
editor.destroy = function() {
try {
editor.saveView();
editor._initState = null;
this._destroy();
} catch (e) { }
$(el).remove();
$(toolbarRow).remove();
}
editor.on("blur", function () {
editor.focusMemory = false;
editor.saveView();
})
editor.on("focus", function () {
if (editor._initState) {
editor.restoreView(editor._initState);
editor._initState = null;
}
})
editor.getView = function () {
var session = editor.getSession();
return {
selection: session.selection.toJSON(),
scrollTop: session.getScrollTop(),
scrollLeft: session.getScrollLeft(),
options: session.getOptions()
}
}
editor.saveView = function () {
if (!options.stateId) { return; } //only possible if created with a unique stateId
window._editorStateAce = window._editorStateAce || {};
var state = editor.getView();
window._editorStateAce[options.stateId] = state;
return state;
}
editor.restoreView = function (state) {
if (!options.stateId) { return; } //only possible if created with a unique stateId
window._editorStateAce = window._editorStateAce || {};
var _state = state || window._editorStateAce[options.stateId];
if (!_state) { return; } //no view state available
try {
var session = editor.getSession();
session.setOptions(_state.options);
session.selection.fromJSON(_state.selection);
session.setScrollTop(_state.scrollTop);
session.setScrollLeft(_state.scrollLeft);
editor._initState = _state;
} catch (error) {
delete window._editorStateMonaco[options.stateId];
}
};
editor.restoreView();
editor.type = type;
return editor;
}
return {
/**
* Editor type
* @memberof RED.editor.codeEditor.ace
*/
get type() { return type; },
/**
* Editor initialised
* @memberof RED.editor.codeEditor.ace
*/
get initialised() { return initialised; },
/**
* Initialise code editor
* @param {object} options - initialisation options
* @memberof RED.editor.codeEditor.ace
*/
init: init,
/**
* Create a code editor
* @param {object} options - the editor options
* @memberof RED.editor.codeEditor.ace
*/
create: create
}
})();

View File

@@ -1,625 +0,0 @@
RED.editor.envVarList = (function() {
var currentLocale = 'en-US';
var DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred','jsonata'];
/**
* Create env var edit interface
* @param container - container
* @param node - subflow node
*/
function buildPropertiesList(envContainer, node) {
var isTemplateNode = (node.type === "subflow");
envContainer
.css({
'min-height':'150px',
'min-width':'450px'
})
.editableList({
header: isTemplateNode?$('<div><div><div></div><div data-i18n="common.label.name"></div><div data-i18n="editor-tab.defaultValue"></div><div></div></div></div>'):undefined,
addItem: function(container, i, opt) {
// If this is an instance node, these are properties unique to
// this instance - ie opt.parent will not be defined.
if (isTemplateNode) {
container.addClass("red-ui-editor-subflow-env-editable")
}
var envRow = $('<div/>').appendTo(container);
var nameField = null;
var valueField = null;
nameField = $('<input/>', {
class: "node-input-env-name",
type: "text",
placeholder: RED._("common.label.name")
}).attr("autocomplete","disable").appendTo(envRow).val(opt.name);
valueField = $('<input/>',{
style: "width:100%",
class: "node-input-env-value",
type: "text",
}).attr("autocomplete","disable").appendTo(envRow);
var types = (opt.ui && opt.ui.opts && opt.ui.opts.types);
if (!types) {
types = isTemplateNode ? DEFAULT_ENV_TYPE_LIST : DEFAULT_ENV_TYPE_LIST_INC_CRED;
}
valueField.typedInput({default:'str',types:types});
valueField.typedInput('type', opt.type);
if (opt.type === "cred") {
if (opt.value) {
valueField.typedInput('value', opt.value);
} else if (node.credentials && node.credentials[opt.name]) {
valueField.typedInput('value', node.credentials[opt.name]);
} else if (node.credentials && node.credentials['has_'+opt.name]) {
valueField.typedInput('value', "__PWRD__");
} else {
valueField.typedInput('value', "");
}
} else {
valueField.typedInput('value', opt.value);
}
opt.nameField = nameField;
opt.valueField = valueField;
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(envRow);
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
actionButton.on("click", function(evt) {
evt.preventDefault();
removeTip.close();
container.parent().addClass("red-ui-editableList-item-deleting")
container.fadeOut(300, function() {
envContainer.editableList('removeItem',opt);
});
});
if (isTemplateNode) {
// Add the UI customisation row
// if `opt.ui` does not exist, then apply defaults. If these
// defaults do not change then they will get stripped off
// before saving.
if (opt.type === 'cred') {
opt.ui = opt.ui || {
icon: "",
type: "cred"
}
opt.ui.type = "cred";
} else {
opt.ui = opt.ui || {
icon: "",
type: "input",
opts: {types:DEFAULT_ENV_TYPE_LIST}
}
}
opt.ui.label = opt.ui.label || {};
opt.ui.type = opt.ui.type || "input";
if ((opt.ui.type === "cred") &&
opt.ui.opts &&
opt.ui.opts.types) {
opt.ui.type = "input";
}
var uiRow = $('<div/>').appendTo(container).hide();
// save current info for reverting on cancel
// var copy = $.extend(true, {}, ui);
$('<a href="#"><i class="fa fa-angle-right"></a>').prependTo(envRow).on("click", function (evt) {
evt.preventDefault();
if ($(this).hasClass('expanded')) {
uiRow.slideUp();
$(this).removeClass('expanded');
} else {
uiRow.slideDown();
$(this).addClass('expanded');
}
});
buildEnvEditRow(uiRow, opt.ui, nameField, valueField);
nameField.trigger('change');
}
},
sortable: ".red-ui-editableList-item-handle",
removable: false
});
var parentEnv = {};
var envList = [];
if (/^subflow:/.test(node.type)) {
var subflowDef = RED.nodes.subflow(node.type.substring(8));
if (subflowDef.env) {
subflowDef.env.forEach(function(env) {
var item = {
name:env.name,
parent: {
type: env.type,
value: env.value,
ui: env.ui
}
}
envList.push(item);
parentEnv[env.name] = item;
})
}
}
if (node.env) {
for (var i = 0; i < node.env.length; i++) {
var env = node.env[i];
if (parentEnv.hasOwnProperty(env.name)) {
parentEnv[env.name].type = env.type;
parentEnv[env.name].value = env.value;
} else {
envList.push({
name: env.name,
type: env.type,
value: env.value,
ui: env.ui
});
}
}
}
envList.forEach(function(env) {
if (env.parent && env.parent.ui && env.parent.ui.type === 'hide') {
return;
}
if (!isTemplateNode && env.parent) {
return;
}
envContainer.editableList('addItem', JSON.parse(JSON.stringify(env)));
});
}
/**
* Create UI edit interface for environment variable
* @param container - container
* @param env - env var definition
* @param nameField - name field of env var
* @param valueField - value field of env var
*/
function buildEnvEditRow(container, ui, nameField, valueField) {
container.addClass("red-ui-editor-subflow-env-ui-row")
var topRow = $('<div></div>').appendTo(container);
$('<div></div>').appendTo(topRow);
$('<div>').text(RED._("editor.icon")).appendTo(topRow);
$('<div>').text(RED._("editor.label")).appendTo(topRow);
$('<div>').text(RED._("editor.inputType")).appendTo(topRow);
var row = $('<div></div>').appendTo(container);
$('<div><i class="red-ui-editableList-item-handle fa fa-bars"></i></div>').appendTo(row);
var typeOptions = {
'input': {types:DEFAULT_ENV_TYPE_LIST},
'select': {opts:[]},
'spinner': {},
'cred': {}
};
if (ui.opts) {
typeOptions[ui.type] = ui.opts;
} else {
// Pick up the default values if not otherwise provided
ui.opts = typeOptions[ui.type];
}
var iconCell = $('<div></div>').appendTo(row);
var iconButton = $('<a href="#"></a>').appendTo(iconCell);
iconButton.on("click", function(evt) {
evt.preventDefault();
var icon = ui.icon || "";
var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) {
iconButton.empty();
var path = newIcon || "";
var newPath = RED.utils.separateIconPath(path);
if (newPath) {
$('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
}
ui.icon = path;
});
})
if (ui.icon) {
var newPath = RED.utils.separateIconPath(ui.icon);
$('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
}
var labelCell = $('<div></div>').appendTo(row);
var label = ui.label && ui.label[currentLocale] || "";
var labelInput = $('<input type="text">').val(label).appendTo(labelCell);
ui.labelField = labelInput;
labelInput.on('change', function(evt) {
ui.label = ui.label || {};
var val = $(this).val().trim();
if (val === "") {
delete ui.label[currentLocale];
} else {
ui.label[currentLocale] = val;
}
})
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelCell);
RED.popover.tooltip(labelIcon,function() {
var langs = Object.keys(ui.label);
var content = $("<div>");
if (langs.indexOf(currentLocale) === -1) {
langs.push(currentLocale);
langs.sort();
}
langs.forEach(function(l) {
var row = $('<div>').appendTo(content);
$('<span>').css({display:"inline-block",width:"120px"}).text(RED._("languages."+l)+(l===currentLocale?"*":"")).appendTo(row);
$('<span>').text(ui.label[l]||"").appendTo(row);
});
return content;
})
nameField.on('change',function(evt) {
labelInput.attr("placeholder",$(this).val())
});
var inputCell = $('<div></div>').appendTo(row);
var inputCellInput = $('<input type="text">').css("width","100%").appendTo(inputCell);
if (ui.type === "input") {
inputCellInput.val(ui.opts.types.join(","));
}
var checkbox;
var selectBox;
inputCellInput.typedInput({
types: [
{
value:"input",
label:RED._("editor.inputs.input"), icon:"fa fa-i-cursor",showLabel:false,multiple:true,options:[
{value:"str",label:RED._("editor.types.str"),icon:"red/images/typedInput/az.svg"},
{value:"num",label:RED._("editor.types.num"),icon:"red/images/typedInput/09.svg"},
{value:"bool",label:RED._("editor.types.bool"),icon:"red/images/typedInput/bool.svg"},
{value:"json",label:RED._("editor.types.json"),icon:"red/images/typedInput/json.svg"},
{value: "bin",label: RED._("editor.types.bin"),icon: "red/images/typedInput/bin.svg"},
{value: "env",label: RED._("editor.types.env"),icon: "red/images/typedInput/env.svg"},
{value: "cred",label: RED._("editor.types.cred"),icon: "fa fa-lock"}
],
default: DEFAULT_ENV_TYPE_LIST,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-i-cursor"></i></span>').appendTo(input);
if (value.length) {
value.forEach(function(v) {
if (!/^fa /.test(v.icon)) {
$('<img>',{src:v.icon,style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
} else {
var s = $('<span>',{style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
$("<i>",{class: v.icon}).appendTo(s);
}
})
} else {
$('<span class="red-ui-editor-subflow-env-input-type-placeholder"></span>').text(RED._("editor.selectType")).appendTo(input);
}
}
},
{
value: "cred",
label: RED._("typedInput.type.cred"), icon:"fa fa-lock", showLabel: false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type">').css({
"border-top-right-radius": "4px",
"border-bottom-right-radius": "4px"
}).appendTo(container);
$('<div class="placeholder-input">').html("&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;").appendTo(innerContainer);
}
},
{
value:"select",
label:RED._("editor.inputs.select"), icon:"fa fa-tasks",showLabel:false,
valueLabel: function(container,value) {
container.css("padding","0");
selectBox = $('<select></select>').appendTo(container);
if (ui.opts && Array.isArray(ui.opts.opts)) {
ui.opts.opts.forEach(function(o) {
var label = lookupLabel(o.l, o.l["en-US"]||o.v, currentLocale);
// $('<option>').val((o.t||'str')+":"+o.v).text(label).appendTo(selectBox);
$('<option>').val(o.v).text(label).appendTo(selectBox);
})
}
selectBox.on('change', function(evt) {
var v = selectBox.val();
// var parts = v.split(":");
// var t = parts.shift();
// v = parts.join(":");
//
// valueField.typedInput("type",'str')
valueField.typedInput("value",v)
});
selectBox.val(valueField.typedInput("value"));
// selectBox.val(valueField.typedInput('type')+":"+valueField.typedInput("value"));
},
expand: {
icon: "fa-caret-down",
minWidth: 400,
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
var optList = $('<ol>').appendTo(content).editableList({
header:$("<div><div>"+RED._("editor.select.label")+"</div><div>"+RED._("editor.select.value")+"</div></div>"),
addItem: function(row,index,itemData) {
var labelDiv = $('<div>').appendTo(row);
var label = lookupLabel(itemData.l, "", currentLocale);
itemData.label = $('<input type="text">').val(label).appendTo(labelDiv);
itemData.label.on('keydown', function(evt) {
if (evt.keyCode === 13) {
itemData.input.focus();
evt.preventDefault();
}
});
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelDiv);
RED.popover.tooltip(labelIcon,function() {
return currentLocale;
})
itemData.input = $('<input type="text">').val(itemData.v).appendTo(row);
// Problem using a TI here:
// - this is in a popout panel
// - clicking the expand button in the TI will close the parent edit tray
// and open the type editor.
// - but it leaves the popout panel over the top.
// - there is no way to get back to the popout panel after closing the type editor
//.typedInput({default:itemData.t||'str', types:DEFAULT_ENV_TYPE_LIST});
itemData.input.on('keydown', function(evt) {
if (evt.keyCode === 13) {
// Enter or Tab
var index = optList.editableList('indexOf',itemData);
var length = optList.editableList('length');
if (index + 1 === length) {
var newItem = {};
optList.editableList('addItem',newItem);
setTimeout(function() {
if (newItem.label) {
newItem.label.focus();
}
},100)
} else {
var nextItem = optList.editableList('getItemAt',index+1);
if (nextItem.label) {
nextItem.label.focus()
}
}
evt.preventDefault();
}
});
},
sortable: true,
removable: true,
height: 160
})
if (ui.opts.opts.length > 0) {
ui.opts.opts.forEach(function(o) {
optList.editableList('addItem',$.extend(true,{},o))
})
} else {
optList.editableList('addItem',{})
}
return {
onclose: function() {
var items = optList.editableList('items');
var vals = [];
items.each(function (i,el) {
var data = el.data('data');
var l = data.label.val().trim();
var v = data.input.val();
// var t = data.input.typedInput('type');
// var v = data.input.typedInput('value');
if (l.length > 0) {
data.l = data.l || {};
data.l[currentLocale] = l;
}
data.v = v;
if (l.length > 0 || v.length > 0) {
var val = {l:data.l,v:data.v};
// if (t !== 'str') {
// val.t = t;
// }
vals.push(val);
}
});
ui.opts.opts = vals;
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"checkbox",
label:RED._("editor.inputs.checkbox"), icon:"fa fa-check-square-o",showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
checkbox = $('<input type="checkbox">').appendTo(container);
checkbox.on('change', function(evt) {
valueField.typedInput('value',$(this).prop('checked')?"true":"false");
})
checkbox.prop('checked',valueField.typedInput('value')==="true");
}
},
{
value:"spinner",
label:RED._("editor.inputs.spinner"), icon:"fa fa-sort-numeric-asc", showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-sort-numeric-asc"></i></span>').appendTo(input);
var min = ui.opts && ui.opts.min;
var max = ui.opts && ui.opts.max;
var label = "";
if (min !== undefined && max !== undefined) {
label = Math.min(min,max)+" - "+Math.max(min,max);
} else if (min !== undefined) {
label = "> "+min;
} else if (max !== undefined) {
label = "< "+max;
}
$('<span>').css("margin-left","15px").text(label).appendTo(input);
},
expand: {
icon: "fa-caret-down",
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
content.css("padding","8px 5px")
var min = ui.opts.min;
var max = ui.opts.max;
var minInput = $('<input type="number" style="margin-bottom:0; width:60px">');
minInput.val(min);
var maxInput = $('<input type="number" style="margin-bottom:0; width:60px">');
maxInput.val(max);
$('<div class="form-row" style="margin-bottom:3px"><label>'+RED._("editor.spinner.min")+'</label></div>').append(minInput).appendTo(content);
$('<div class="form-row" style="margin-bottom:0"><label>'+RED._("editor.spinner.max")+'</label></div>').append(maxInput).appendTo(content);
return {
onclose: function() {
var min = minInput.val().trim();
var max = maxInput.val().trim();
if (min !== "") {
ui.opts.min = parseInt(min);
} else {
delete ui.opts.min;
}
if (max !== "") {
ui.opts.max = parseInt(max);
} else {
delete ui.opts.max;
}
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"none",
label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
},
{
value:"hide",
label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
}
],
default: 'none'
}).on("typedinputtypechange", function(evt,type) {
ui.type = $(this).typedInput("type");
ui.opts = typeOptions[ui.type];
if (ui.type === 'input') {
// In the case of 'input' type, the typedInput uses the multiple-option
// mode. Its value needs to be set to a comma-separately list of the
// selected options.
inputCellInput.typedInput('value',ui.opts.types.join(","))
} else {
// No other type cares about `value`, but doing this will
// force a refresh of the label now that `ui.opts` has
// been updated.
inputCellInput.typedInput('value',Date.now())
}
switch (ui.type) {
case 'input':
valueField.typedInput('types',ui.opts.types);
break;
case 'select':
valueField.typedInput('types',['str']);
break;
case 'checkbox':
valueField.typedInput('types',['bool']);
break;
case 'spinner':
valueField.typedInput('types',['num']);
break;
case 'cred':
valueField.typedInput('types',['cred']);
break;
default:
valueField.typedInput('types',DEFAULT_ENV_TYPE_LIST)
}
if (ui.type === 'checkbox') {
valueField.typedInput('type','bool');
} else if (ui.type === 'spinner') {
valueField.typedInput('type','num');
}
if (ui.type !== 'checkbox') {
checkbox = null;
}
}).on("change", function(evt,type) {
if (ui.type === 'input') {
var types = inputCellInput.typedInput('value');
ui.opts.types = (types === "") ? ["str"] : types.split(",");
valueField.typedInput('types',ui.opts.types);
}
});
valueField.on("change", function(evt) {
if (checkbox) {
checkbox.prop('checked',$(this).typedInput('value')==="true")
}
})
// Set the input to the right type. This will trigger the 'typedinputtypechange'
// event handler (just above ^^) to update the value if needed
inputCellInput.typedInput('type',ui.type)
}
function setLocale(l, list) {
currentLocale = l;
if (list) {
var items = list.editableList("items");
items.each(function (i, item) {
var entry = $(this).data('data');
var labelField = entry.ui.labelField;
labelField.val(lookupLabel(entry.ui.label, "", currentLocale));
if (labelField.timeout) {
clearTimeout(labelField.timeout);
delete labelField.timeout;
}
labelField.addClass("input-updated");
labelField.timeout = setTimeout(function() {
delete labelField.timeout
labelField.removeClass("input-updated");
},3000);
});
}
}
/**
* Lookup text for specific locale
* @param labels - dict of labels
* @param defaultLabel - fallback label if not found
* @param locale - target locale
* @returns {string} text for specified locale
*/
function lookupLabel(labels, defaultLabel, locale) {
if (labels) {
if (labels[locale]) {
return labels[locale];
}
if (locale) {
var lang = locale.substring(0, 2);
if (labels[lang]) {
return labels[lang];
}
}
}
return defaultLabel;
}
return {
create: buildPropertiesList,
setLocale: setLocale,
lookupLabel: lookupLabel,
DEFAULT_ENV_TYPE_LIST: DEFAULT_ENV_TYPE_LIST,
DEFAULT_ENV_TYPE_LIST_INC_CRED: DEFAULT_ENV_TYPE_LIST_INC_CRED
}
})();

View File

@@ -50,7 +50,6 @@
show: function(options) { show: function(options) {
var expressionTestCacheId = options.parent||"_"; var expressionTestCacheId = options.parent||"_";
var value = options.value; var value = options.value;
var onCancel = options.cancel;
var onComplete = options.complete; var onComplete = options.complete;
var type = "_expression" var type = "_expression"
if ($("script[data-template-name='"+type+"']").length === 0) { if ($("script[data-template-name='"+type+"']").length === 0) {
@@ -64,14 +63,12 @@
var trayOptions = { var trayOptions = {
title: options.title, title: options.title,
focusElement: options.focusElement,
width: "inherit", width: "inherit",
buttons: [ buttons: [
{ {
id: "node-dialog-cancel", id: "node-dialog-cancel",
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
if(onCancel) { onCancel(); }
RED.tray.close(); RED.tray.close();
} }
}, },
@@ -81,8 +78,7 @@
class: "primary", class: "primary",
click: function() { click: function() {
$("#red-ui-editor-type-expression-help").text(""); $("#red-ui-editor-type-expression-help").text("");
expressionEditor.saveView(); onComplete(expressionEditor.getValue());
if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(),expressionEditor); }
RED.tray.close(); RED.tray.close();
} }
} }
@@ -114,8 +110,6 @@
id: 'red-ui-editor-type-expression', id: 'red-ui-editor-type-expression',
value: "", value: "",
mode:"ace/mode/jsonata", mode:"ace/mode/jsonata",
stateId: options.stateId,
focus: true,
options: { options: {
enableBasicAutocompletion:true, enableBasicAutocompletion:true,
enableSnippets:true, enableSnippets:true,
@@ -127,75 +121,73 @@
var currentFunctionMarker = null; var currentFunctionMarker = null;
expressionEditor.getSession().setValue(value||"",-1); expressionEditor.getSession().setValue(value||"",-1);
//ace only (monaco has jsonata tokeniser) expressionEditor.on("changeSelection", function() {
if(expressionEditor.type == "ace") { var c = expressionEditor.getCursorPosition();
expressionEditor.on("changeSelection", function() { var token = expressionEditor.getSession().getTokenAt(c.row,c.column);
var c = expressionEditor.getCursorPosition(); if (token !== currentToken || (token && /paren/.test(token.type) && c.column !== currentTokenPos)) {
var token = expressionEditor.getSession().getTokenAt(c.row,c.column); currentToken = token;
if (token !== currentToken || (token && /paren/.test(token.type) && c.column !== currentTokenPos)) { var r,p;
currentToken = token; var scopedFunction = null;
var r,p; if (token && token.type === 'keyword') {
var scopedFunction = null; r = c.row;
if (token && token.type === 'keyword') { scopedFunction = token;
} else {
var depth = 0;
var next = false;
if (token) {
if (token.type === 'paren.rparen') {
// If this is a block of parens ')))', set
// depth to offset against the cursor position
// within the block
currentTokenPos = c.column;
depth = c.column - (token.start + token.value.length);
}
r = c.row; r = c.row;
scopedFunction = token; p = token.index;
} else { } else {
var depth = 0; r = c.row-1;
var next = false; p = -1;
if (token) {
if (token.type === 'paren.rparen') {
// If this is a block of parens ')))', set
// depth to offset against the cursor position
// within the block
currentTokenPos = c.column;
depth = c.column - (token.start + token.value.length);
}
r = c.row;
p = token.index;
} else {
r = c.row-1;
p = -1;
}
while ( scopedFunction === null && r > -1) {
var rowTokens = expressionEditor.getSession().getTokens(r);
if (p === -1) {
p = rowTokens.length-1;
}
while (p > -1) {
var type = rowTokens[p].type;
if (next) {
if (type === 'keyword') {
scopedFunction = rowTokens[p];
// console.log("HIT",scopedFunction);
break;
}
next = false;
}
if (type === 'paren.lparen') {
depth-=rowTokens[p].value.length;
} else if (type === 'paren.rparen') {
depth+=rowTokens[p].value.length;
}
if (depth < 0) {
next = true;
depth = 0;
}
// console.log(r,p,depth,next,rowTokens[p]);
p--;
}
if (!scopedFunction) {
r--;
}
}
} }
expressionEditor.session.removeMarker(currentFunctionMarker); while ( scopedFunction === null && r > -1) {
if (scopedFunction) { var rowTokens = expressionEditor.getSession().getTokens(r);
//console.log(token,.map(function(t) { return t.type})); if (p === -1) {
funcSelect.val(scopedFunction.value).trigger("change"); p = rowTokens.length-1;
}
while (p > -1) {
var type = rowTokens[p].type;
if (next) {
if (type === 'keyword') {
scopedFunction = rowTokens[p];
// console.log("HIT",scopedFunction);
break;
}
next = false;
}
if (type === 'paren.lparen') {
depth-=rowTokens[p].value.length;
} else if (type === 'paren.rparen') {
depth+=rowTokens[p].value.length;
}
if (depth < 0) {
next = true;
depth = 0;
}
// console.log(r,p,depth,next,rowTokens[p]);
p--;
}
if (!scopedFunction) {
r--;
}
} }
} }
}); expressionEditor.session.removeMarker(currentFunctionMarker);
} if (scopedFunction) {
//console.log(token,.map(function(t) { return t.type}));
funcSelect.val(scopedFunction.value).trigger("change");
}
}
});
dialogForm.i18n(); dialogForm.i18n();
$("#red-ui-editor-type-expression-func-insert").on("click", function(e) { $("#red-ui-editor-type-expression-func-insert").on("click", function(e) {
e.preventDefault(); e.preventDefault();
@@ -239,8 +231,6 @@
testDataEditor = RED.editor.createEditor({ testDataEditor = RED.editor.createEditor({
id: 'red-ui-editor-type-expression-test-data', id: 'red-ui-editor-type-expression-test-data',
value: expressionTestCache[expressionTestCacheId] || '{\n "payload": "hello world"\n}', value: expressionTestCache[expressionTestCacheId] || '{\n "payload": "hello world"\n}',
stateId: false,
focus: false,
mode:"ace/mode/json", mode:"ace/mode/json",
lineNumbers: false lineNumbers: false
}); });
@@ -255,10 +245,7 @@
var currentExpression = expressionEditor.getValue(); var currentExpression = expressionEditor.getValue();
var expr; var expr;
var usesContext = false; var usesContext = false;
var usesEnv = false; var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
var usesMoment = false;
var usesClone = false;
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode); $(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
try { try {
expr = jsonata(currentExpression); expr = jsonata(currentExpression);
@@ -270,18 +257,6 @@
usesContext = true; usesContext = true;
return null; return null;
}); });
expr.assign("env", function(name) {
usesEnv = true;
return null;
});
expr.assign("moment", function(name) {
usesMoment = true;
return null;
});
expr.assign("clone", function(name) {
usesClone = true;
return null;
});
} catch(err) { } catch(err) {
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1); testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
return; return;
@@ -299,18 +274,6 @@
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1); testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
return; return;
} }
if (usesEnv) {
testResultEditor.setValue(RED._("expressionEditor.errors.env-unsupported"),-1);
return;
}
if (usesMoment) {
testResultEditor.setValue(RED._("expressionEditor.errors.moment-unsupported"),-1);
return;
}
if (usesClone) {
testResultEditor.setValue(RED._("expressionEditor.errors.clone-unsupported"),-1);
return;
}
var formattedResult; var formattedResult;
if (result !== undefined) { if (result !== undefined) {
@@ -337,8 +300,6 @@
testResultEditor = RED.editor.createEditor({ testResultEditor = RED.editor.createEditor({
id: 'red-ui-editor-type-expression-test-result', id: 'red-ui-editor-type-expression-test-result',
value: "", value: "",
stateId: false,
focus: false,
mode:"ace/mode/json", mode:"ace/mode/json",
lineNumbers: false, lineNumbers: false,
readOnly: true readOnly: true
@@ -382,7 +343,6 @@
} }
expressionEditor.destroy(); expressionEditor.destroy();
testDataEditor.destroy(); testDataEditor.destroy();
testResultEditor.destroy();
}, },
show: function() {} show: function() {}
} }

View File

@@ -1,99 +0,0 @@
RED.editor.iconPicker = (function() {
function showIconPicker(container, backgroundColor, iconPath, faOnly, done) {
var picker = $('<div class="red-ui-icon-picker">');
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(picker);
searchInput = $('<input type="text">').attr("placeholder",RED._("editor.searchIcons")).appendTo(searchDiv).searchBox({
delay: 50,
change: function() {
var searchTerm = $(this).val().trim();
if (searchTerm === "") {
iconList.find(".red-ui-icon-list-module").show();
iconList.find(".red-ui-icon-list-icon").show();
} else {
iconList.find(".red-ui-icon-list-module").hide();
iconList.find(".red-ui-icon-list-icon").each(function(i,n) {
if ($(n).data('icon').indexOf(searchTerm) === -1) {
$(n).hide();
} else {
$(n).show();
}
});
}
}
});
var row = $('<div>').appendTo(picker);
var iconList = $('<div class="red-ui-icon-list">').appendTo(picker);
var metaRow = $('<div class="red-ui-icon-meta"></div>').appendTo(picker);
var summary = $('<span>').appendTo(metaRow);
var resetButton = $('<button type="button" class="red-ui-button red-ui-button-small">'+RED._("editor.useDefault")+'</button>').appendTo(metaRow).on("click", function(e) {
e.preventDefault();
iconPanel.hide();
done(null);
});
if (!backgroundColor && faOnly) {
iconList.addClass("red-ui-icon-list-dark");
}
setTimeout(function() {
var iconSets = RED.nodes.getIconSets();
Object.keys(iconSets).forEach(function(moduleName) {
if (faOnly && (moduleName !== "font-awesome")) {
return;
}
var icons = iconSets[moduleName];
if (icons.length > 0) {
// selectIconModule.append($("<option></option>").val(moduleName).text(moduleName));
var header = $('<div class="red-ui-icon-list-module"></div>').text(moduleName).appendTo(iconList);
$('<i class="fa fa-cube"></i>').prependTo(header);
icons.forEach(function(icon) {
var iconDiv = $('<div>',{class:"red-ui-icon-list-icon"}).appendTo(iconList);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconDiv);
var icon_url = RED.settings.apiRootUrl+"icons/"+moduleName+"/"+icon;
iconDiv.data('icon',icon_url);
if (backgroundColor) {
nodeDiv.css({
'backgroundColor': backgroundColor
});
var borderColor = RED.utils.getDarkerColor(backgroundColor);
if (borderColor !== backgroundColor) {
nodeDiv.css('border-color',borderColor)
}
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
if (iconPath.module === moduleName && iconPath.file === icon) {
iconDiv.addClass("selected");
}
iconDiv.on("mouseover", function() {
summary.text(icon);
})
iconDiv.on("mouseout", function() {
summary.html("&nbsp;");
})
iconDiv.on("click", function() {
iconPanel.hide();
done(moduleName+"/"+icon);
})
})
}
});
setTimeout(function() {
spinner.remove();
},50);
},300);
var spinner = RED.utils.addSpinnerOverlay(iconList,true);
var iconPanel = RED.popover.panel(picker);
iconPanel.show({
target: container
})
picker.slideDown(100);
searchInput.trigger("focus");
}
return {
show: showIconPicker
}
})();

View File

@@ -21,7 +21,6 @@
var definition = { var definition = {
show: function(options) { show: function(options) {
var value = options.value; var value = options.value;
var onCancel = options.cancel;
var onComplete = options.complete; var onComplete = options.complete;
var type = "_js" var type = "_js"
if ($("script[data-template-name='"+type+"']").length === 0) { if ($("script[data-template-name='"+type+"']").length === 0) {
@@ -29,16 +28,16 @@
} }
RED.view.state(RED.state.EDITING); RED.view.state(RED.state.EDITING);
var expressionEditor; var expressionEditor;
var changeTimer;
var trayOptions = { var trayOptions = {
title: options.title, title: options.title,
focusElement: options.focusElement,
width: options.width||"inherit", width: options.width||"inherit",
buttons: [ buttons: [
{ {
id: "node-dialog-cancel", id: "node-dialog-cancel",
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
if (onCancel) { onCancel(); }
RED.tray.close(); RED.tray.close();
} }
}, },
@@ -47,8 +46,7 @@
text: RED._("common.label.done"), text: RED._("common.label.done"),
class: "primary", class: "primary",
click: function() { click: function() {
expressionEditor.saveView(); onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition());
if (onComplete) { onComplete(expressionEditor.getValue(), expressionEditor.getCursorPosition(), expressionEditor); }
RED.tray.close(); RED.tray.close();
} }
} }
@@ -64,12 +62,11 @@
expressionEditor.resize(); expressionEditor.resize();
}, },
open: function(tray) { open: function(tray) {
var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
expressionEditor = RED.editor.createEditor({ expressionEditor = RED.editor.createEditor({
id: 'node-input-js', id: 'node-input-js',
mode: options.mode || 'ace/mode/javascript', mode: options.mode || 'ace/mode/javascript',
stateId: options.stateId,
focus: true,
value: value, value: value,
globals: { globals: {
msg:true, msg:true,
@@ -84,19 +81,21 @@
clearTimeout: true, clearTimeout: true,
setInterval: true, setInterval: true,
clearInterval: true clearInterval: true
}, }
extraLibs: options.extraLibs
}); });
if (options.cursor && !expressionEditor._initState) { if (options.cursor) {
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
} }
dialogForm.i18n(); dialogForm.i18n();
setTimeout(function() {
expressionEditor.focus();
},300);
}, },
close: function() { close: function() {
expressionEditor.destroy();
if (options.onclose) { if (options.onclose) {
options.onclose(); options.onclose();
} }
expressionEditor.destroy();
}, },
show: function() {} show: function() {}
} }

View File

@@ -21,9 +21,7 @@
'<ul id="red-ui-editor-type-json-tabs"></ul>'+ '<ul id="red-ui-editor-type-json-tabs"></ul>'+
'<div id="red-ui-editor-type-json-tab-raw" class="red-ui-editor-type-json-tab-content hide">'+ '<div id="red-ui-editor-type-json-tab-raw" class="red-ui-editor-type-json-tab-content hide">'+
'<div class="form-row" style="margin-bottom: 3px; text-align: right;">'+ '<div class="form-row" style="margin-bottom: 3px; text-align: right;">'+
'<span class="button-group">'+ '<button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button>'+
'<button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button>'+
'<span class="button-group">'+
'</div>'+ '</div>'+
'<div class="form-row node-text-editor-row">'+ '<div class="form-row node-text-editor-row">'+
'<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>'+ '<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>'+
@@ -36,7 +34,7 @@
var activeTab; var activeTab;
function insertNewItem(parent,index,copyIndex,readOnly) { function insertNewItem(parent,index,copyIndex) {
var newValue = ""; var newValue = "";
if (parent.children.length > 0) { if (parent.children.length > 0) {
@@ -62,26 +60,26 @@
newKey = keyRoot+"-"+(keySuffix++); newKey = keyRoot+"-"+(keySuffix++);
} }
} }
var newItem = handleItem(newKey,newValue,parent.depth+1,parent,readOnly); var newItem = handleItem(newKey,newValue,parent.depth+1,parent);
parent.treeList.insertChildAt(newItem, index, true); parent.treeList.insertChildAt(newItem, index, true);
parent.treeList.expand(); parent.treeList.expand();
} }
function showObjectMenu(button,item,readOnly) { function showObjectMenu(button,item) {
var elementPos = button.offset(); var elementPos = button.offset();
var options = []; var options = [];
if (item.parent) { if (item.parent) {
options.push({id:"red-ui-editor-type-json-menu-insert-above", icon:"fa fa-toggle-up", label:RED._('jsonEditor.insertAbove'),onselect:function(){ options.push({id:"red-ui-editor-type-json-menu-insert-above", icon:"fa fa-toggle-up", label:RED._('jsonEditor.insertAbove'),onselect:function(){
var index = item.parent.children.indexOf(item); var index = item.parent.children.indexOf(item);
insertNewItem(item.parent,index,index,readOnly); insertNewItem(item.parent,index,index);
}}); }});
options.push({id:"red-ui-editor-type-json-menu-insert-below", icon:"fa fa-toggle-down", label:RED._('jsonEditor.insertBelow'),onselect:function(){ options.push({id:"red-ui-editor-type-json-menu-insert-below", icon:"fa fa-toggle-down", label:RED._('jsonEditor.insertBelow'),onselect:function(){
var index = item.parent.children.indexOf(item)+1; var index = item.parent.children.indexOf(item)+1;
insertNewItem(item.parent,index,index-1,readOnly); insertNewItem(item.parent,index,index-1);
}}); }});
} }
if (item.type === 'array' || item.type === 'object') { if (item.type === 'array' || item.type === 'object') {
options.push({id:"red-ui-editor-type-json-menu-add-child", icon:"fa fa-plus", label:RED._('jsonEditor.addItem'),onselect:function(){ options.push({id:"red-ui-editor-type-json-menu-add-child", icon:"fa fa-plus", label:RED._('jsonEditor.addItem'),onselect:function(){
insertNewItem(item,item.children.length,item.children.length-1,readOnly); insertNewItem(item,item.children.length,item.children.length-1);
}}); }});
} }
if (item.parent) { if (item.parent) {
@@ -123,7 +121,7 @@
newKey = keyRoot+"-"+(keySuffix++); newKey = keyRoot+"-"+(keySuffix++);
} }
} }
var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent,readOnly); var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent);
var index = item.parent.children.indexOf(item)+1; var index = item.parent.children.indexOf(item)+1;
item.parent.treeList.insertChildAt(newItem, index, true); item.parent.treeList.insertChildAt(newItem, index, true);
@@ -173,24 +171,24 @@
menuOptionMenu.show(); menuOptionMenu.show();
} }
function parseObject(obj,depth,parent,readOnly) { function parseObject(obj,depth,parent) {
var result = []; var result = [];
for (var prop in obj) { for (var prop in obj) {
if (obj.hasOwnProperty(prop)) { if (obj.hasOwnProperty(prop)) {
result.push(handleItem(prop,obj[prop],depth,parent,readOnly)); result.push(handleItem(prop,obj[prop],depth,parent));
} }
} }
return result; return result;
} }
function parseArray(obj,depth,parent,readOnly) { function parseArray(obj,depth,parent) {
var result = []; var result = [];
var l = obj.length; var l = obj.length;
for (var i=0;i<l;i++) { for (var i=0;i<l;i++) {
result.push(handleItem(i,obj[i],depth,parent,readOnly)); result.push(handleItem(i,obj[i],depth,parent));
} }
return result; return result;
} }
function handleItem(key,val,depth,parent,readOnly) { function handleItem(key,val,depth,parent) {
var item = {depth:depth, type: typeof val}; var item = {depth:depth, type: typeof val};
var container = $('<span class="red-ui-editor-type-json-editor-label">'); var container = $('<span class="red-ui-editor-type-json-editor-label">');
if (key != null) { if (key != null) {
@@ -206,14 +204,11 @@
if (parent && parent.type === "array") { if (parent && parent.type === "array") {
keyLabel.addClass("red-ui-editor-type-json-editor-label-array-key") keyLabel.addClass("red-ui-editor-type-json-editor-label-array-key")
} }
if(readOnly) {
keyLabel.addClass("readonly")
}
keyLabel.on("click", function(evt) { keyLabel.on("click", function(evt) {
if (item.parent.type === 'array') { if (item.parent.type === 'array') {
return; return;
} }
if (readOnly) { return; }
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
var w = Math.max(150,keyLabel.width()); var w = Math.max(150,keyLabel.width());
@@ -258,10 +253,10 @@
item.expanded = depth < 2; item.expanded = depth < 2;
item.type = "array"; item.type = "array";
item.deferBuild = depth >= 2; item.deferBuild = depth >= 2;
item.children = parseArray(val,depth+1,item,readOnly); item.children = parseArray(val,depth+1,item);
} else if (val !== null && item.type === "object") { } else if (val !== null && item.type === "object") {
item.expanded = depth < 2; item.expanded = depth < 2;
item.children = parseObject(val,depth+1,item,readOnly); item.children = parseObject(val,depth+1,item);
item.deferBuild = depth >= 2; item.deferBuild = depth >= 2;
} else { } else {
item.value = val; item.value = val;
@@ -292,11 +287,7 @@
// //
var orphanedChildren; var orphanedChildren;
var valueLabel = $('<span class="red-ui-editor-type-json-editor-label-value">').addClass(valClass).text(valValue).appendTo(container); var valueLabel = $('<span class="red-ui-editor-type-json-editor-label-value">').addClass(valClass).text(valValue).appendTo(container);
if (readOnly) {
valueLabel.addClass("readonly")
}
valueLabel.on("click", function(evt) { valueLabel.on("click", function(evt) {
if (readOnly) { return; }
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (valType === 'str') { if (valType === 'str') {
@@ -311,8 +302,8 @@
types:[ types:[
'str','num','bool', 'str','num','bool',
{value:"null",label:RED._("common.type.null"),hasValue:false}, {value:"null",label:RED._("common.type.null"),hasValue:false},
{value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.svg"}, {value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.png"},
{value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.svg"} {value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.png"}
], ],
default: valType default: valType
}); });
@@ -404,19 +395,17 @@
valueLabel.hide(); valueLabel.hide();
}) })
item.gutter = $('<span class="red-ui-editor-type-json-editor-item-gutter"></span>'); item.gutter = $('<span class="red-ui-editor-type-json-editor-item-gutter"></span>');
if(!readOnly) {
if (parent) {
$('<span class="red-ui-editor-type-json-editor-item-handle"><i class="fa fa-bars"></span>').appendTo(item.gutter);
} else {
$('<span></span>').appendTo(item.gutter);
}
$('<button type="button" class="editor-button editor-button-small"><i class="fa fa-caret-down"></button>').appendTo(item.gutter).on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
showObjectMenu($(this), item, readOnly);
});
}
if (parent) {//red-ui-editor-type-json-editor-item-handle
$('<span class="red-ui-editor-type-json-editor-item-handle"><i class="fa fa-bars"></span>').appendTo(item.gutter);
} else {
$('<span></span>').appendTo(item.gutter);
}
$('<button type="button" class="editor-button editor-button-small"><i class="fa fa-caret-down"></button>').appendTo(item.gutter).on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
showObjectMenu($(this), item);
});
item.element = container; item.element = container;
return item; return item;
} }
@@ -445,7 +434,6 @@
var definition = { var definition = {
show: function(options) { show: function(options) {
var value = options.value; var value = options.value;
var onCancel = options.cancel;
var onComplete = options.complete; var onComplete = options.complete;
var type = "_json" var type = "_json"
if ($("script[data-template-name='"+type+"']").length === 0) { if ($("script[data-template-name='"+type+"']").length === 0) {
@@ -467,16 +455,15 @@
} }
} }
var rootNode; var rootNode;
var trayOptions = { var trayOptions = {
title: options.title, title: options.title,
focusElement: options.focusElement,
width: options.width||700, width: options.width||700,
buttons: [ buttons: [
{ {
id: "node-dialog-cancel", id: "node-dialog-cancel",
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
if (onCancel) { onCancel(); }
RED.tray.close(); RED.tray.close();
} }
}, },
@@ -498,8 +485,7 @@
} else if (activeTab === "json-raw") { } else if (activeTab === "json-raw") {
result = expressionEditor.getValue(); result = expressionEditor.getValue();
} }
expressionEditor.saveView(); if (onComplete) { onComplete(result) }
if (onComplete) { onComplete(result,null,expressionEditor) }
RED.tray.close(); RED.tray.close();
} }
} }
@@ -512,29 +498,10 @@
open: function(tray) { open: function(tray) {
var trayBody = tray.find('.red-ui-tray-body'); var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
var toolbarButtons = options.toolbarButtons || [];
if (toolbarButtons.length) {
toolbarButtons.forEach(function (button) {
var element = $('<button type="button" class="red-ui-button red-ui-button-small"> </button>')
.insertBefore("#node-input-json-reformat")
.on("click", function (evt) {
evt.preventDefault();
if (button.click !== undefined) {
button.click.call(element, evt);
}
});
if (button.id) { element.attr("id", button.id); }
if (button.title) { element.attr("title", button.title); }
if (button.icon) { element.append($("<i></i>").attr("class", button.icon)); }
if (button.label || button.text) {
element.append($("<span></span>").text(" " + (button.label || button.text)));
}
});
}
var container = $("#red-ui-editor-type-json-tab-ui-container").css({"height":"100%"}); var container = $("#red-ui-editor-type-json-tab-ui-container").css({"height":"100%"});
var filterDepth = Infinity; var filterDepth = Infinity;
var list = $('<div class="red-ui-debug-msg-payload red-ui-editor-type-json-editor">').appendTo(container).treeList({ var list = $('<div class="red-ui-debug-msg-payload red-ui-editor-type-json-editor">').appendTo(container).treeList({
selectable: false,
rootSortable: false, rootSortable: false,
sortable: ".red-ui-editor-type-json-editor-item-handle", sortable: ".red-ui-editor-type-json-editor-item-handle",
}).on("treelistchangeparent", function(event, evt) { }).on("treelistchangeparent", function(event, evt) {
@@ -561,15 +528,13 @@
}) })
}); });
expressionEditor = RED.editor.createEditor({ expressionEditor = RED.editor.createEditor({
id: 'node-input-json', id: 'node-input-json',
value: value||"", value: "",
mode:"ace/mode/json", mode:"ace/mode/json"
readOnly: !!options.readOnly,
stateId: options.stateId,
focus: true
}); });
expressionEditor.getSession().setValue(value||"",-1);
if (options.requireValid) { if (options.requireValid) {
expressionEditor.getSession().on('change', function() { expressionEditor.getSession().on('change', function() {
clearTimeout(changeTimer); clearTimeout(changeTimer);
@@ -606,7 +571,7 @@
var raw = expressionEditor.getValue().trim() ||"{}"; var raw = expressionEditor.getValue().trim() ||"{}";
try { try {
var parsed = JSON.parse(raw); var parsed = JSON.parse(raw);
rootNode = handleItem(null,parsed,0,null,options.readOnly); rootNode = handleItem(null,parsed,0,null);
rootNode.class = "red-ui-editor-type-json-root-node" rootNode.class = "red-ui-editor-type-json-root-node"
list.treeList('data',[rootNode]); list.treeList('data',[rootNode]);
} catch(err) { } catch(err) {
@@ -624,21 +589,23 @@
tabs.addTab({ tabs.addTab({
id: 'json-raw', id: 'json-raw',
label: options.readOnly ? RED._('jsonEditor.rawMode-readonly') : RED._('jsonEditor.rawMode'), label: RED._('jsonEditor.rawMode'),
content: $("#red-ui-editor-type-json-tab-raw") content: $("#red-ui-editor-type-json-tab-raw")
}); });
tabs.addTab({ tabs.addTab({
id: 'json-ui', id: 'json-ui',
label: options.readOnly ? RED._('jsonEditor.uiMode-readonly') : RED._('jsonEditor.uiMode'), label: RED._('jsonEditor.uiMode'),
content: $("#red-ui-editor-type-json-tab-ui") content: $("#red-ui-editor-type-json-tab-ui")
}); });
finishedBuild = true; finishedBuild = true;
}, },
close: function() { close: function() {
// expressionEditor.destroy();
if (options.onclose) { if (options.onclose) {
options.onclose(); options.onclose();
} }
expressionEditor.destroy();
}, },
show: function() {} show: function() {}
} }

View File

@@ -14,61 +14,6 @@
* limitations under the License. * limitations under the License.
**/ **/
(function() { (function() {
/**
* Converts dropped image file to date URL
*/
function file2base64Image(file, cb) {
var reader = new FileReader();
reader.onload = (function (fd) {
return function (e) {
cb(e.target.result);
};
})(file);
reader.readAsDataURL(file);
}
var initialized = false;
var currentEditor = null;
/**
* Initialize handler for image file drag events
*/
function initImageDrag(elem, editor) {
$(elem).on("dragenter", function (ev) {
ev.preventDefault();
$("#red-ui-image-drop-target").css({display:'table'}).focus();
currentEditor = editor;
});
if (!initialized) {
initialized = true;
$("#red-ui-image-drop-target").on("dragover", function (ev) {
ev.preventDefault();
}).on("dragleave", function (ev) {
$("#red-ui-image-drop-target").hide();
}).on("drop", function (ev) {
ev.preventDefault();
if ($.inArray("Files",ev.originalEvent.dataTransfer.types) != -1) {
var files = ev.originalEvent.dataTransfer.files;
if (files.length === 1) {
var file = files[0];
var name = file.name.toLowerCase();
if (name.match(/\.(apng|avif|gif|jpeg|png|svg|webp)$/)) {
file2base64Image(file, function (image) {
var session = currentEditor.getSession();
var img = `<img src="${image}"/>\n`;
var pos = session.getCursorPosition();
session.insert(pos, img);
$("#red-ui-image-drop-target").hide();
});
return;
}
}
}
$("#red-ui-image-drop-target").hide();
});
}
}
var toolbarTemplate = '<div style="margin-bottom: 5px">'+ var toolbarTemplate = '<div style="margin-bottom: 5px">'+
'<span class="button-group">'+ '<span class="button-group">'+
@@ -109,26 +54,24 @@
var definition = { var definition = {
show: function(options) { show: function(options) {
var value = options.value; var value = options.value;
var onCancel = options.cancel;
var onComplete = options.complete; var onComplete = options.complete;
var type = "_markdown" var type = "_markdown"
if ($("script[data-template-name='"+type+"']").length === 0) { if ($("script[data-template-name='"+type+"']").length === 0) {
$(template).appendTo("#red-ui-editor-node-configs"); $(template).appendTo("#red-ui-editor-node-configs");
} }
RED.view.state(RED.state.EDITING); RED.view.state(RED.state.EDITING);
var expressionEditor; var expressionEditor;
var trayOptions = { var trayOptions = {
title: options.title, title: options.title,
focusElement: options.focusElement,
width: options.width||Infinity, width: options.width||Infinity,
buttons: [ buttons: [
{ {
id: "node-dialog-cancel", id: "node-dialog-cancel",
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
if (onCancel) { onCancel(); }
RED.tray.close(); RED.tray.close();
} }
}, },
@@ -137,8 +80,7 @@
text: RED._("common.label.done"), text: RED._("common.label.done"),
class: "primary", class: "primary",
click: function() { click: function() {
expressionEditor.saveView(); onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition());
if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(), expressionEditor); }
RED.tray.close(); RED.tray.close();
} }
} }
@@ -157,8 +99,6 @@
expressionEditor = RED.editor.createEditor({ expressionEditor = RED.editor.createEditor({
id: 'red-ui-editor-type-markdown', id: 'red-ui-editor-type-markdown',
value: value, value: value,
stateId: options.stateId,
focus: true,
mode:"ace/mode/markdown", mode:"ace/mode/markdown",
expandable: false expandable: false
}); });
@@ -169,7 +109,6 @@
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop(); var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop); $(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
mermaid.init();
},200); },200);
}) })
if (options.header) { if (options.header) {
@@ -178,7 +117,6 @@
if (value) { if (value) {
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue())); $(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
mermaid.init();
} }
panels = RED.panels.create({ panels = RED.panels.create({
id:"red-ui-editor-type-markdown-panels", id:"red-ui-editor-type-markdown-panels",
@@ -205,21 +143,17 @@
}); });
RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview")); RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview"));
if(!expressionEditor._initState) { if (options.cursor) {
if (options.cursor) { expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); }
}
else {
expressionEditor.gotoLine(0, 0, false);
}
}
dialogForm.i18n(); dialogForm.i18n();
}, },
close: function() { close: function() {
expressionEditor.destroy();
if (options.onclose) { if (options.onclose) {
options.onclose(); options.onclose();
} }
expressionEditor.destroy();
}, },
show: function() {} show: function() {}
} }
@@ -234,7 +168,7 @@
'b': { before:"**", after: "**", tooltip: RED._("markdownEditor.bold")}, 'b': { before:"**", after: "**", tooltip: RED._("markdownEditor.bold")},
'i': { before:"_", after: "_", tooltip: RED._("markdownEditor.italic")}, 'i': { before:"_", after: "_", tooltip: RED._("markdownEditor.italic")},
'code': { before:"`", after: "`", tooltip: RED._("markdownEditor.code")}, 'code': { before:"`", after: "`", tooltip: RED._("markdownEditor.code")},
'ol': { before:" 1. ", newline: true, tooltip: RED._("markdownEditor.ordered-list")}, 'ol': { before:" * ", newline: true, tooltip: RED._("markdownEditor.ordered-list")},
'ul': { before:" - ", newline: true, tooltip: RED._("markdownEditor.unordered-list")}, 'ul': { before:" - ", newline: true, tooltip: RED._("markdownEditor.unordered-list")},
'bq': { before:"> ", newline: true, tooltip: RED._("markdownEditor.quote")}, 'bq': { before:"> ", newline: true, tooltip: RED._("markdownEditor.quote")},
'link': { before:"[", after: "]()", tooltip: RED._("markdownEditor.link")}, 'link': { before:"[", after: "]()", tooltip: RED._("markdownEditor.link")},
@@ -276,11 +210,7 @@
} }
}) })
return toolbar; return toolbar;
}, }
postInit: function (editor, options) {
var elem = $("#"+options.id);
initImageDrag(elem, editor);
}
} }
RED.editor.registerTypeEditor("_markdown", definition); RED.editor.registerTypeEditor("_markdown", definition);
})(); })();

View File

@@ -1,530 +0,0 @@
;(function() {
RED.editor.registerEditPane("editor-tab-appearance", function(node) {
return {
label: RED._("editor-tab.appearance"),
name: RED._("editor-tab.appearance"),
iconClass: "fa fa-object-group",
create: function(container) {
this.content = container;
buildAppearanceForm(this.content,node);
if (node.type === 'subflow') {
this.defaultIcon = "node-red/subflow.svg";
} else {
var iconPath = RED.utils.getDefaultNodeIcon(node._def,node);
this.defaultIcon = iconPath.module+"/"+iconPath.file;
if (node.icon && node.icon !== this.defaultIcon) {
this.isDefaultIcon = false;
} else {
this.isDefaultIcon = true;
}
}
},
resize: function(size) {
},
close: function() {
},
show: function() {
refreshLabelForm(this.content, node);
},
apply: function(editState) {
if (updateLabels(node, editState.changes, editState.outputMap)) {
editState.changed = true;
}
if (!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) {
var icon = $("#red-ui-editor-node-icon").val()||"";
if (!this.isDefaultIcon) {
if ((node.icon && icon !== node.icon) || (!node.icon && icon !== "")) {
editState.changes.icon = node.icon;
node.icon = icon;
editState.changed = true;
}
} else {
if (icon !== "" && icon !== this.defaultIcon) {
editState.changes.icon = node.icon;
node.icon = icon;
editState.changed = true;
} else {
var iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
var currentDefaultIcon = iconPath.module+"/"+iconPath.file;
if (this.defaultIcon !== currentDefaultIcon) {
editState.changes.icon = node.icon;
node.icon = currentDefaultIcon;
editState.changed = true;
}
}
}
}
if (node.type === "subflow") {
var newCategory = $("#subflow-appearance-input-category").val().trim();
if (newCategory === "_custom_") {
newCategory = $("#subflow-appearance-input-custom-category").val().trim();
if (newCategory === "") {
newCategory = node.category;
}
}
if (newCategory === 'subflows') {
newCategory = '';
}
if (newCategory != node.category) {
editState.changes['category'] = node.category;
node.category = newCategory;
editState.changed = true;
}
var oldColor = node.color;
var newColor = $("#red-ui-editor-node-color").val();
if (oldColor !== newColor) {
editState.changes.color = node.color;
node.color = newColor;
editState.changed = true;
RED.utils.clearNodeColorCache();
if (node.type === "subflow") {
var nodeDefinition = RED.nodes.getType(
"subflow:" + node.id
);
nodeDefinition["color"] = newColor;
}
}
}
var showLabel = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true;
if (!$("#node-input-show-label").prop('checked')) {
// Not checked - hide label
if (showLabel) {
// Default to show label
if (node.l !== false) {
editState.changes.l = node.l;
editState.changed = true;
}
node.l = false;
} else {
// Node has showLabel:false (eg link nodes)
if (node.hasOwnProperty('l') && node.l) {
editState.changes.l = node.l;
editState.changed = true;
}
delete node.l;
}
} else {
// Checked - show label
if (showLabel) {
// Default to show label
if (node.hasOwnProperty('l') && !node.l) {
editState.changes.l = node.l;
editState.changed = true;
}
delete node.l;
} else {
if (!node.l) {
editState.changes.l = node.l;
editState.changed = true;
}
node.l = true;
}
}
}
};
});
function buildAppearanceForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var i,row;
if (node.type === "subflow") {
var categoryRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>", {
for: "subflow-appearance-input-category",
"data-i18n": "editor:subflow.category"
}).appendTo(categoryRow);
var categorySelector = $("<select/>", {
id: "subflow-appearance-input-category"
}).css({
width: "250px"
}).appendTo(categoryRow);
$("<input/>", {
type: "text",
id: "subflow-appearance-input-custom-category"
}).css({
display: "none",
"margin-left": "10px",
width: "calc(100% - 250px)"
}).appendTo(categoryRow);
var categories = RED.palette.getCategories();
categories.sort(function(A,B) {
return A.label.localeCompare(B.label);
});
categories.forEach(function(cat) {
categorySelector.append($("<option/>").val(cat.id).text(cat.label));
});
categorySelector.append($("<option/>").attr('disabled',true).text("---"));
categorySelector.append($("<option/>").val("_custom_").text(RED._("palette.addCategory")));
$("#subflow-appearance-input-category").on("change", function() {
var val = $(this).val();
if (val === "_custom_") {
$("#subflow-appearance-input-category").width(120);
$("#subflow-appearance-input-custom-category").show();
} else {
$("#subflow-appearance-input-category").width(250);
$("#subflow-appearance-input-custom-category").hide();
}
});
$("#subflow-appearance-input-category").val(node.category||"subflows");
var userCount = 0;
var subflowType = "subflow:"+node.id;
// RED.nodes.eachNode(function(n) {
// if (n.type === subflowType) {
// userCount++;
// }
// });
$("#red-ui-editor-subflow-user-count")
.text(RED._("subflow.subflowInstances", {count:node.instances.length})).show();
}
$('<div class="form-row">'+
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
'<span style="margin-right: 2px;"/>'+
'<input type="checkbox" id="node-input-show-label"/>'+
'</div>').appendTo(dialogForm);
$("#node-input-show-label").toggleButton({
enabledLabel: RED._("editor.show"),
disabledLabel: RED._("editor.hide")
});
if (!node.hasOwnProperty("l")) {
// Show label unless def.showLabel set to false
node.l = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true;
}
$("#node-input-show-label").prop("checked",node.l).trigger("change");
if (node.type === "subflow") {
// subflow template can select its color
var color = node.color ? node.color : "#DDAA99";
var colorRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>").text(RED._("editor.color")).appendTo(colorRow);
var recommendedColors = [
"#DDAA99",
"#3FADB5", "#87A980", "#A6BBCF",
"#AAAA66", "#C0C0C0", "#C0DEED",
"#C7E9C0", "#D7D7A0", "#D8BFD8",
"#DAC4B4", "#DEB887", "#DEBD5C",
"#E2D96E", "#E6E0F8", "#E7E7AE",
"#E9967A", "#F3B567", "#FDD0A2",
"#FDF0C2", "#FFAAAA", "#FFCC66",
"#FFF0F0", "#FFFFFF"
];
RED.editor.colorPicker.create({
id: "red-ui-editor-node-color",
value: color,
defaultValue: "#DDAA99",
palette: recommendedColors,
sortPalette: function (a, b) {return a.l - b.l;}
}).appendTo(colorRow);
$("#red-ui-editor-node-color").on('change', function(ev) {
// Horribly out of scope...
var colour = $(this).val();
nodeDiv.css('backgroundColor',colour);
var borderColor = RED.utils.getDarkerColor(colour);
if (borderColor !== colour) {
nodeDiv.css('border-color',borderColor);
}
});
}
// If a node has icon property in defaults, the icon of the node cannot be modified. (e.g, ui_button node in dashboard)
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
var iconRow = $('<div class="form-row"></div>').appendTo(dialogForm);
$('<label data-i18n="editor.settingIcon">').appendTo(iconRow);
var iconButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(iconRow);
$('<i class="fa fa-caret-down"></i>').appendTo(iconButton);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconButton);
var colour = RED.utils.getNodeColor(node.type, node._def);
var icon_url = RED.utils.getNodeIcon(node._def,node);
nodeDiv.css('backgroundColor',colour);
var borderColor = RED.utils.getDarkerColor(colour);
if (borderColor !== colour) {
nodeDiv.css('border-color',borderColor);
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
iconButton.on("click", function(e) {
e.preventDefault();
var iconPath;
var icon = $("#red-ui-editor-node-icon").val()||"";
if (icon) {
iconPath = RED.utils.separateIconPath(icon);
} else {
iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
}
var backgroundColor = RED.utils.getNodeColor(node.type, node._def);
if (node.type === "subflow") {
backgroundColor = $("#red-ui-editor-node-color").val();
}
RED.editor.iconPicker.show(iconButton,backgroundColor,iconPath,false,function(newIcon) {
$("#red-ui-editor-node-icon").val(newIcon||"");
var icon_url = RED.utils.getNodeIcon(node._def,{type:node.type,icon:newIcon});
RED.utils.createIconElement(icon_url, iconContainer, true);
});
});
RED.popover.tooltip(iconButton, function() {
return $("#red-ui-editor-node-icon").val() || RED._("editor.default");
});
$('<input type="hidden" id="red-ui-editor-node-icon">').val(node.icon).appendTo(iconRow);
}
$('<div class="form-row"><span data-i18n="editor.portLabels"></span></div>').appendTo(dialogForm);
var inputCount = node.inputs || node._def.inputs || 0;
var outputCount = node.outputs || node._def.outputs || 0;
if (node.type === 'subflow') {
inputCount = node.in.length;
outputCount = node.out.length;
}
var inputLabels = node.inputLabels || [];
var outputLabels = node.outputLabels || [];
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
$('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelInputs"></span><div id="red-ui-editor-node-label-form-inputs"></div></div>').appendTo(dialogForm);
var inputsDiv = $("#red-ui-editor-node-label-form-inputs");
if (inputCount > 0) {
for (i=0;i<inputCount;i++) {
buildLabelRow("input",i,inputLabels[i],inputPlaceholder).appendTo(inputsDiv);
}
} else {
buildLabelRow().appendTo(inputsDiv);
}
$('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelOutputs"></span><div id="red-ui-editor-node-label-form-outputs"></div></div>').appendTo(dialogForm);
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
if (outputCount > 0) {
for (i=0;i<outputCount;i++) {
buildLabelRow("output",i,outputLabels[i],outputPlaceholder).appendTo(outputsDiv);
}
} else {
buildLabelRow().appendTo(outputsDiv);
}
}
function refreshLabelForm(container,node) {
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var inputsDiv = $("#red-ui-editor-node-label-form-inputs");
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
var inputCount;
var formInputs = $("#node-input-inputs").val();
if (formInputs === undefined) {
if (node.type === 'subflow') {
inputCount = node.in.length;
} else {
inputCount = node.inputs || node._def.inputs || 0;
}
} else {
inputCount = Math.min(1,Math.max(0,parseInt(formInputs)));
if (isNaN(inputCount)) {
inputCount = 0;
}
}
var children = inputsDiv.children();
var childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
if (childCount < inputCount) {
if (childCount === 0) {
// remove the 'none' placeholder
$(children[0]).remove();
}
for (i = childCount;i<inputCount;i++) {
buildLabelRow("input",i,"",inputPlaceholder).appendTo(inputsDiv);
}
} else if (childCount > inputCount) {
for (i=inputCount;i<childCount;i++) {
$(children[i]).remove();
}
if (inputCount === 0) {
buildLabelRow().appendTo(inputsDiv);
}
}
var outputCount;
var i;
var formOutputs = $("#node-input-outputs").val();
if (formOutputs === undefined) {
if (node.type === 'subflow') {
outputCount = node.out.length;
} else {
inputCount = node.outputs || node._def.outputs || 0;
}
} else if (isNaN(formOutputs)) {
var outputMap = JSON.parse(formOutputs);
var keys = Object.keys(outputMap);
children = outputsDiv.children();
childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
outputCount = 0;
var rows = [];
keys.forEach(function(p) {
var row = $("#red-ui-editor-node-label-form-output-"+p).parent();
if (row.length === 0 && outputMap[p] !== -1) {
if (childCount === 0) {
$(children[0]).remove();
childCount = -1;
}
row = buildLabelRow("output",p,"",outputPlaceholder);
} else {
row.detach();
}
if (outputMap[p] !== -1) {
outputCount++;
rows.push({i:parseInt(outputMap[p]),r:row});
}
});
rows.sort(function(A,B) {
return A.i-B.i;
});
rows.forEach(function(r,i) {
r.r.find("label").text((i+1)+".");
r.r.appendTo(outputsDiv);
});
if (rows.length === 0) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
} else {
}
} else {
outputCount = Math.max(0,parseInt(formOutputs));
}
children = outputsDiv.children();
childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
if (childCount < outputCount) {
if (childCount === 0) {
// remove the 'none' placeholder
$(children[0]).remove();
}
for (i = childCount;i<outputCount;i++) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
}
} else if (childCount > outputCount) {
for (i=outputCount;i<childCount;i++) {
$(children[i]).remove();
}
if (outputCount === 0) {
buildLabelRow().appendTo(outputsDiv);
}
}
}
function buildLabelRow(type, index, value, placeHolder) {
var result = $('<div>',{class:"red-ui-editor-node-label-form-row"});
if (type === undefined) {
$('<span>').text(RED._("editor.noDefaultLabel")).appendTo(result);
result.addClass("red-ui-editor-node-label-form-none");
} else {
result.addClass("");
var id = "red-ui-editor-node-label-form-"+type+"-"+index;
$('<label>',{for:id}).text((index+1)+".").appendTo(result);
var input = $('<input>',{type:"text",id:id, placeholder: placeHolder}).val(value).appendTo(result);
var clear = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-times"></i></button>').appendTo(result);
clear.on("click", function(evt) {
evt.preventDefault();
input.val("");
});
}
return result;
}
function updateLabels(node, changes, outputMap) {
var inputLabels = $("#red-ui-editor-node-label-form-inputs").children().find("input");
var outputLabels = $("#red-ui-editor-node-label-form-outputs").children().find("input");
var hasNonBlankLabel = false;
var changed = false;
var newValue = inputLabels.map(function() {
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
return v;
}).toArray().slice(0,node.inputs);
if ((node.inputLabels === undefined && hasNonBlankLabel) ||
(node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(node.inputLabels))) {
changes.inputLabels = node.inputLabels;
node.inputLabels = newValue;
changed = true;
}
hasNonBlankLabel = false;
newValue = new Array(node.outputs);
outputLabels.each(function() {
var index = $(this).attr('id').substring("red-ui-editor-node-label-form-output-".length);
if (outputMap && outputMap.hasOwnProperty(index)) {
index = parseInt(outputMap[index]);
if (index === -1) {
return;
}
}
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
// mark changed output port labels as dirty
if (node.type === "subflow" && (!node.outputLabels || node.outputLabels[index] !== v)) {
node.out[index].dirty = true;
}
newValue[index] = v;
});
if ((node.outputLabels === undefined && hasNonBlankLabel) ||
(node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(node.outputLabels))) {
changes.outputLabels = node.outputLabels;
node.outputLabels = newValue;
changed = true;
// trigger redraw of dirty port labels
if (node.type === "subflow") {
RED.view.redraw();
}
}
return changed;
}
})();

View File

@@ -1,67 +0,0 @@
;(function() {
RED.editor.registerEditPane("editor-tab-description", function(node) {
return {
label: RED._("editor-tab.description"),
name: RED._("editor-tab.description"),
iconClass: "fa fa-file-text-o",
create: function(container) {
this.editor = buildDescriptionForm(container,node);
},
resize: function(size) {
this.editor.resize();
},
close: function() {
this.editor.destroy();
this.editor = null;
},
show: function() {
this.editor.focus();
},
apply: function(editState) {
var oldInfo = node.info;
var newInfo = this.editor.getValue();
if (!!oldInfo) {
// Has existing info property
if (newInfo.trim() === "") {
// New value is blank - remove the property
editState.changed = true;
editState.changes.info = oldInfo;
delete node.info;
} else if (newInfo !== oldInfo) {
// New value is different
editState.changed = true;
editState.changes.info = oldInfo;
node.info = newInfo;
}
} else {
// No existing info
if (newInfo.trim() !== "") {
// New value is not blank
editState.changed = true;
editState.changes.info = undefined;
node.info = newInfo;
}
}
}
}
});
function buildDescriptionForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var toolbarRow = $('<div></div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row" style="position:relative; padding-top: 4px; height: 100%"></div>').appendTo(dialogForm);
var editorId = "node-info-input-info-editor-"+Math.floor(1000*Math.random());
$('<div style="height: 100%" class="node-text-editor" id="'+editorId+'" ></div>').appendTo(row);
var nodeInfoEditor = RED.editor.createEditor({
id: editorId,
mode: 'ace/mode/markdown',
stateId: RED.editor.generateViewStateId("node", node, "nodeinfo"),
value: node.info || ""
});
node.infoEditor = nodeInfoEditor;
return nodeInfoEditor;
}
})();

View File

@@ -1,75 +0,0 @@
;(function() {
RED.editor.registerEditPane("editor-tab-envProperties", function(node) {
return {
label: RED._("editor-tab.envProperties"),
name: RED._("editor-tab.envProperties"),
iconClass: "fa fa-list",
create: function(container) {
var form = $('<form class="dialog-form form-horizontal"></form>').appendTo(container);
var listContainer = $('<div class="form-row node-input-env-container-row"></div>').appendTo(form);
this.list = $('<ol></ol>').appendTo(listContainer);
RED.editor.envVarList.create(this.list, node);
},
resize: function(size) {
this.list.editableList('height',size.height);
},
close: function() {
},
apply: function(editState) {
var old_env = node.env;
var new_env = [];
if (/^subflow:/.test(node.type)) {
new_env = RED.subflow.exportSubflowInstanceEnv(node);
}
// Get the values from the Properties table tab
var items = this.list.editableList('items');
items.each(function (i,el) {
var data = el.data('data');
var item;
if (data.nameField && data.valueField) {
item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
}
if (item.name.trim() !== "") {
new_env.push(item);
}
}
});
if (new_env && new_env.length > 0) {
new_env.forEach(function(prop) {
if (prop.type === "cred") {
node.credentials = node.credentials || {_:{}};
node.credentials[prop.name] = prop.value;
node.credentials['has_'+prop.name] = (prop.value !== "");
if (prop.value !== '__PWRD__') {
editState.changed = true;
}
delete prop.value;
}
});
}
if (!old_env && new_env.length === 0) {
delete node.env;
} else if (!isSameObj(old_env, new_env)) {
editState.changes.env = node.env;
if (new_env.length === 0) {
delete node.env;
} else {
node.env = new_env;
}
editState.changed = true;
}
}
}
});
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
})();

View File

@@ -1,58 +0,0 @@
;(function() {
RED.editor.registerEditPane("editor-tab-flow-properties", function(node) {
return {
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
iconClass: "fa fa-cog",
create: function(container) {
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(container);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
'<div style="min-height:150px;" class="node-text-editor" id="node-input-info"></div>'+
'</div>').appendTo(dialogForm);
this.tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
value: ""
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
$("#node-input-name").val(node.label);
RED.text.bidi.prepareInput($("#node-input-name"));
this.tabflowEditor.getSession().setValue(node.info || "", -1);
},
resize: function(size) {
$("#node-input-info").css("height", (size.height-70)+"px");
this.tabflowEditor.resize();
},
close: function() {
this.tabflowEditor.destroy();
},
apply: function(editState) {
var label = $( "#node-input-name" ).val();
if (node.label != label) {
editState.changes.label = node.label;
editState.changed = true;
node.label = label;
}
var info = this.tabflowEditor.getValue();
if (node.info !== info) {
editState.changes.info = node.info;
editState.changed = true;
node.info = info;
}
$("#red-ui-tab-"+(node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!node.disabled);
}
}
});
})();

View File

@@ -1,198 +0,0 @@
;(function() {
RED.editor.registerEditPane("editor-tab-properties", function(node) {
return {
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
iconClass: "fa fa-cog",
create: function(container) {
var nodeType = node.type;
if (node.type === "subflow") {
nodeType = "subflow-template";
} else if (node.type.substring(0,8) == "subflow:") {
nodeType = "subflow";
}
var i18nNamespace;
if (node._def.set.module === "node-red") {
i18nNamespace = "node-red";
} else {
i18nNamespace = node._def.set.id;
}
var formStyle = "dialog-form";
this.inputClass = "node-input";
if (node._def.category === "config" && nodeType !== "group") {
this.inputClass = "node-config-input";
formStyle = "node-config-dialog-edit-form";
}
RED.editor.buildEditForm(container,formStyle,nodeType,i18nNamespace,node);
},
resize: function(size) {
if (node && node._def.oneditresize) {
try {
node._def.oneditresize.call(node,size);
} catch(err) {
console.log("oneditresize",node.id,node.type,err.toString());
}
}
},
close: function() {
},
apply: function(editState) {
var newValue;
var d;
if (node._def.defaults) {
for (d in node._def.defaults) {
if (node._def.defaults.hasOwnProperty(d)) {
var input = $("#"+this.inputClass+"-"+d);
if (input.attr('type') === "checkbox") {
newValue = input.prop('checked');
} else if (input.prop("nodeName") === "select" && input.attr("multiple") === "multiple") {
// An empty select-multiple box returns null.
// Need to treat that as an empty array.
newValue = input.val();
if (newValue == null) {
newValue = [];
}
} else if ("format" in node._def.defaults[d] && node._def.defaults[d].format !== "" && input[0].nodeName === "DIV") {
newValue = input.text();
} else {
newValue = input.val();
}
if (newValue != null) {
if (d === "outputs") {
if (newValue.trim() === "") {
continue;
}
if (isNaN(newValue)) {
editState.outputMap = JSON.parse(newValue);
var outputCount = 0;
var outputsChanged = false;
var keys = Object.keys(editState.outputMap);
keys.forEach(function(p) {
if (isNaN(p)) {
// New output;
outputCount ++;
delete editState.outputMap[p];
} else {
editState.outputMap[p] = editState.outputMap[p]+"";
if (editState.outputMap[p] !== "-1") {
outputCount++;
if (editState.outputMap[p] !== p) {
// Output moved
outputsChanged = true;
} else {
delete editState.outputMap[p];
}
} else {
// Output removed
outputsChanged = true;
}
}
});
newValue = outputCount;
if (outputsChanged) {
editState.changed = true;
}
} else {
newValue = parseInt(newValue);
}
}
if (node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
}
if (!isEqual(node[d], newValue)) {
if (node._def.defaults[d].type) {
// Change to a related config node
var configNode = RED.nodes.node(node[d]);
if (configNode) {
var users = configNode.users;
users.splice(users.indexOf(node),1);
RED.events.emit("nodes:change",configNode);
}
configNode = RED.nodes.node(newValue);
if (configNode) {
configNode.users.push(node);
RED.events.emit("nodes:change",configNode);
}
}
editState.changes[d] = node[d];
node[d] = newValue;
editState.changed = true;
}
}
}
}
}
if (node._def.credentials) {
var credDefinition = node._def.credentials;
var credsChanged = updateNodeCredentials(node,credDefinition,this.inputClass);
editState.changed = editState.changed || credsChanged;
}
}
}
});
/**
* Compares `newValue` with `originalValue` for equality.
* @param {*} originalValue Original value
* @param {*} newValue New value
* @returns {boolean} true if originalValue equals newValue, otherwise false
*/
function isEqual(originalValue, newValue) {
try {
if(originalValue == newValue) {
return true;
}
return JSON.stringify(originalValue) === JSON.stringify(newValue);
} catch (err) {
return false;
}
}
/**
* Update the node credentials from the edit form
* @param node - the node containing the credentials
* @param credDefinition - definition of the credentials
* @param prefix - prefix of the input fields
* @return {boolean} whether anything has changed
*/
function updateNodeCredentials(node, credDefinition, prefix) {
var changed = false;
if (!node.credentials) {
node.credentials = {_:{}};
} else if (!node.credentials._) {
node.credentials._ = {};
}
for (var cred in credDefinition) {
if (credDefinition.hasOwnProperty(cred)) {
var input = $("#" + prefix + '-' + cred);
if (input.length > 0) {
var value = input.val();
if (credDefinition[cred].type == 'password') {
node.credentials['has_' + cred] = (value !== "");
if (value == '__PWRD__') {
continue;
}
changed = true;
}
node.credentials[cred] = value;
if (value != node.credentials._[cred]) {
changed = true;
}
}
}
}
return changed;
}
})();

View File

@@ -1,179 +0,0 @@
(function() {
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
'<div class="form-row">'+
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-type" data-i18n="[append]editor:subflow.type"> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-type">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-license" data-i18n="[append]editor:subflow.license"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
'</div>'+
'</form>';
RED.editor.registerEditPane("editor-tab-subflow-module", function(node) {
return {
label: RED._("editor-tab.module"),
name: RED._("editor-tab.module"),
iconClass: "fa fa-cube",
create: function(container) {
buildModuleForm(container, node);
},
resize: function(size) {
},
close: function() {
},
apply: function(editState) {
var newMeta = exportSubflowModuleProperties(node);
if (!isSameObj(node.meta,newMeta)) {
editState.changes.meta = node.meta;
node.meta = newMeta;
editState.changed = true;
}
}
}
});
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
function setupInputValidation(input,validator) {
var errorTip;
var validateTimeout;
var validateFunction = function() {
if (validateTimeout) {
return;
}
validateTimeout = setTimeout(function() {
var error = validator(input.val());
// if (!error && errorTip) {
// errorTip.close();
// errorTip = null;
// } else if (error && !errorTip) {
// errorTip = RED.popover.create({
// tooltip: true,
// target:input,
// size: "small",
// direction: "bottom",
// content: error,
// }).open();
// }
input.toggleClass("input-error",!!error);
validateTimeout = null;
})
}
input.on("change keyup paste", validateFunction);
}
function buildModuleForm(container, node) {
$(_subflowModulePaneTemplate).appendTo(container);
var moduleProps = node.meta || {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords',
'license'
].forEach(function(property) {
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
})
$("#subflow-input-module-type").attr("placeholder",node.id);
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue.length < 215;
isValid = isValid && !/^[._]/.test(newValue);
isValid = isValid && !/[A-Z]/.test(newValue);
if (newValue !== encodeURIComponent(newValue)) {
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
if (m) {
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
} else {
isValid = false;
}
}
return isValid?"":"Invalid module name"
})
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue === "" ||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
return isValid?"":"Invalid version number"
})
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
var typedLicenses = {
types: licenses.map(function(l) {
return {
value: l,
label: l === "none" ? RED._("editor:subflow.licenseNone") : l,
hasValue: false
};
})
}
typedLicenses.types.push({
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
})
if (!moduleProps.license) {
typedLicenses.default = "none";
} else if (licenses.indexOf(moduleProps.license) > -1) {
typedLicenses.default = moduleProps.license;
} else {
typedLicenses.default = "_custom_";
}
$("#subflow-input-module-license").typedInput(typedLicenses)
}
function exportSubflowModuleProperties(node) {
var value;
var moduleProps = {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords'
].forEach(function(property) {
value = $("#subflow-input-module-"+property).val().trim();
if (value) {
moduleProps[property] = value;
}
})
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
if (selectedLicenseType === '_custom_') {
value = $("#subflow-input-module-license").val();
if (value) {
moduleProps.license = value;
}
} else if (selectedLicenseType !== "none") {
moduleProps.license = selectedLicenseType;
}
return moduleProps;
}
})();

View File

@@ -21,7 +21,6 @@
var definition = { var definition = {
show: function(options) { show: function(options) {
var value = options.value; var value = options.value;
var onCancel = options.cancel;
var onComplete = options.complete; var onComplete = options.complete;
var type = "_text" var type = "_text"
if ($("script[data-template-name='"+type+"']").length === 0) { if ($("script[data-template-name='"+type+"']").length === 0) {
@@ -29,16 +28,16 @@
} }
RED.view.state(RED.state.EDITING); RED.view.state(RED.state.EDITING);
var expressionEditor; var expressionEditor;
var changeTimer;
var trayOptions = { var trayOptions = {
title: options.title, title: options.title,
focusElement: options.focusElement,
width: options.width||"inherit", width: options.width||"inherit",
buttons: [ buttons: [
{ {
id: "node-dialog-cancel", id: "node-dialog-cancel",
text: RED._("common.label.cancel"), text: RED._("common.label.cancel"),
click: function() { click: function() {
if(onCancel) { onCancel(); }
RED.tray.close(); RED.tray.close();
} }
}, },
@@ -47,8 +46,7 @@
text: RED._("common.label.done"), text: RED._("common.label.done"),
class: "primary", class: "primary",
click: function() { click: function() {
expressionEditor.saveView(); onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition());
if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(),expressionEditor);}
RED.tray.close(); RED.tray.close();
} }
} }
@@ -57,27 +55,31 @@
var rows = $("#dialog-form>div:not(.node-text-editor-row)"); var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row"); var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height(); var height = $("#dialog-form").height();
// for (var i=0;i<rows.size();i++) {
// height -= $(rows[i]).outerHeight(true);
// }
// height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
$(".node-text-editor").css("height",height+"px"); $(".node-text-editor").css("height",height+"px");
expressionEditor.resize(); expressionEditor.resize();
}, },
open: function(tray) { open: function(tray) {
var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
expressionEditor = RED.editor.createEditor({ expressionEditor = RED.editor.createEditor({
id: 'node-input-text', id: 'node-input-text',
value: value||"", value: "",
stateId: options.stateId, mode:"ace/mode/"+(options.mode||"text")
mode:"ace/mode/"+(options.mode||"text"),
focus: true,
}); });
if (options.cursor && !expressionEditor._initState) { expressionEditor.getSession().setValue(value||"",-1);
if (options.cursor) {
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
} }
}, },
close: function() { close: function() {
expressionEditor.destroy();
if (options.onclose) { if (options.onclose) {
options.onclose(); options.onclose();
} }
expressionEditor.destroy();
}, },
show: function() {} show: function() {}
} }

View File

@@ -1,179 +0,0 @@
RED.envVar = (function() {
function saveEnvList(list) {
const items = list.editableList("items")
const new_env = [];
items.each(function (i,el) {
var data = el.data('data');
var item;
if (data.nameField && data.valueField) {
item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
};
new_env.push(item);
}
});
return new_env;
}
function getGlobalConf(create) {
var gconf = null;
RED.nodes.eachConfig(function (conf) {
if (conf.type === "global-config") {
gconf = conf;
}
});
if ((gconf === null) && create) {
var cred = {
_ : {},
map: {}
};
gconf = {
id: RED.nodes.id(),
type: "global-config",
env: [],
name: "global-config",
label: "",
hasUsers: false,
users: [],
credentials: cred,
_def: RED.nodes.getType("global-config"),
};
RED.nodes.add(gconf);
}
return gconf;
}
function applyChanges(list) {
var gconf = getGlobalConf(false);
var new_env = [];
var items = list.editableList('items');
var credentials = gconf ? gconf.credentials : null;
if (!credentials) {
credentials = {
_ : {},
map: {}
};
}
items.each(function (i,el) {
var data = el.data('data');
if (data.nameField && data.valueField) {
var item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
};
if (item.name.trim() !== "") {
new_env.push(item);
if ((item.type === "cred") && (item.value !== "__PWRD__")) {
credentials.map[item.name] = item.value;
credentials.map["has_"+item.name] = (item.value !== "");
item.value = "__PWRD__";
}
}
}
});
if (gconf === null) {
gconf = getGlobalConf(true);
}
if ((JSON.stringify(new_env) !== JSON.stringify(gconf.env)) ||
(JSON.stringify(credentials) !== JSON.stringify(gconf.credentials))) {
gconf.env = new_env;
gconf.credentials = credentials;
RED.nodes.dirty(true);
}
}
function getSettingsPane() {
var gconf = getGlobalConf(false);
var env = gconf ? gconf.env : [];
var cred = gconf ? gconf.credentials : null;
if (!cred) {
cred = {
_ : {},
map: {}
};
}
var pane = $("<div/>", {
id: "red-ui-settings-tab-envvar",
class: "form-horizontal"
});
var content = $("<div/>", {
class: "form-row node-input-env-container-row"
}).css({
"margin": "10px"
}).appendTo(pane);
var label = $("<label></label>").css({
width: "100%"
}).appendTo(content);
$("<i/>", {
class: "fa fa-list"
}).appendTo(label);
$("<span/>").text(" "+RED._("env-var.header")).appendTo(label);
var list = $("<ol/>", {
id: "node-input-env-container"
}).appendTo(content);
var node = {
type: "",
env: env,
credentials: cred.map,
};
RED.editor.envVarList.create(list, node);
var buttons = $("<div/>").css({
"text-align": "right",
}).appendTo(content);
var revertButton = $("<button/>", {
class: "red-ui-button"
}).css({
}).text(RED._("env-var.revert")).appendTo(buttons);
var items = saveEnvList(list);
revertButton.on("click", function (ev) {
list.editableList("empty");
list.editableList("addItems", items);
});
return pane;
}
function init(done) {
if (!RED.user.hasPermission("settings.write")) {
RED.notify(RED._("user.errors.settings"),"error");
return;
}
RED.userSettings.add({
id:'envvar',
title: RED._("env-var.environment"),
get: getSettingsPane,
focus: function() {
var height = $("#red-ui-settings-tab-envvar").parent().height();
$("#node-input-env-container").editableList("height", (height -100));
},
close: function() {
var list = $("#node-input-env-container");
try {
applyChanges(list);
}
catch (e) {
console.log(e);
console.log(e.stack);
}
}
});
RED.actions.add("core:show-global-env", function() {
RED.userSettings.show('envvar');
});
}
return {
init: init,
};
})();

View File

@@ -73,7 +73,6 @@ RED.eventLog = (function() {
var trayBody = tray.find('.red-ui-tray-body'); var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
eventLogEditor = RED.editor.createEditor({ eventLogEditor = RED.editor.createEditor({
mode:"ace/mode/shell",
id: 'red-ui-event-log-editor', id: 'red-ui-event-log-editor',
value: backlog.join("\n"), value: backlog.join("\n"),
lineNumbers: false, lineNumbers: false,

View File

@@ -87,21 +87,18 @@ RED.group = (function() {
"label-position": "nw" "label-position": "nw"
}; };
var groupDef = { var groupDef = {
defaults:{ defaults:{
name:{value:""}, name:{value:""},
style:{value:{label:true}}, style:{value:{label:true}},
nodes:{value:[]}, nodes:{value:[]}
env: {value:[]},
}, },
category: "config", category: "config",
oneditprepare: function() { oneditprepare: function() {
var style = this.style || {}; var style = this.style || {};
RED.editor.colorPicker.create({ RED.colorPicker.create({
id:"node-input-style-stroke", id:"node-input-style-stroke",
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4", value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
defaultValue: "#a4a4a4",
palette: colorPalette, palette: colorPalette,
cellPerRow: colorCount, cellPerRow: colorCount,
cellWidth: 16, cellWidth: 16,
@@ -110,10 +107,9 @@ RED.group = (function() {
none: true, none: true,
opacity: style.hasOwnProperty('stroke-opacity')?style['stroke-opacity']:(defaultGroupStyle.hasOwnProperty('stroke-opacity')?defaultGroupStyle['stroke-opacity']:1.0) opacity: style.hasOwnProperty('stroke-opacity')?style['stroke-opacity']:(defaultGroupStyle.hasOwnProperty('stroke-opacity')?defaultGroupStyle['stroke-opacity']:1.0)
}).appendTo("#node-input-row-style-stroke"); }).appendTo("#node-input-row-style-stroke");
RED.editor.colorPicker.create({ RED.colorPicker.create({
id:"node-input-style-fill", id:"node-input-style-fill",
value: style.fill || defaultGroupStyle.fill ||"none", value: style.fill || defaultGroupStyle.fill ||"none",
defaultValue: "none",
palette: colorPalette, palette: colorPalette,
cellPerRow: colorCount, cellPerRow: colorCount,
cellWidth: 16, cellWidth: 16,
@@ -128,10 +124,9 @@ RED.group = (function() {
value:style["label-position"] || "nw" value:style["label-position"] || "nw"
}).appendTo("#node-input-row-style-label-position"); }).appendTo("#node-input-row-style-label-position");
RED.editor.colorPicker.create({ RED.colorPicker.create({
id:"node-input-style-color", id:"node-input-style-color",
value: style.color || defaultGroupStyle.color ||"#a4a4a4", value: style.color || defaultGroupStyle.color ||"#a4a4a4",
defaultValue: "#a4a4a4",
palette: colorPalette, palette: colorPalette,
cellPerRow: colorCount, cellPerRow: colorCount,
cellWidth: 16, cellWidth: 16,
@@ -149,6 +144,7 @@ RED.group = (function() {
}) })
$("#node-input-style-label").prop("checked", this.style.label) $("#node-input-style-label").prop("checked", this.style.label)
$("#node-input-style-label").trigger("change"); $("#node-input-style-label").trigger("change");
}, },
oneditresize: function(size) { oneditresize: function(size) {
}, },
@@ -187,11 +183,7 @@ RED.group = (function() {
var activateUngroup = false; var activateUngroup = false;
var activateMerge = false; var activateMerge = false;
var activateRemove = false; var activateRemove = false;
var singleGroupSelected = false;
var locked = RED.workspaces.isLocked()
if (activateGroup) { if (activateGroup) {
singleGroupSelected = selection.nodes.length === 1 && selection.nodes[0].type === 'group';
selection.nodes.forEach(function (n) { selection.nodes.forEach(function (n) {
if (n.type === "group") { if (n.type === "group") {
activateUngroup = true; activateUngroup = true;
@@ -204,12 +196,10 @@ RED.group = (function() {
activateMerge = (selection.nodes.length > 1); activateMerge = (selection.nodes.length > 1);
} }
} }
RED.menu.setDisabled("menu-item-group-group", locked || !activateGroup); RED.menu.setDisabled("menu-item-group-group", !activateGroup);
RED.menu.setDisabled("menu-item-group-ungroup", locked || !activateUngroup); RED.menu.setDisabled("menu-item-group-ungroup", !activateUngroup);
RED.menu.setDisabled("menu-item-group-merge", locked || !activateMerge); RED.menu.setDisabled("menu-item-group-merge", !activateMerge);
RED.menu.setDisabled("menu-item-group-remove", locked || !activateRemove); RED.menu.setDisabled("menu-item-group-remove", !activateRemove);
RED.menu.setDisabled("menu-item-edit-copy-group-style", !singleGroupSelected);
RED.menu.setDisabled("menu-item-edit-paste-group-style", locked || !activateUngroup);
}); });
RED.actions.add("core:group-selection", function() { groupSelection() }) RED.actions.add("core:group-selection", function() { groupSelection() })
@@ -262,11 +252,9 @@ RED.group = (function() {
if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].type === 'group') { if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].type === 'group') {
groupStyleClipboard = JSON.parse(JSON.stringify(selection.nodes[0].style)); groupStyleClipboard = JSON.parse(JSON.stringify(selection.nodes[0].style));
RED.notify(RED._("clipboard.groupStyleCopied"),{id:"clipboard"}) RED.notify(RED._("clipboard.groupStyleCopied"),{id:"clipboard"})
RED.menu.setDisabled("menu-item-edit-paste-group-style", false)
} }
} }
function pasteGroupStyle() { function pasteGroupStyle() {
if (RED.workspaces.isLocked()) { return }
if (RED.view.state() !== RED.state.DEFAULT) { return } if (RED.view.state() !== RED.state.DEFAULT) { return }
if (groupStyleClipboard) { if (groupStyleClipboard) {
var selection = RED.view.selection(); var selection = RED.view.selection();
@@ -301,7 +289,6 @@ RED.group = (function() {
} }
function groupSelection() { function groupSelection() {
if (RED.workspaces.isLocked()) { return }
if (RED.view.state() !== RED.state.DEFAULT) { return } if (RED.view.state() !== RED.state.DEFAULT) { return }
var selection = RED.view.selection(); var selection = RED.view.selection();
if (selection.nodes) { if (selection.nodes) {
@@ -315,23 +302,24 @@ RED.group = (function() {
RED.history.push(historyEvent); RED.history.push(historyEvent);
RED.view.select({nodes:[group]}); RED.view.select({nodes:[group]});
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.focus();
} }
} }
} }
function ungroupSelection() { function ungroupSelection() {
if (RED.workspaces.isLocked()) { return }
if (RED.view.state() !== RED.state.DEFAULT) { return } if (RED.view.state() !== RED.state.DEFAULT) { return }
var selection = RED.view.selection(); var selection = RED.view.selection();
if (selection.nodes) { if (selection.nodes) {
var newSelection = []; var newSelection = [];
let groups = selection.nodes.filter(function(n) { return n.type === "group" }); groups = selection.nodes.filter(function(n) { return n.type === "group" });
var historyEvent = { var historyEvent = {
t:"ungroup", t:"ungroup",
groups: [ ], groups: [ ],
dirty: RED.nodes.dirty() dirty: RED.nodes.dirty()
} }
RED.history.push(historyEvent);
groups.forEach(function(g) { groups.forEach(function(g) {
newSelection = newSelection.concat(ungroup(g)) newSelection = newSelection.concat(ungroup(g))
historyEvent.groups.push(g); historyEvent.groups.push(g);
@@ -339,12 +327,10 @@ RED.group = (function() {
RED.history.push(historyEvent); RED.history.push(historyEvent);
RED.view.select({nodes:newSelection}) RED.view.select({nodes:newSelection})
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.focus();
} }
} }
function ungroup(g) { function ungroup(g) {
if (RED.workspaces.isLocked()) { return }
var nodes = []; var nodes = [];
var parentGroup = RED.nodes.group(g.g); var parentGroup = RED.nodes.group(g.g);
g.nodes.forEach(function(n) { g.nodes.forEach(function(n) {
@@ -360,10 +346,8 @@ RED.group = (function() {
} }
if (n.type === 'group') { if (n.type === 'group') {
RED.events.emit("groups:change",n) RED.events.emit("groups:change",n)
} else if (n.type !== 'junction') {
RED.events.emit("nodes:change",n)
} else { } else {
RED.events.emit("junctions:change",n) RED.events.emit("nodes:change",n)
} }
}) })
RED.nodes.removeGroup(g); RED.nodes.removeGroup(g);
@@ -371,7 +355,6 @@ RED.group = (function() {
} }
function mergeSelection() { function mergeSelection() {
if (RED.workspaces.isLocked()) { return }
if (RED.view.state() !== RED.state.DEFAULT) { return } if (RED.view.state() !== RED.state.DEFAULT) { return }
var selection = RED.view.selection(); var selection = RED.view.selection();
if (selection.nodes) { if (selection.nodes) {
@@ -436,12 +419,10 @@ RED.group = (function() {
}); });
RED.history.push(historyEvent); RED.history.push(historyEvent);
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.focus();
} }
} }
function removeSelection() { function removeSelection() {
if (RED.workspaces.isLocked()) { return }
if (RED.view.state() !== RED.state.DEFAULT) { return } if (RED.view.state() !== RED.state.DEFAULT) { return }
var selection = RED.view.selection(); var selection = RED.view.selection();
if (selection.nodes) { if (selection.nodes) {
@@ -465,25 +446,15 @@ RED.group = (function() {
} }
} }
RED.view.select({nodes:selection.nodes}) RED.view.select({nodes:selection.nodes})
RED.view.focus();
} }
} }
function createGroup(nodes) { function createGroup(nodes) {
if (RED.workspaces.isLocked()) { return }
if (nodes.length === 0) { if (nodes.length === 0) {
return; return;
} }
const existingGroup = nodes[0].g if (nodes.filter(function(n) { return n.type === "subflow" }).length > 0) {
for (let i = 0; i < nodes.length; i++) { RED.notify(RED._("group.errors.cannotAddSubflowPorts"),"error");
const n = nodes[i] return;
if (n.type === 'subflow') {
RED.notify(RED._("group.errors.cannotAddSubflowPorts"),"error");
return;
}
if (n.g !== existingGroup) {
console.warn("Cannot add nooes with different z properties")
return
}
} }
// nodes is an array // nodes is an array
// each node must be on the same tab (z) // each node must be on the same tab (z)
@@ -496,16 +467,11 @@ RED.group = (function() {
y: Number.POSITIVE_INFINITY, y: Number.POSITIVE_INFINITY,
w: 0, w: 0,
h: 0, h: 0,
_def: RED.group.def, _def: RED.group.def
changed: true
} }
group.z = nodes[0].z; group.z = nodes[0].z;
group = RED.nodes.addGroup(group); RED.nodes.addGroup(group);
if (existingGroup) {
addToGroup(RED.nodes.group(existingGroup), group)
}
try { try {
addToGroup(group,nodes); addToGroup(group,nodes);
@@ -530,7 +496,7 @@ RED.group = (function() {
if (!z) { if (!z) {
z = n.z; z = n.z;
} else if (z !== n.z) { } else if (z !== n.z) {
throw new Error("Cannot add nodes with different z properties") throw new Error("Cannot add nooes with different z properties")
} }
if (n.g) { if (n.g) {
// This is already in a group. // This is already in a group.
@@ -547,10 +513,14 @@ RED.group = (function() {
throw new Error(RED._("group.errors.cannotCreateDiffGroups")) throw new Error(RED._("group.errors.cannotCreateDiffGroups"))
} }
} }
// The nodes are already in a group - so we need to remove them first // The nodes are already in a group. The assumption is they should be
// wrapped in the newly provided group, and that group added to in their
// place to the existing containing group.
if (g) { if (g) {
g = RED.nodes.group(g); g = RED.nodes.group(g);
g.nodes.push(group);
g.dirty = true; g.dirty = true;
group.g = g.id;
} }
// Second pass - add them to the group // Second pass - add them to the group
for (i=0;i<nodes.length;i++) { for (i=0;i<nodes.length;i++) {
@@ -571,10 +541,8 @@ RED.group = (function() {
group.h = Math.max(group.h,n.y+n.h/2+25-group.y); group.h = Math.max(group.h,n.y+n.h/2+25-group.y);
if (n.type === 'group') { if (n.type === 'group') {
RED.events.emit("groups:change",n) RED.events.emit("groups:change",n)
} else if (n.type !== 'junction') {
RED.events.emit("nodes:change",n)
} else { } else {
RED.events.emit("junctions:change",n) RED.events.emit("nodes:change",n)
} }
} }
} }
@@ -584,7 +552,6 @@ RED.group = (function() {
markDirty(group); markDirty(group);
} }
function removeFromGroup(group, nodes, reparent) { function removeFromGroup(group, nodes, reparent) {
if (RED.workspaces.isLocked()) { return }
if (!Array.isArray(nodes)) { if (!Array.isArray(nodes)) {
nodes = [nodes]; nodes = [nodes];
} }
@@ -602,7 +569,7 @@ RED.group = (function() {
n.dirty = true; n.dirty = true;
var index = group.nodes.indexOf(n); var index = group.nodes.indexOf(n);
group.nodes.splice(index,1); group.nodes.splice(index,1);
if (reparent && parentGroup) { if (reparent && group.g) {
n.g = group.g n.g = group.g
parentGroup.nodes.push(n); parentGroup.nodes.push(n);
} else { } else {
@@ -610,23 +577,19 @@ RED.group = (function() {
} }
if (n.type === 'group') { if (n.type === 'group') {
RED.events.emit("groups:change",n) RED.events.emit("groups:change",n)
} else if (n.type !== 'junction') {
RED.events.emit("nodes:change",n)
} else { } else {
RED.events.emit("junctions:change",n) RED.events.emit("nodes:change",n)
} }
} }
markDirty(group); markDirty(group);
} }
function getNodes(group,recursive,excludeGroup) { function getNodes(group,recursive) {
var nodes = []; var nodes = [];
group.nodes.forEach(function(n) { group.nodes.forEach(function(n) {
if (n.type !== 'group' || !excludeGroup) { nodes.push(n);
nodes.push(n);
}
if (recursive && n.type === 'group') { if (recursive && n.type === 'group') {
nodes = nodes.concat(getNodes(n,recursive,excludeGroup)) nodes = nodes.concat(getNodes(n,recursive))
} }
}) })
return nodes; return nodes;

View File

@@ -49,15 +49,15 @@ RED.keyboard = (function() {
"]": 221, "]": 221,
"{": 219,// <- QWERTY specific "{": 219,// <- QWERTY specific
"}": 221 // <- QWERTY specific "}": 221 // <- QWERTY specific
}; }
var metaKeyCodes = { var metaKeyCodes = {
16: true, 16: true,
17: true, 17: true,
18: true, 18: true,
91: true, 91: true,
93: true 93: true
}; }
var actionToKeyMap = {}; var actionToKeyMap = {}
var defaultKeyMap = {}; var defaultKeyMap = {};
// FF generates some different keycodes because reasons. // FF generates some different keycodes because reasons.
@@ -65,7 +65,7 @@ RED.keyboard = (function() {
59:186, 59:186,
61:187, 61:187,
173:189 173:189
}; }
function migrateOldKeymap() { function migrateOldKeymap() {
// pre-0.18 // pre-0.18
@@ -80,7 +80,7 @@ RED.keyboard = (function() {
} }
function getUserKey(action) { function getUserKey(action) {
return RED.settings.get('editor.keymap',{})[action]; return RED.settings.get('editor.keymap',{})[action]
} }
function mergeKeymaps(defaultKeymap, themeKeymap) { function mergeKeymaps(defaultKeymap, themeKeymap) {
@@ -105,7 +105,7 @@ RED.keyboard = (function() {
scope:scope, scope:scope,
key:key, key:key,
user:false user:false
}); })
} }
} }
} }
@@ -115,13 +115,13 @@ RED.keyboard = (function() {
if (themeKeymap.hasOwnProperty(action)) { if (themeKeymap.hasOwnProperty(action)) {
if (!themeKeymap[action].key) { if (!themeKeymap[action].key) {
// No key for this action - default is no keybinding // No key for this action - default is no keybinding
delete mergedKeymap[action]; delete mergedKeymap[action]
} else { } else {
mergedKeymap[action] = [{ mergedKeymap[action] = [{
scope: themeKeymap[action].scope || "*", scope: themeKeymap[action].scope || "*",
key: themeKeymap[action].key, key: themeKeymap[action].key,
user: false user: false
}]; }]
if (mergedKeymap[action][0].scope === "workspace") { if (mergedKeymap[action][0].scope === "workspace") {
mergedKeymap[action][0].scope = "red-ui-workspace"; mergedKeymap[action][0].scope = "red-ui-workspace";
} }
@@ -131,7 +131,7 @@ RED.keyboard = (function() {
return mergedKeymap; return mergedKeymap;
} }
function init(done) { function init() {
// Migrate from pre-0.18 // Migrate from pre-0.18
migrateOldKeymap(); migrateOldKeymap();
@@ -164,7 +164,6 @@ RED.keyboard = (function() {
} }
} }
} }
done();
}); });
RED.userSettings.add({ RED.userSettings.add({
@@ -175,11 +174,8 @@ RED.keyboard = (function() {
setTimeout(function() { setTimeout(function() {
$("#red-ui-settings-tab-keyboard-filter").trigger("focus"); $("#red-ui-settings-tab-keyboard-filter").trigger("focus");
},200); },200);
},
close: function() {
RED.menu.refreshShortcuts();
} }
}); })
} }
function revertToDefault(action) { function revertToDefault(action) {
@@ -243,13 +239,7 @@ RED.keyboard = (function() {
function resolveKeyEvent(evt) { function resolveKeyEvent(evt) {
var slot = partialState||handlers; var slot = partialState||handlers;
// We cheat with MacOS CMD key and consider it the same as Ctrl. if (evt.ctrlKey || evt.metaKey) {
// That means we don't have to have separate keymaps for different OS.
// It mostly works.
// One exception is shortcuts that include both Cmd and Ctrl. We don't
// support them - but we need to make sure we don't block browser-specific
// shortcuts (such as Cmd-Ctrl-F for fullscreen).
if ((evt.ctrlKey || evt.metaKey) && (evt.ctrlKey !== evt.metaKey)) {
slot = slot.ctrl; slot = slot.ctrl;
} }
if (slot && evt.shiftKey) { if (slot && evt.shiftKey) {
@@ -265,18 +255,13 @@ RED.keyboard = (function() {
if (partialState) { if (partialState) {
partialState = null; partialState = null;
return resolveKeyEvent(evt); return resolveKeyEvent(evt);
} else if (Object.keys(handler).length > 0) {
partialState = handler;
evt.preventDefault();
return null;
} else {
return null;
} }
if (Object.keys(handler).length > 0) {
// check if there's a potential combined handler initiated by this keyCode
for (let h in handler) {
if (matchHandlerToEvent(evt,handler[h]) > -1) {
partialState = handler;
evt.preventDefault();
break;
}
}
}
return null;
} else { } else {
var depth = Infinity; var depth = Infinity;
var matchedHandler; var matchedHandler;
@@ -332,7 +317,7 @@ RED.keyboard = (function() {
scope:scope, scope:scope,
key:key, key:key,
user:false user:false
}; }
} }
if (!ondown) { if (!ondown) {
var userAction = getUserKey(cbdown); var userAction = getUserKey(cbdown);
@@ -355,7 +340,7 @@ RED.keyboard = (function() {
} }
} }
} else { } else {
keys.push([key,mod]); keys.push([key,mod])
} }
var slot = handlers; var slot = handlers;
for (i=0;i<keys.length;i++) { for (i=0;i<keys.length;i++) {
@@ -378,7 +363,7 @@ RED.keyboard = (function() {
//slot[key] = {scope: scope, ondown:cbdown}; //slot[key] = {scope: scope, ondown:cbdown};
} }
slot.handlers = slot.handlers || []; slot.handlers = slot.handlers || [];
slot.handlers.push({scope:scope,ondown:cbdown}); slot.handlers.push({scope:scope,ondown:cbdown})
slot.scope = scope; slot.scope = scope;
slot.ondown = cbdown; slot.ondown = cbdown;
} }
@@ -395,12 +380,12 @@ RED.keyboard = (function() {
if (parsedKey) { if (parsedKey) {
keys.push(parsedKey); keys.push(parsedKey);
} else { } else {
console.log("Unrecognised key specifier:",key); console.log("Unrecognised key specifier:",key)
return; return;
} }
} }
} else { } else {
keys.push([key,mod]); keys.push([key,mod])
} }
var slot = handlers; var slot = handlers;
for (i=0;i<keys.length;i++) { for (i=0;i<keys.length;i++) {
@@ -422,7 +407,7 @@ RED.keyboard = (function() {
} }
if (typeof slot.ondown === "string") { if (typeof slot.ondown === "string") {
if (typeof modifiers === 'boolean' && modifiers) { if (typeof modifiers === 'boolean' && modifiers) {
actionToKeyMap[slot.ondown] = {user: modifiers}; actionToKeyMap[slot.ondown] = {user: modifiers}
} else { } else {
delete actionToKeyMap[slot.ondown]; delete actionToKeyMap[slot.ondown];
} }
@@ -438,11 +423,11 @@ RED.keyboard = (function() {
function formatKey(key,plain) { function formatKey(key,plain) {
var formattedKey = isMac?key.replace(/ctrl-?/,"&#8984;"):key; var formattedKey = isMac?key.replace(/ctrl-?/,"&#8984;"):key;
formattedKey = isMac?formattedKey.replace(/alt-?/,"&#8997;"):key; formattedKey = isMac?formattedKey.replace(/alt-?/,"&#8997;"):key;
formattedKey = formattedKey.replace(/shift-?/,"&#8679;"); formattedKey = formattedKey.replace(/shift-?/,"&#8679;")
formattedKey = formattedKey.replace(/left/,"&#x2190;"); formattedKey = formattedKey.replace(/left/,"&#x2190;")
formattedKey = formattedKey.replace(/up/,"&#x2191;"); formattedKey = formattedKey.replace(/up/,"&#x2191;")
formattedKey = formattedKey.replace(/right/,"&#x2192;"); formattedKey = formattedKey.replace(/right/,"&#x2192;")
formattedKey = formattedKey.replace(/down/,"&#x2193;"); formattedKey = formattedKey.replace(/down/,"&#x2193;")
if (plain) { if (plain) {
return formattedKey; return formattedKey;
} }
@@ -466,6 +451,7 @@ RED.keyboard = (function() {
var container = $(this); var container = $(this);
var object = container.data('data'); var object = container.data('data');
if (!container.hasClass('keyboard-shortcut-entry-expanded')) { if (!container.hasClass('keyboard-shortcut-entry-expanded')) {
endEditShortcut(); endEditShortcut();
@@ -489,7 +475,7 @@ RED.keyboard = (function() {
} }
$(this).toggleClass("input-error",!valid); $(this).toggleClass("input-error",!valid);
okButton.attr("disabled",!valid); okButton.attr("disabled",!valid);
}); })
var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope); var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope);
scopeSelect.i18n(); scopeSelect.i18n();
@@ -499,7 +485,7 @@ RED.keyboard = (function() {
scopeSelect.val(object.scope||'*'); scopeSelect.val(object.scope||'*');
scopeSelect.on("change", function() { scopeSelect.on("change", function() {
keyInput.trigger("change"); keyInput.trigger("change");
}); })
var div = $('<div class="keyboard-shortcut-edit button-group-vertical"></div>').appendTo(scope); var div = $('<div class="keyboard-shortcut-edit button-group-vertical"></div>').appendTo(scope);
var okButton = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-check"></i></button>').appendTo(div); var okButton = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-check"></i></button>').appendTo(div);
@@ -525,13 +511,10 @@ RED.keyboard = (function() {
id:object.id, id:object.id,
scope:shortcut?shortcut.scope:undefined, scope:shortcut?shortcut.scope:undefined,
key:shortcut?shortcut.key:undefined, key:shortcut?shortcut.key:undefined,
user:shortcut?shortcut.user:undefined, user:shortcut?shortcut.user:undefined
}
label: object.label,
options: object.options,
};
buildShortcutRow(container,obj); buildShortcutRow(container,obj);
}); })
keyInput.trigger("focus"); keyInput.trigger("focus");
} }
@@ -566,7 +549,7 @@ RED.keyboard = (function() {
delete object.scope; delete object.scope;
} else { } else {
keyDiv.parent().removeClass("keyboard-shortcut-entry-unassigned"); keyDiv.parent().removeClass("keyboard-shortcut-entry-unassigned");
keyDiv.append(RED.keyboard.formatKey(key)); keyDiv.append(RED.keyboard.formatKey(key))
$("<span>").text(scope).appendTo(scopeDiv); $("<span>").text(scope).appendTo(scopeDiv);
object.key = key; object.key = key;
object.scope = scope; object.scope = scope;
@@ -579,7 +562,7 @@ RED.keyboard = (function() {
userKeymap[object.id] = { userKeymap[object.id] = {
scope:shortcut.scope, scope:shortcut.scope,
key:shortcut.key key:shortcut.key
}; }
RED.settings.set('editor.keymap',userKeymap); RED.settings.set('editor.keymap',userKeymap);
} }
} }
@@ -595,7 +578,13 @@ RED.keyboard = (function() {
var item = $('<div class="keyboard-shortcut-entry">').appendTo(container); var item = $('<div class="keyboard-shortcut-entry">').appendTo(container);
container.data('data',object); container.data('data',object);
var text = object.label; var text = object.id.replace(/(^.+:([a-z]))|(-([a-z]))/g,function() {
if (arguments[5] === 0) {
return arguments[2].toUpperCase();
} else {
return " "+arguments[4].toUpperCase();
}
});
var label = $('<div>').addClass("keyboard-shortcut-entry-text").text(text).appendTo(item); var label = $('<div>').addClass("keyboard-shortcut-entry-text").text(text).appendTo(item);
var user = $('<i class="fa fa-user"></i>').prependTo(label); var user = $('<i class="fa fa-user"></i>').prependTo(label);
@@ -630,15 +619,14 @@ RED.keyboard = (function() {
pane.find("#red-ui-settings-tab-keyboard-filter").searchBox({ pane.find("#red-ui-settings-tab-keyboard-filter").searchBox({
delay: 100, delay: 100,
change: function() { change: function() {
var filterValue = $(this).val().trim().toLowerCase(); var filterValue = $(this).val().trim();
if (filterValue === "") { if (filterValue === "") {
shortcutList.editableList('filter', null); shortcutList.editableList('filter', null);
} else { } else {
filterValue = filterValue.replace(/\s/g,""); filterValue = filterValue.replace(/\s/g,"");
shortcutList.editableList('filter', function(data) { shortcutList.editableList('filter', function(data) {
var label = data.label.toLowerCase(); return data.id.toLowerCase().replace(/^.*:/,"").replace("-","").indexOf(filterValue) > -1;
return label.indexOf(filterValue) > -1; })
});
} }
} }
}); });
@@ -659,9 +647,9 @@ RED.keyboard = (function() {
}); });
var shortcuts = RED.actions.list(); var shortcuts = RED.actions.list();
shortcuts.sort(function(A,B) { shortcuts.sort(function(A,B) {
var Akey = A.label; var Aid = A.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
var Bkey = B.label; var Bid = B.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
return Akey.localeCompare(Bkey); return Aid.localeCompare(Bid);
}); });
knownShortcuts = new Set(); knownShortcuts = new Set();
shortcuts.forEach(function(s) { shortcuts.forEach(function(s) {

237
packages/node_modules/@node-red/editor-client/src/js/ui/library.js vendored Normal file → Executable file
View File

@@ -27,7 +27,7 @@ RED.library = (function() {
'<div class="red-ui-panel" id="red-ui-library-dialog-load-browser"></div>'+ '<div class="red-ui-panel" id="red-ui-library-dialog-load-browser"></div>'+
'<div class="red-ui-panel">'+ '<div class="red-ui-panel">'+
'<div id="red-ui-library-dialog-load-preview">'+ '<div id="red-ui-library-dialog-load-preview">'+
'<div class="red-ui-panel" id="red-ui-library-dialog-load-preview-text" style="position:relative; height: 50%; overflow-y: hidden;"></div>'+ '<div class="red-ui-panel" id="red-ui-library-dialog-load-preview-text"></div>'+
'<div class="red-ui-panel" id="red-ui-library-dialog-load-preview-details">'+ '<div class="red-ui-panel" id="red-ui-library-dialog-load-preview-details">'+
'<table id="red-ui-library-dialog-load-preview-details-table" class="red-ui-info-table"></table>'+ '<table id="red-ui-library-dialog-load-preview-details-table" class="red-ui-info-table"></table>'+
'</div>'+ '</div>'+
@@ -216,27 +216,21 @@ RED.library = (function() {
{ id:'node-input-'+options.type+'-menu-open-library', { id:'node-input-'+options.type+'-menu-open-library',
label: RED._("library.openLibrary"), label: RED._("library.openLibrary"),
onselect: function() { onselect: function() {
var editorOpts = {
id: 'red-ui-library-dialog-load-preview-text', libraryEditor = ace.edit('red-ui-library-dialog-load-preview-text',{
mode: options.mode, useWorker: false
});
libraryEditor.setTheme("ace/theme/tomorrow");
if (options.mode) {
libraryEditor.getSession().setMode(options.mode);
}
libraryEditor.setOptions({
readOnly: true, readOnly: true,
highlightActiveLine: false, highlightActiveLine: false,
highlightGutterLine: false, highlightGutterLine: false
contextmenu: false });
} libraryEditor.renderer.$cursorLayer.element.style.opacity=0;
libraryEditor = RED.editor.createEditor(editorOpts); //use red.editor libraryEditor.$blockScrolling = Infinity;
if(libraryEditor.isACE) {
if (options.mode) {
libraryEditor.getSession().setMode(options.mode);
}
libraryEditor.setOptions({
readOnly: true,
highlightActiveLine: false,
highlightGutterLine: false
});
libraryEditor.renderer.$cursorLayer.element.style.opacity=0;
libraryEditor.$blockScrolling = Infinity;
}
activeLibrary = options; activeLibrary = options;
var listing = []; var listing = [];
@@ -363,112 +357,106 @@ RED.library = (function() {
options.onconfirm(item); options.onconfirm(item);
} }
}); });
var itemTools = null; var itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
.on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
var elementPos = menuButton.offset();
var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu",
options: [
{id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
var defaultFolderName = "new-folder";
var defaultFolderNameMatches = {};
var selected = dirList.treeList('selected');
if (!selected.children) {
selected = selected.parent;
}
var complete = function() {
selected.children.forEach(function(c) {
if (/^new-folder/.test(c.label)) {
defaultFolderNameMatches[c.label] = true
}
});
var folderIndex = 2;
while(defaultFolderNameMatches[defaultFolderName]) {
defaultFolderName = "new-folder-"+(folderIndex++)
}
selected.treeList.expand();
var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
var newItem = {
icon: "fa fa-folder-o",
children:[],
path: selected.path,
element: input
}
var confirmAdd = function() {
var val = input.val().trim();
if (val === "") {
cancelAdd();
return;
} else {
for (var i=0;i<selected.children.length;i++) {
if (selected.children[i].label === val) {
cancelAdd();
return;
}
}
}
newItem.treeList.remove();
var finalItem = {
library: selected.library,
type: selected.type,
icon: "fa fa-folder",
children:[],
label: val,
path: newItem.path+val+"/"
}
selected.treeList.addChild(finalItem,true);
}
var cancelAdd = function() {
newItem.treeList.remove();
}
input.on('keydown', function(evt) {
evt.stopPropagation();
if (evt.keyCode === 13) {
confirmAdd();
} else if (evt.keyCode === 27) {
cancelAdd();
}
})
input.on("blur", function() {
confirmAdd();
})
selected.treeList.addChild(newItem);
setTimeout(function() {
input.trigger("focus");
input.select();
},400);
}
selected.treeList.expand(complete);
} },
// null,
// {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} },
// {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} }
]
}).on('mouseleave', function(){ $(this).remove(); dirList.focus() })
.on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)})
.appendTo("body");
menuOptionMenu.css({
position: "absolute",
top: elementPos.top+"px",
left: (elementPos.left - menuOptionMenu.width() + 20)+"px"
}).show();
}).appendTo(itemTools);
if (options.folderTools) { if (options.folderTools) {
dirList.on('treelistselect', function(event, item) { dirList.on('treelistselect', function(event, item) {
if (item.writable !== false && item.treeList) { if (item.writable !== false && item.treeList) {
if (itemTools) {
itemTools.remove();
}
itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
.on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
var elementPos = menuButton.offset();
var menuOptionMenu
= RED.menu.init({id:"red-ui-library-browser-menu",
options: [
{id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
var defaultFolderName = "new-folder";
var defaultFolderNameMatches = {};
var selected = dirList.treeList('selected');
if (!selected.children) {
selected = selected.parent;
}
var complete = function() {
selected.children.forEach(function(c) {
if (/^new-folder/.test(c.label)) {
defaultFolderNameMatches[c.label] = true
}
});
var folderIndex = 2;
while(defaultFolderNameMatches[defaultFolderName]) {
defaultFolderName = "new-folder-"+(folderIndex++)
}
selected.treeList.expand();
var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
var newItem = {
icon: "fa fa-folder-o",
children:[],
path: selected.path,
element: input
}
var confirmAdd = function() {
var val = input.val().trim();
if (val === "") {
cancelAdd();
return;
} else {
for (var i=0;i<selected.children.length;i++) {
if (selected.children[i].label === val) {
cancelAdd();
return;
}
}
}
newItem.treeList.remove();
var finalItem = {
library: selected.library,
type: selected.type,
icon: "fa fa-folder",
children:[],
label: val,
path: newItem.path+val+"/"
}
selected.treeList.addChild(finalItem,true);
}
var cancelAdd = function() {
newItem.treeList.remove();
}
input.on('keydown', function(evt) {
evt.stopPropagation();
if (evt.keyCode === 13) {
confirmAdd();
} else if (evt.keyCode === 27) {
cancelAdd();
}
})
input.on("blur", function() {
confirmAdd();
})
selected.treeList.addChild(newItem);
setTimeout(function() {
input.trigger("focus");
input.select();
},400);
}
selected.treeList.expand(complete);
} },
// null,
// {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} },
// {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} }
]
}).on('mouseleave', function(){ $(this).remove(); dirList.focus() })
.on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)})
.appendTo("body");
menuOptionMenu.css({
position: "absolute",
top: elementPos.top+"px",
left: (elementPos.left - menuOptionMenu.width() + 20)+"px"
}).show();
}).appendTo(itemTools);
itemTools.appendTo(item.treeList.label); itemTools.appendTo(item.treeList.label);
} }
}); });
@@ -542,7 +530,7 @@ RED.library = (function() {
// evt.preventDefault(); // evt.preventDefault();
// var icon = libraryFields['icon'].input.val() || ""; // var icon = libraryFields['icon'].input.val() || "";
// var iconPath = (icon ? RED.utils.separateIconPath(icon) : {}); // var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
// RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) { // RED.editor.showIconPicker(iconButton, null, iconPath, true, function (newIcon) {
// iconButton.empty(); // iconButton.empty();
// var path = newIcon || ""; // var path = newIcon || "";
// var newPath = RED.utils.separateIconPath(path); // var newPath = RED.utils.separateIconPath(path);
@@ -821,7 +809,6 @@ RED.library = (function() {
open: function(e) { open: function(e) {
RED.keyboard.disable(); RED.keyboard.disable();
$(this).parent().find(".ui-dialog-titlebar-close").hide(); $(this).parent().find(".ui-dialog-titlebar-close").hide();
libraryEditor.resize();
}, },
close: function(e) { close: function(e) {
RED.keyboard.enable(); RED.keyboard.enable();

Some files were not shown because too many files have changed in this diff Show More