Compare commits

..

1 Commits

Author SHA1 Message Date
Dave Conway-Jones
499d22daca Add start script to default project package 2018-04-05 11:30:16 +01:00
689 changed files with 10848 additions and 33760 deletions

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
/packages/node_modules/** linguist-generated=false

View File

@@ -8,9 +8,7 @@ If your issue is:
- a feature request or suggestion for a change,
- or problems with 3rd party (`node-red-contrib-`) nodes
please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
please use the [mailing list](https://groups.google.com/forum/#!forum/node-red), [slack team](https://nodered.org/slack) or ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
That way the whole Node-RED user community can help, rather than rely on the core development team.

View File

@@ -16,7 +16,7 @@ Put an `x` in the boxes that apply
<!--
If you want to raise a pull-request with a new feature, or a refactoring
of existing code, it **may well get rejected** if it hasn't been discussed on
the [forum](https://discourse.nodered.org) or
the [mailing list](https://groups.google.com/forum/#!forum/node-red) or
[slack team](https://nodered.org/slack) first.
-->

4
.gitignore vendored
View File

@@ -17,7 +17,3 @@ node_modules
public
locales/zz-ZZ
nodes/core/locales/zz-ZZ
!packages/node_modules
packages/node_modules/@node-red/editor-client/public
!test/**/node_modules
docs

7
.npmignore Normal file
View File

@@ -0,0 +1,7 @@
.settings
.jshintignore
.jshintrc
.project
.tern-project
.travis.yml
.git

View File

@@ -1,10 +1,20 @@
sudo: false
language: node_js
matrix:
include:
- node_js: "10"
script:
- ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
before_script:
- npm install -g istanbul coveralls
- node_js: "8"
env:
- CXX="g++-4.8"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- gcc-4.8
node_js:
- "8"
- "6"
- "4"
script:
- istanbul cover ./node_modules/.bin/grunt --report lcovonly && istanbul report text && ( cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js || true ) && rm -rf coverage
before_script:
- npm install -g istanbul
- npm install coveralls

View File

@@ -1,195 +1,3 @@
#### 0.19.4: Maintenance Release
- Fix race condition in non-cache lfs context Fixes #1888
- LocalFileSystem Context: Remove extra flush code
- Prevent race condition in caching mode of lfs context (#1889)
- Allow context store name to be provided in the key
- Switch node: only use promises when absolutely necessary
- Fix dbl-click handling on webkit-based browsers
- Ensure context.flow/global cannot be deleted or enumerated
- Handle context.get with multiple levels of unknown key Fixes #1883
- Fix global.get("foo.bar") for functionGlobalContext set values
- Fix node color bug (#1877)
- Merge pull request #1857 from cclauss/patch-1
- Define raw_input() in Python 3 & fix time.sleep()
#### 0.19.3: Maintenance Release
- Split node - fix complete to send msg for k/v object
- Remove unused Join node merged object key typed input
- Set the JavaScript editor to full-screen
- Filter global modules installed locally
- Add svg to permitted icon extension list
- Debug node - indicate status all the time if selected to do so
- pi nodes - increase test coverage slightly
- TCP-request node - only write payload
- JSON schema: perform validation when obj -> obj or str -> str
- JSON schema: add draft-06 support (via $schema keyword)
- Mqtt proxy configuration for websocket connection, #1651.
- Allows MQTT Shared Subscriptions for MQTT-In core node
- Fix use of HTML tag or CSS class specification as icon of typedInput
#### 0.19.2: Maintenance Release
- Ensure node default colour is used if palette.theme has no match
- fix lost messages / properties in TCPRequest Node; closes #1863 (#1864)
- Fix typo in template.html
- Improve error reporting from context plugin loading
- Prevent no-op edit of node marking as changed due to icon
- Change node must handle empty rule set
#### 0.19.1: Maintenance Release
- Pull in latest twitter node
- Handle windows paths for context storage
- Handle persisting objects with circular refs in context
- Ensure js editor can expand to fill available space
- Add example localfilesystem contextStorage to settings
- Fix template node handling of nested context tags
#### 0.19: Milestone Release
Editor
- Add editorTheme.palette.theme to allow overriding colours
- Index all node properties when searching Fixes #1446
- Handle NaN and Infinity properly in debug sidebar Fixes #1778 #1779
- Prevent horizontal scroll when palette name cannot wrap
- Ignore middle-click on node/ports to enable panning
- Better wire layout when looping back
- fix appearence of retry button of remote branch management dialog
- Handle releasing ctrl when using quick-add node dialog
- Add $env function to JSONata expressions
- Widen support for env var to use ${} or $() syntax
- Add env-var support to TypedInput
- Show unknown node properties in info tab
- Add node icon picker widget
- Only edit nodes on dbl click on primary button with no modifiers
- Allow subflows to be put in any palette category
- Add flow navigator widget
- Cache flow library result to improve response time Fixes #1753
- Add middle-button-drag to pan the workspace
- allow multi-line category name in editor
- Redesign sidebar tabs
- Do not disable the export-clipboard menu option with empty selection
Nodes
- Change: Ensure runtime errors in Change node can be caught Fixes #1769
- File: Add output to File Out node
- Function: add expandable JavaScript editor pane
- Function: allow id and name reference in function node code (#1731)
- HTTP Request: Move to request module
- HTTP: Ensure apiMaxLength applies to HTTP Nodes Fixes #1278
- Join: accumulate top level properties
- Join: allow environment variable as reduce init value
- JSON: add JSON schema validation via msg.schema
- Pi: Let nrgpio code work with python 3
- Pi: let Pi nodes be visible/editable on all platforms
- Switch: add isEmpty rule
- TCP: queue messages while connecting; closes #1414
- TLS: Add servername option to TLS config node for SNI Fixes #1805
- UDP: Don't accidentally re-use udp port when set to not do so
Persistent Context
- Add Context data sidebar
- Add persistable context option
- Add default memory store
- Add file-based context store
- Add async mode to evaluateJSONataExpression
- Update RED.util.evaluateNodeProperty to support context stores
Runtime
- Support flow.disabled and .info in /flow API
- Node errors should be Strings not Errors Fixes #1781
- Add detection of connection timeout in git communication Fixes #1770
- Handle loading empty nodesDir
- Add 'private' property to userDir generated package.json
- Add RED.require to allow nodes to access other modules
- Ensure add/remove modules are run sequentially
#### 0.18.7: Maintenance Release
Editor Fixes
- Do not trim wires if node declares outputs in defaults but misses value Fixes #1737
Node Fixes
- Relax twitter node version ready for major version bump
- Pass Date into the Function node sandbox to fix instanceof tests
- let TCP in node report remote ip and port when in single packet mode
- typo fix in node help (#1735)
Other Fixes
- Tidy up default grunt task and fixup test break due to reorder Fixes #1738
- Bump jsonata version
#### 0.18.6: Maintenance Release
Editor Fixes
- Handle a node having wires in the editor on ports it no longer has Fixes #1724
- Add missing ACE snippet files
- Fix wireClippedNodes is not defined Fixes #1726
- Split node html to isolate bad nodes when loading
- Avoid unnecessary use of .html() where .text() will do
- Add editorTheme.projects.enabled to default settings.js"
#### 0.18.5: Maintenance Release
Projects
- Add clone project to welcome screen
- Handle cloning a project without package.json
- Keep remote branch state in sync between editor and runtime
New Features
- Add type checks to switch node options (#1714)
- add output property select to HTML parse node (#1701)
- Add Prevent Following Redirect to HTTP Request node (#615) (#1684)
- Add debug and trace functions to function node (#1654)
- Enable user defined icon for subflow
- Add MQTT disconnect message and rework broker node UI (#1719)
- Japanese message catalogue updates (#1723)
- Show node load errors in the Palette Manager view
Editor Fixes
- Highlight subflow node when log msg comes from inside Fixes #1698
- Ensure node wires array is not longer than outputs value Fixes #1678
- Allow importing an unknown config node to be undone Fixes #1681
- Ensure keyboard shortcuts get saved in runtime settings Fixes #1696
- Don't mark a subflow changed when actually modified nothing (#1665)
Node Fixes
- bind to correct port when doing udp broadcast/multicast (#1686)
- Provide full error stack in Function node log message (#1700)
- Fix http request doc type Fixes #1690
- Make debug slightly larger to pass WCAG AA rating
- Make core nodes labels more consistent, to close #1673
- Allow template node to be updated more than once Fixes #1671
- Fix the problem that output labels of switch node sometimes disappear (#1664)
- Chinese translations for core nodes (#1607)
Runtime Fixes
- Handle and display for invalid flow credentials when project is disabled #1689 (#1694)
- node-red-pi: fix behavior with old bash version (#1713)
- Fix ENOENT error on first start when no user dir (#1711)
- Handle null error object in Flow.handleError Fixes #1721
- update settings comments to describe how to setup for ipv6 (#1675)
- Remove credential props after diffing flow to prevent future false positives Fixes #1359
- Log error if settings unavailable when saving user settings Fixes #1645
- Keep backup of .config.json
- Add warning if using \_credentialSecret from .config.json
- Filter req.user in /settings to prevent potentially leaking info
#### 0.18.4: Maintenance Release
Projects

View File

@@ -30,13 +30,13 @@ At a minimum, please include:
## Feature requests
For feature requests, please raise them on the [forum](https://discourse.nodered.org).
For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red).
## Pull-Requests
If you want to raise a pull-request with a new feature, or a refactoring
of existing code, it may well get rejected if you haven't discussed it on
the [forum](https://discourse.nodered.org) first.
the [mailing list](https://groups.google.com/forum/#!forum/node-red) first.
All contributors need to sign the JS Foundation's Contributor License Agreement.
It is an online process and quick to do. You can read the details of the agreement

View File

@@ -24,10 +24,6 @@ module.exports = function(grunt) {
nodemonArgs.push(flowFile);
}
var nonHeadless = grunt.option('non-headless');
if (nonHeadless) {
process.env.NODE_RED_NON_HEADLESS = 'true';
}
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
paths: {
@@ -42,7 +38,7 @@ module.exports = function(grunt) {
reporter: 'spec'
},
all: { src: ['test/**/*_spec.js'] },
core: { src: ["test/_spec.js","test/unit/**/*_spec.js"]},
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
nodes: { src: ["test/nodes/**/*_spec.js"]}
},
webdriver: {
@@ -59,8 +55,8 @@ module.exports = function(grunt) {
reportFormats: ['lcov','html'],
print: 'both'
},
all: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js","test/nodes/**/*_spec.js"] },
core: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js"]},
all: { src: ['test/**/*_spec.js'] },
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
nodes: { src: ["test/nodes/**/*_spec.js"]}
},
jshint: {
@@ -80,14 +76,16 @@ module.exports = function(grunt) {
all: [
'Gruntfile.js',
'red.js',
'packages/**/*.js'
'red/**/*.js',
'nodes/core/*/*.js',
'editor/js/**/*.js'
],
core: {
files: {
src: [
'Gruntfile.js',
'red.js',
'packages/**/*.js',
'red/**/*.js'
]
}
},
@@ -118,81 +116,78 @@ module.exports = function(grunt) {
src: [
// Ensure editor source files are concatenated in
// the right order
"packages/node_modules/@node-red/editor-client/src/js/red.js",
"packages/node_modules/@node-red/editor-client/src/js/events.js",
"packages/node_modules/@node-red/editor-client/src/js/i18n.js",
"packages/node_modules/@node-red/editor-client/src/js/settings.js",
"packages/node_modules/@node-red/editor-client/src/js/user.js",
"packages/node_modules/@node-red/editor-client/src/js/comms.js",
"packages/node_modules/@node-red/editor-client/src/js/text/bidi.js",
"packages/node_modules/@node-red/editor-client/src/js/text/format.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/state.js",
"packages/node_modules/@node-red/editor-client/src/js/nodes.js",
"packages/node_modules/@node-red/editor-client/src/js/history.js",
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/searchBox.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/view.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/sidebar.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/palette.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tray.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/notifications.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/search.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js"
"editor/js/red.js",
"editor/js/events.js",
"editor/js/i18n.js",
"editor/js/settings.js",
"editor/js/user.js",
"editor/js/comms.js",
"editor/js/text/bidi.js",
"editor/js/text/format.js",
"editor/js/ui/state.js",
"editor/js/nodes.js",
"editor/js/history.js",
"editor/js/validators.js",
"editor/js/ui/utils.js",
"editor/js/ui/common/editableList.js",
"editor/js/ui/common/checkboxSet.js",
"editor/js/ui/common/menu.js",
"editor/js/ui/common/panels.js",
"editor/js/ui/common/popover.js",
"editor/js/ui/common/searchBox.js",
"editor/js/ui/common/tabs.js",
"editor/js/ui/common/stack.js",
"editor/js/ui/common/typedInput.js",
"editor/js/ui/actions.js",
"editor/js/ui/deploy.js",
"editor/js/ui/diff.js",
"editor/js/ui/keyboard.js",
"editor/js/ui/workspaces.js",
"editor/js/ui/view.js",
"editor/js/ui/sidebar.js",
"editor/js/ui/palette.js",
"editor/js/ui/tab-info.js",
"editor/js/ui/tab-config.js",
"editor/js/ui/palette-editor.js",
"editor/js/ui/editor.js",
"editor/js/ui/tray.js",
"editor/js/ui/clipboard.js",
"editor/js/ui/library.js",
"editor/js/ui/notifications.js",
"editor/js/ui/search.js",
"editor/js/ui/typeSearch.js",
"editor/js/ui/subflow.js",
"editor/js/ui/userSettings.js",
"editor/js/ui/projects/projects.js",
"editor/js/ui/projects/projectSettings.js",
"editor/js/ui/projects/projectUserSettings.js",
"editor/js/ui/projects/tab-versionControl.js",
"editor/js/ui/touch/radialMenu.js"
],
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
dest: "public/red/red.js"
},
vendor: {
files: {
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.js": [
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-1.11.3.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/bootstrap/js/bootstrap.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js"
"public/vendor/vendor.js": [
"editor/vendor/jquery/js/jquery-1.11.3.min.js",
"editor/vendor/bootstrap/js/bootstrap.min.js",
"editor/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js",
"editor/vendor/jquery/js/jquery.ui.touch-punch.min.js",
"editor/vendor/marked/marked.min.js",
"editor/vendor/d3/d3.v3.min.js",
"editor/vendor/i18next/i18next.min.js"
],
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
"public/vendor/vendor.css": [
// TODO: resolve relative resource paths in
// bootstrap/FA/jquery
],
"packages/node_modules/@node-red/editor-client/public/vendor/jsonata/jsonata.min.js": [
"public/vendor/jsonata/jsonata.min.js": [
"node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js"
"editor/vendor/jsonata/formatter.js"
],
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
"public/vendor/ace/worker-jsonata.js": [
"node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
"editor/vendor/jsonata/worker-jsonata.js"
]
}
}
@@ -200,10 +195,10 @@ module.exports = function(grunt) {
uglify: {
build: {
files: {
'packages/node_modules/@node-red/editor-client/public/red/red.min.js': 'packages/node_modules/@node-red/editor-client/public/red/red.js',
'packages/node_modules/@node-red/editor-client/public/red/main.min.js': 'packages/node_modules/@node-red/editor-client/public/red/main.js',
'packages/node_modules/@node-red/editor-client/public/vendor/ace/mode-jsonata.js': 'packages/node_modules/@node-red/editor-client/src/vendor/jsonata/mode-jsonata.js',
'packages/node_modules/@node-red/editor-client/public/vendor/ace/snippets/jsonata.js': 'packages/node_modules/@node-red/editor-client/src/vendor/jsonata/snippets-jsonata.js'
'public/red/red.min.js': 'public/red/red.js',
'public/red/main.min.js': 'public/red/main.js',
'public/vendor/ace/mode-jsonata.js': 'editor/vendor/jsonata/mode-jsonata.js',
'public/vendor/ace/snippets/jsonata.js': 'editor/vendor/jsonata/snippets-jsonata.js'
}
}
},
@@ -213,50 +208,50 @@ module.exports = function(grunt) {
outputStyle: 'compressed'
},
files: [{
dest: 'packages/node_modules/@node-red/editor-client/public/red/style.min.css',
src: 'packages/node_modules/@node-red/editor-client/src/sass/style.scss'
dest: 'public/red/style.min.css',
src: 'editor/sass/style.scss'
},
{
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/bootstrap/css/bootstrap.min.css',
src: 'packages/node_modules/@node-red/editor-client/src/vendor/bootstrap/css/bootstrap.css'
dest: 'public/vendor/bootstrap/css/bootstrap.min.css',
src: 'editor/vendor/bootstrap/css/bootstrap.css'
}]
}
},
jsonlint: {
messages: {
src: [
'packages/node_modules/@node-red/nodes/locales/**/*.json',
'packages/node_modules/@node-red/editor-api/lib/editor/locales/**/*.json',
'packages/node_modules/@node-red/runtime/locales/**/*.json'
'nodes/core/locales/en-US/messages.json',
'red/api/locales/en-US/editor.json',
'red/runtime/locales/en-US/runtime.json'
]
},
keymaps: {
src: [
'packages/node_modules/@node-red/editor-client/src/js/keymap.json'
'editor/js/keymap.json'
]
}
},
attachCopyright: {
js: {
src: [
'packages/node_modules/@node-red/editor-client/public/red/red.min.js',
'packages/node_modules/@node-red/editor-client/public/red/main.min.js'
'public/red/red.min.js',
'public/red/main.min.js'
]
},
css: {
src: [
'packages/node_modules/@node-red/editor-client/public/red/style.min.css'
'public/red/style.min.css'
]
}
},
clean: {
build: {
src: [
"packages/node_modules/@node-red/editor-client/public/red",
"packages/node_modules/@node-red/editor-client/public/index.html",
"packages/node_modules/@node-red/editor-client/public/favicon.ico",
"packages/node_modules/@node-red/editor-client/public/icons",
"packages/node_modules/@node-red/editor-client/public/vendor"
"public/red",
"public/index.html",
"public/favicon.ico",
"public/icons",
"public/vendor"
]
},
release: {
@@ -268,27 +263,27 @@ module.exports = function(grunt) {
watch: {
js: {
files: [
'packages/node_modules/@node-red/editor-client/src/js/**/*.js'
'editor/js/**/*.js'
],
tasks: ['copy:build','concat','uglify','attachCopyright:js']
},
sass: {
files: [
'packages/node_modules/@node-red/editor-client/src/sass/**/*.scss'
'editor/sass/**/*.scss'
],
tasks: ['sass','attachCopyright:css']
},
json: {
files: [
'packages/node_modules/@node-red/nodes/locales/**/*.json',
'packages/node_modules/@node-red/editor-api/lib/editor/locales/**/*.json',
'packages/node_modules/@node-red/runtime/locales/**/*.json'
'nodes/core/locales/en-US/messages.json',
'red/api/locales/en-US/editor.json',
'red/runtime/locales/en-US/runtime.json'
],
tasks: ['jsonlint:messages']
},
keymaps: {
files: [
'packages/node_modules/@node-red/editor-client/src/js/keymap.json'
'editor/js/keymap.json'
],
tasks: ['jsonlint:keymaps','copy:build']
},
@@ -303,13 +298,12 @@ module.exports = function(grunt) {
nodemon: {
/* uses .nodemonignore */
dev: {
script: 'packages/node_modules/node-red/red.js',
script: 'red.js',
options: {
args: nodemonArgs,
ext: 'js,html,json',
watch: [
'packages/node_modules',
'!packages/node_modules/@node-red/editor-client'
'red','nodes'
]
}
}
@@ -328,21 +322,21 @@ module.exports = function(grunt) {
build: {
files:[
{
src: 'packages/node_modules/@node-red/editor-client/src/js/main.js',
dest: 'packages/node_modules/@node-red/editor-client/public/red/main.js'
src: 'editor/js/main.js',
dest: 'public/red/main.js'
},
{
src: 'packages/node_modules/@node-red/editor-client/src/js/keymap.json',
dest: 'packages/node_modules/@node-red/editor-client/public/red/keymap.json'
src: 'editor/js/keymap.json',
dest: 'public/red/keymap.json'
},
{
cwd: 'packages/node_modules/@node-red/editor-client/src/images',
cwd: 'editor/images',
src: '**',
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/red/images/'
dest: 'public/red/images/'
},
{
cwd: 'packages/node_modules/@node-red/editor-client/src/vendor',
cwd: 'editor/vendor',
src: [
'ace/**',
//'bootstrap/css/**',
@@ -351,25 +345,46 @@ module.exports = function(grunt) {
'font-awesome/**'
],
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/'
dest: 'public/vendor/'
},
{
cwd: 'packages/node_modules/@node-red/editor-client/src/icons',
cwd: 'editor/icons',
src: '**',
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/icons/'
dest: 'public/icons/'
},
{
expand: true,
src: ['packages/node_modules/@node-red/editor-client/src/index.html','packages/node_modules/@node-red/editor-client/src/favicon.ico'],
dest: 'packages/node_modules/@node-red/editor-client/public/',
src: ['editor/index.html','editor/favicon.ico'],
dest: 'public/',
flatten: true
},
{
src: 'CHANGELOG.md',
dest: 'packages/node_modules/@node-red/editor-client/public/red/about'
dest: 'public/red/about'
}
]
},
release: {
files: [{
mode: true,
expand: true,
src: [
'*.md',
'LICENSE',
'package.json',
'settings.js',
'red.js',
'lib/.gitignore',
'nodes/*.demo',
'nodes/core/**',
'red/**',
'public/**',
'editor/templates/**',
'bin/**'
],
dest: path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>')
}]
}
},
chmod: {
@@ -378,8 +393,8 @@ module.exports = function(grunt) {
},
release: {
src: [
"packages/node_modules/@node-red/nodes/core/hardware/nrgpio",
"packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/node-red-*sh"
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*'),
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/red/runtime/storage/localfilesystem/projects/git/node-red-*sh')
]
}
},
@@ -389,43 +404,8 @@ module.exports = function(grunt) {
archive: '<%= paths.dist %>/node-red-<%= pkg.version %>.zip'
},
expand: true,
cwd: 'packages/node_modules/',
src: [
'**',
'!@node-red/editor-client/src/**'
]
}
},
jsdoc : {
runtimeAPI: {
src: 'packages/node_modules/@node-red/runtime/lib/api/*.js',
options: {
destination: 'docs',
configure: './jsdoc.json'
}
},
nodeREDUtil: {
src: 'packages/node_modules/@node-red/util/**/*.js',
options: {
destination: 'packages/node_modules/@node-red/util/docs',
configure: './jsdoc.json'
}
}
},
jsdoc2md: {
runtimeAPI: {
options: {
separators: true
},
src: 'packages/node_modules/@node-red/runtime/lib/api/*.js',
dest: 'docs/runtime-api.md'
},
nodeREDUtil: {
options: {
separators: true
},
src: 'packages/node_modules/@node-red/util/**/*.js',
dest: 'packages/node_modules/@node-red/util/docs/api.md'
cwd: '<%= paths.dist %>/',
src: ['node-red-<%= pkg.version %>/**']
}
}
});
@@ -445,8 +425,6 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-jsonlint');
grunt.loadNpmTasks('grunt-mocha-istanbul');
grunt.loadNpmTasks('grunt-webdriver');
grunt.loadNpmTasks('grunt-jsdoc');
grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
grunt.registerMultiTask('attachCopyright', function() {
var files = this.data.src;
@@ -488,15 +466,6 @@ module.exports = function(grunt) {
}
});
grunt.registerTask('verifyPackageDependencies', function() {
var verifyDependencies = require("./scripts/verify-package-dependencies.js");
var failures = verifyDependencies();
if (failures.length > 0) {
failures.forEach(f => grunt.log.error(f));
grunt.fail.fatal("Failed to verify package dependencies");
}
});
grunt.registerTask('setDevEnv',
'Sets NODE_ENV=development so non-minified assets are used',
function () {
@@ -505,7 +474,7 @@ module.exports = function(grunt) {
grunt.registerTask('default',
'Builds editor content then runs code style checks and unit tests on all components',
['build','verifyPackageDependencies','jshint:editor','mocha_istanbul:all']);
['build','test-core','test-editor','test-nodes']);
grunt.registerTask('test-core',
'Runs code style check and unit tests on core runtime code',
@@ -533,13 +502,9 @@ module.exports = function(grunt) {
grunt.registerTask('release',
'Create distribution zip file',
['build','verifyPackageDependencies','clean:release','chmod:release','compress:release']);
['build','clean:release','copy:release','chmod:release','compress:release']);
grunt.registerTask('coverage',
'Run Istanbul code test coverage task',
['build','mocha_istanbul:all']);
grunt.registerTask('docs',
'Generates API documentation',
['jsdoc','jsdoc2md']);
};

View File

@@ -22,7 +22,8 @@ started.
More documentation can be found [here](http://nodered.org/docs).
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
For further help, or general discussion, please use the
[mailing list](https://groups.google.com/forum/#!forum/node-red).
## Developers
@@ -44,6 +45,9 @@ If you want to run the latest code from git, here's how to get started:
4. Run
npm start
or
node red.js
## Contributing

View File

@@ -31,7 +31,7 @@ done
# Find the real location of this script
CURRENT_PATH=`pwd`
SCRIPT_PATH="${BASH_SOURCE[0]}";
while [ -h "${SCRIPT_PATH}" ]; do
while([ -h "${SCRIPT_PATH}" ]); do
cd "`dirname "${SCRIPT_PATH}"`"
SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")";
done

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 308 B

View File

Before

Width:  |  Height:  |  Size: 603 B

After

Width:  |  Height:  |  Size: 603 B

View File

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 712 B

After

Width:  |  Height:  |  Size: 712 B

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 508 B

After

Width:  |  Height:  |  Size: 508 B

View File

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 575 B

View File

Before

Width:  |  Height:  |  Size: 493 B

After

Width:  |  Height:  |  Size: 493 B

View File

Before

Width:  |  Height:  |  Size: 601 B

After

Width:  |  Height:  |  Size: 601 B

View File

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 459 B

View File

Before

Width:  |  Height:  |  Size: 218 B

After

Width:  |  Height:  |  Size: 218 B

View File

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 324 B

View File

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 378 B

View File

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 255 B

View File

Before

Width:  |  Height:  |  Size: 457 B

After

Width:  |  Height:  |  Size: 457 B

View File

Before

Width:  |  Height:  |  Size: 502 B

After

Width:  |  Height:  |  Size: 502 B

View File

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 449 B

View File

Before

Width:  |  Height:  |  Size: 253 B

After

Width:  |  Height:  |  Size: 253 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 639 B

After

Width:  |  Height:  |  Size: 639 B

View File

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 402 B

View File

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 414 B

View File

Before

Width:  |  Height:  |  Size: 671 B

After

Width:  |  Height:  |  Size: 671 B

View File

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 413 B

View File

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 467 B

After

Width:  |  Height:  |  Size: 467 B

View File

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 423 B

View File

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 360 B

View File

Before

Width:  |  Height:  |  Size: 736 B

After

Width:  |  Height:  |  Size: 736 B

View File

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 482 B

View File

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 273 B

View File

Before

Width:  |  Height:  |  Size: 793 B

After

Width:  |  Height:  |  Size: 793 B

View File

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 256 B

View File

Before

Width:  |  Height:  |  Size: 439 B

After

Width:  |  Height:  |  Size: 439 B

View File

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 592 B

View File

Before

Width:  |  Height:  |  Size: 509 B

After

Width:  |  Height:  |  Size: 509 B

View File

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 488 B

View File

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 628 B

View File

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 258 B

View File

Before

Width:  |  Height:  |  Size: 404 B

After

Width:  |  Height:  |  Size: 404 B

View File

Before

Width:  |  Height:  |  Size: 591 B

After

Width:  |  Height:  |  Size: 591 B

View File

Before

Width:  |  Height:  |  Size: 707 B

After

Width:  |  Height:  |  Size: 707 B

View File

Before

Width:  |  Height:  |  Size: 291 B

After

Width:  |  Height:  |  Size: 291 B

View File

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 289 B

View File

Before

Width:  |  Height:  |  Size: 368 B

After

Width:  |  Height:  |  Size: 368 B

View File

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 290 B

View File

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 392 B

View File

Before

Width:  |  Height:  |  Size: 192 B

After

Width:  |  Height:  |  Size: 192 B

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1019 B

After

Width:  |  Height:  |  Size: 1019 B

View File

Before

Width:  |  Height:  |  Size: 600 B

After

Width:  |  Height:  |  Size: 600 B

View File

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 410 B

View File

Before

Width:  |  Height:  |  Size: 638 B

After

Width:  |  Height:  |  Size: 638 B

View File

Before

Width:  |  Height:  |  Size: 546 B

After

Width:  |  Height:  |  Size: 546 B

View File

Before

Width:  |  Height:  |  Size: 638 B

After

Width:  |  Height:  |  Size: 638 B

View File

Before

Width:  |  Height:  |  Size: 646 B

After

Width:  |  Height:  |  Size: 646 B

View File

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 563 B

View File

Before

Width:  |  Height:  |  Size: 588 B

After

Width:  |  Height:  |  Size: 588 B

View File

Before

Width:  |  Height:  |  Size: 502 B

After

Width:  |  Height:  |  Size: 502 B

View File

@@ -28,24 +28,14 @@ RED.comms = (function() {
function connectWS() {
active = true;
var wspath;
if (RED.settings.apiRootUrl) {
var m = /^(https?):\/\/(.*)$/.exec(RED.settings.apiRootUrl);
if (m) {
console.log(m);
wspath = "ws"+(m[1]==="https"?"s":"")+"://"+m[2]+"comms";
}
} else {
var path = location.hostname;
var port = location.port;
if (port.length !== 0) {
path = path+":"+port;
}
path = path+document.location.pathname;
path = path+(path.slice(-1) == "/"?"":"/")+"comms";
wspath = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path;
var path = location.hostname;
var port = location.port;
if (port.length !== 0) {
path = path+":"+port;
}
path = path+document.location.pathname;
path = path+(path.slice(-1) == "/"?"":"/")+"comms";
path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path;
var auth_tokens = RED.settings.get("auth-tokens");
pendingAuth = (auth_tokens!=null);
@@ -58,7 +48,7 @@ RED.comms = (function() {
}
}
ws = new WebSocket(wspath);
ws = new WebSocket(path);
ws.onopen = function() {
reconnectAttempts = 0;
if (errornotification) {

View File

@@ -16,13 +16,10 @@
RED.i18n = (function() {
var apiRootUrl;
return {
init: function(options, done) {
apiRootUrl = options.apiRootUrl||"";
init: function(done) {
i18n.init({
resGetPath: apiRootUrl+'locales/__ns__?lng=__lng__',
resGetPath: 'locales/__ns__?lng=__lng__',
dynamicLoad: false,
load:'current',
ns: {
@@ -39,7 +36,7 @@ RED.i18n = (function() {
}
},
loadNodeCatalog: function(namespace,done) {
loadCatalog: function(namespace,done) {
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
var toLoad = languageList.length;
languageList.forEach(function(lang) {
@@ -48,7 +45,7 @@ RED.i18n = (function() {
"Accept":"application/json"
},
cache: false,
url: apiRootUrl+'nodes/'+namespace+'/messages?lng='+lang,
url: 'locales/'+namespace+'?lng='+lang,
success: function(data) {
i18n.addResourceBundle(lang,namespace,data);
toLoad--;
@@ -71,7 +68,7 @@ RED.i18n = (function() {
"Accept":"application/json"
},
cache: false,
url: apiRootUrl+'nodes/messages?lng='+lang,
url: 'locales/nodes?lng='+lang,
success: function(data) {
var namespaces = Object.keys(data);
namespaces.forEach(function(ns) {

View File

@@ -10,7 +10,6 @@
"ctrl-g i": "core:show-info-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g c": "core:show-config-tab",
"ctrl-g x": "core:show-context-tab",
"ctrl-e": "core:show-export-dialog",
"ctrl-i": "core:show-import-dialog",
"ctrl-space": "core:toggle-sidebar",

View File

@@ -13,45 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = (function() {
function appendNodeConfig(nodeConfig,done) {
done = done || function(){};
var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim());
var moduleId;
if (m) {
moduleId = m[1];
} else {
moduleId = "unknown";
}
try {
var hasDeferred = false;
var nodeConfigEls = $("<div>"+nodeConfig+"</div>");
nodeConfigEls.find("script").each(function(i,el) {
var srcUrl = $(el).attr('src');
if (srcUrl && !/^\s*(https?:|\/|\.)/.test(srcUrl)) {
$(el).remove();
var newScript = document.createElement("script");
newScript.onload = function() { $("body").append(nodeConfigEls); done() }
$('body').append(newScript);
newScript.src = RED.settings.apiRootUrl+srcUrl;
hasDeferred = true;
}
})
if (!hasDeferred) {
$("body").append(nodeConfigEls);
done();
}
} catch(err) {
RED.notify(RED._("notification.errors.failedToAppendNode",{module:moduleId, error:err.toString()}),{
type: "error",
timeout: 10000
});
console.log("["+moduleId+"] "+err.toString());
done();
}
}
(function() {
function loadNodeList() {
$.ajax({
@@ -93,41 +55,33 @@ var RED = (function() {
cache: false,
url: 'nodes',
success: function(data) {
var configs = data.trim().split(/(?=<!-- --- \[red-module:\S+\] --- -->)/);
var stepConfig = function() {
if (configs.length === 0) {
$("body").i18n();
$("#palette > .palette-spinner").hide();
$(".palette-scroll").removeClass("hide");
$("#palette-search").removeClass("hide");
loadFlows(function() {
if (RED.settings.theme("projects.enabled",false)) {
RED.projects.refresh(function(activeProject) {
RED.sidebar.info.refresh()
if (!activeProject) {
// Projects enabled but no active project
RED.menu.setDisabled('menu-item-projects-open',true);
RED.menu.setDisabled('menu-item-projects-settings',true);
if (activeProject === false) {
// User previously decline the migration to projects.
} else { // null/undefined
RED.projects.showStartup();
}
}
completeLoad();
});
} else {
// Projects disabled by the user
RED.sidebar.info.refresh()
completeLoad();
$("body").append(data);
$("body").i18n();
$("#palette > .palette-spinner").hide();
$(".palette-scroll").removeClass("hide");
$("#palette-search").removeClass("hide");
loadFlows(function() {
if (RED.settings.theme("projects.enabled",false)) {
RED.projects.refresh(function(activeProject) {
RED.sidebar.info.refresh()
if (!activeProject) {
// Projects enabled but no active project
RED.menu.setDisabled('menu-item-projects-open',true);
RED.menu.setDisabled('menu-item-projects-settings',true);
if (activeProject === false) {
// User previously decline the migration to projects.
} else { // null/undefined
RED.projects.showStartup();
}
}
completeLoad();
});
} else {
var config = configs.shift();
appendNodeConfig(config,stepConfig);
// Projects disabled by the user
RED.sidebar.info.refresh()
completeLoad();
}
}
stepConfig();
});
}
});
}
@@ -176,13 +130,13 @@ var RED = (function() {
loadFlows(function() {
var project = RED.projects.getActiveProject();
var message = {
"change-branch": RED._("notification.project.change-branch", {project: project.git.branches.local}),
"merge-abort": RED._("notification.project.merge-abort"),
"loaded": RED._("notification.project.loaded", {project: msg.project}),
"updated": RED._("notification.project.updated", {project: msg.project}),
"pull": RED._("notification.project.pull", {project: msg.project}),
"revert": RED._("notification.project.revert", {project: msg.project}),
"merge-complete": RED._("notification.project.merge-complete")
"change-branch":"Change to local branch '"+project.git.branches.local+"'",
"merge-abort":"Git merge aborted",
"loaded":"Project '"+msg.project+"' loaded",
"updated":"Project '"+msg.project+"' updated",
"pull":"Project '"+msg.project+"' reloaded",
"revert": "Project '"+msg.project+"' reloaded",
"merge-complete":"Git merge completed"
}[msg.action];
RED.notify("<p>"+message+"</p>");
RED.sidebar.info.refresh()
@@ -201,32 +155,23 @@ var RED = (function() {
id: notificationId
}
if (notificationId === "runtime-state") {
if (msg.error === "safe-mode") {
options.buttons = [
{
text: RED._("common.label.close"),
click: function() {
persistentNotifications[notificationId].hideNotification();
}
}
]
} else if (msg.error === "missing-types") {
if (msg.error === "missing-types") {
text+="<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
if (!!RED.projects.getActiveProject()) {
options.buttons = [
{
text: RED._("notification.label.manage-project-dep"),
text: "Manage project dependencies",
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.settings.show('deps');
}
}
]
// } else if (RED.settings.theme('palette.editable') !== false) {
// } else if (RED.settings.theme('palette.editable') !== false) {
} else {
options.buttons = [
{
text: RED._("common.label.close"),
text: "Close",
click: function() {
persistentNotifications[notificationId].hideNotification();
}
@@ -234,25 +179,13 @@ var RED = (function() {
]
}
} else if (msg.error === "credentials_load_failed") {
if (RED.settings.theme("projects.enabled",false)) {
// projects enabled
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Setup credentials",
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.showCredentialsPrompt();
}
}
]
}
} else {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Close",
text: "Setup credentials",
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.showCredentialsPrompt();
}
}
]
@@ -269,18 +202,6 @@ var RED = (function() {
}
]
}
} else if (msg.error === "missing_package_file") {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Create default package file",
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.createDefaultPackageFile();
}
}
]
}
} else if (msg.error === "project_empty") {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
@@ -349,9 +270,9 @@ var RED = (function() {
var id = m.id;
RED.nodes.addNodeSet(m);
addedTypes = addedTypes.concat(m.types);
RED.i18n.loadNodeCatalog(id, function() {
RED.i18n.loadCatalog(id, function() {
$.get('nodes/'+id, function(data) {
appendNodeConfig(data);
$("body").append(data);
});
});
});
@@ -379,7 +300,7 @@ var RED = (function() {
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
} else {
$.get('nodes/'+msg.id, function(data) {
appendNodeConfig(data);
$("body").append(data);
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
});
@@ -403,8 +324,8 @@ var RED = (function() {
function showAbout() {
$.get('red/about', function(data) {
var aboutHeader = '<div style="text-align:center;">'+
'<img width="50px" src="red/images/node-red-icon.svg" />'+
'</div>';
'<img width="50px" src="red/images/node-red-icon.svg" />'+
'</div>';
RED.sidebar.info.set(aboutHeader+marked(data));
RED.sidebar.info.show();
@@ -442,8 +363,8 @@ var RED = (function() {
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-import-dialog"},
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
]});
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),options:[
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-export-dialog"},
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:"core:show-export-dialog"},
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"}
]});
menuOptions.push(null);
@@ -518,25 +439,16 @@ var RED = (function() {
loadNodeList();
}
var initialised = false;
$(function() {
function init(options) {
if (initialised) {
throw new Error("RED already initialised");
if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) {
document.title = document.title+" : "+window.location.hostname;
}
initialised = true;
ace.require("ace/ext/language_tools");
options = options || {};
options.apiRootUrl = options.apiRootUrl || "";
if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) {
options.apiRootUrl = options.apiRootUrl+"/";
}
RED.i18n.init(options, function() {
RED.settings.init(options, loadEditor);
})
}
return {
init: init
}
RED.i18n.init(function() {
RED.settings.init(loadEditor);
})
});
})();

View File

@@ -133,7 +133,7 @@ RED.nodes = (function() {
registerNodeType: function(nt,def) {
nodeDefinitions[nt] = def;
def.type = nt;
if (nt.substring(0,8) != "subflow:") {
if (def.category != "subflows") {
def.set = nodeSets[typeToId[nt]];
nodeSets[typeToId[nt]].added = true;
nodeSets[typeToId[nt]].enabled = true;
@@ -354,8 +354,9 @@ RED.nodes = (function() {
subflows[sf.id] = sf;
RED.nodes.registerType("subflow:"+sf.id, {
defaults:{name:{value:""}},
info: sf.info,
icon: function() { return sf.icon||"subflow.png" },
category: sf.category || "subflows",
category: "subflows",
inputs: sf.in.length,
outputs: sf.out.length,
color: "#da9",
@@ -490,9 +491,7 @@ RED.nodes = (function() {
for (var j=0;j<wires.length;j++) {
var w = wires[j];
if (w.target.type != "subflow") {
if (w.sourcePort < node.wires.length) {
node.wires[w.sourcePort].push(w.target.id);
}
node.wires[w.sourcePort].push(w.target.id);
}
}
@@ -509,9 +508,6 @@ RED.nodes = (function() {
}
}
}
if (n.info) {
node.info = n.info;
}
return node;
}
@@ -521,7 +517,6 @@ RED.nodes = (function() {
node.type = n.type;
node.name = n.name;
node.info = n.info;
node.category = n.category;
node.in = [];
node.out = [];
@@ -758,7 +753,7 @@ RED.nodes = (function() {
if (!isInitialLoad && unknownTypes.length > 0) {
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
var type = "type"+(unknownTypes.length > 1?"s":"");
RED.notify("<p>"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+"</p>"+typeList,"error",false,10000);
RED.notify("<strong>"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+"</strong>"+typeList,"error",false,10000);
}
var activeWorkspace = RED.workspaces.active();
@@ -906,14 +901,7 @@ RED.nodes = (function() {
}
if (!existingConfigNode || existingConfigNode._def.exclusive) { //} || !compareNodes(existingConfigNode,n,true) || existingConfigNode.z !== n.z) {
configNode = {
id:n.id,
z:n.z,
type:n.type,
info: n.info,
users:[],
_config:{}
};
configNode = {id:n.id, z:n.z, type:n.type, users:[], _config:{}};
for (d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d];
@@ -956,7 +944,6 @@ RED.nodes = (function() {
inputLabels: n.inputLabels,
outputLabels: n.outputLabels,
icon: n.icon,
info: n.info,
changed:false,
_config:{}
};
@@ -1025,13 +1012,6 @@ RED.nodes = (function() {
set: registry.getNodeSet("node-red/unknown")
};
node.users = [];
// This is a config node, so delete the default
// non-config node properties
delete node.x;
delete node.y;
delete node.wires;
delete node.inputLabels;
delete node.outputLabels;
}
var orig = {};
for (var p in n) {
@@ -1044,31 +1024,10 @@ RED.nodes = (function() {
node.type = "unknown";
}
if (node._def.category != "config") {
if (n.hasOwnProperty('inputs')) {
node.inputs = n.inputs;
node._config.inputs = JSON.stringify(n.inputs);
} else {
node.inputs = node._def.inputs;
}
if (n.hasOwnProperty('outputs')) {
node.outputs = n.outputs;
node._config.outputs = JSON.stringify(n.outputs);
} else {
node.outputs = node._def.outputs;
}
if (node.hasOwnProperty('wires') && node.wires.length > node.outputs) {
if (!node._def.defaults.hasOwnProperty("outputs") || !isNaN(parseInt(n.outputs))) {
// If 'wires' is longer than outputs, clip wires
console.log("Warning: node.wires longer than node.outputs - trimming wires:",node.id," wires:",node.wires.length," outputs:",node.outputs);
node.wires = node.wires.slice(0,node.outputs);
} else {
// The node declares outputs in its defaults, but has not got a valid value
// Defer to the length of the wires array
node.outputs = node.wires.length;
}
}
node.inputs = n.inputs||node._def.inputs;
node.outputs = n.outputs||node._def.outputs;
for (d in node._def.defaults) {
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
if (node._def.defaults.hasOwnProperty(d)) {
node[d] = n[d];
node._config[d] = JSON.stringify(n[d]);
}
@@ -1088,9 +1047,7 @@ RED.nodes = (function() {
addNode(node);
RED.editor.validateNode(node);
node_map[n.id] = node;
// If an 'unknown' config node, it will not have been caught by the
// proper config node handling, so needs adding to new_nodes here
if (node.type === "unknown" || node._def.category !== "config") {
if (node._def.category != "config") {
new_nodes.push(node);
}
}

View File

@@ -13,5 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
module.exports = false
var RED = {};

View File

@@ -89,22 +89,18 @@ RED.settings = (function () {
userSettings = data;
}
var init = function (options, done) {
var init = function (done) {
var accessTokenMatch = /[?&]access_token=(.*?)(?:$|&)/.exec(window.location.search);
if (accessTokenMatch) {
var accessToken = accessTokenMatch[1];
RED.settings.set("auth-tokens",{access_token: accessToken});
window.location.search = "";
}
RED.settings.apiRootUrl = options.apiRootUrl;
$.ajaxSetup({
beforeSend: function(jqXHR,settings) {
// Only attach auth header for requests to relative paths
if (!/^\s*(https?:|\/|\.)/.test(settings.url)) {
if (options.apiRootUrl) {
settings.url = options.apiRootUrl+settings.url;
}
var auth_tokens = RED.settings.get("auth-tokens");
if (auth_tokens) {
jqXHR.setRequestHeader("Authorization","Bearer "+auth_tokens.access_token);

View File

@@ -276,20 +276,9 @@ RED.clipboard = (function() {
if (typeof value !== "string" ) {
value = JSON.stringify(value, function(key,value) {
if (value !== null && typeof value === 'object') {
if (value.__enc__) {
if (value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
truncated = value.data.length !== value.length;
return value.data;
}
if (value.type === 'function' || value.type === 'internal') {
return undefined
}
if (value.type === 'number') {
// Handle NaN and Infinity - they are not permitted
// in JSON. We can either substitute with a String
// representation or null
return null;
}
if (value.__encoded__ && value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
truncated = value.data.length !== value.length;
return value.data;
}
}
return value;
@@ -320,6 +309,18 @@ RED.clipboard = (function() {
$('<input type="text" id="clipboard-hidden">').appendTo("body");
RED.events.on("view:selection-changed",function(selection) {
if (!selection.nodes) {
RED.menu.setDisabled("menu-item-export",true);
RED.menu.setDisabled("menu-item-export-clipboard",true);
RED.menu.setDisabled("menu-item-export-library",true);
} else {
RED.menu.setDisabled("menu-item-export",false);
RED.menu.setDisabled("menu-item-export-clipboard",false);
RED.menu.setDisabled("menu-item-export-library",false);
}
});
RED.actions.add("core:show-export-dialog",exportNodes);
RED.actions.add("core:show-import-dialog",importNodes);

View File

@@ -0,0 +1,81 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.panels = (function() {
function createPanel(options) {
var container = options.container || $("#"+options.id);
var children = container.children();
if (children.length !== 2) {
throw new Error("Container must have exactly two children");
}
container.addClass("red-ui-panels");
var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
var startPosition;
var panelHeights = [];
var modifiedHeights = false;
var panelRatio;
separator.draggable({
axis: "y",
containment: container,
scroll: false,
start:function(event,ui) {
var height = container.height();
startPosition = ui.position.top;
panelHeights = [$(children[0]).height(),$(children[1]).height()];
},
drag: function(event,ui) {
var height = container.height();
var delta = ui.position.top-startPosition;
var newHeights = [panelHeights[0]+delta,panelHeights[1]-delta];
$(children[0]).height(newHeights[0]);
$(children[1]).height(newHeights[1]);
if (options.resize) {
options.resize(newHeights[0],newHeights[1]);
}
ui.position.top -= delta;
panelRatio = newHeights[0]/height;
},
stop:function(event,ui) {
modifiedHeights = true;
}
});
return {
resize: function(height) {
var panelHeights = [$(children[0]).height(),$(children[1]).height()];
container.height(height);
if (modifiedHeights) {
var topPanelHeight = panelRatio*height;
var bottomPanelHeight = height - topPanelHeight - 48;
panelHeights = [topPanelHeight,bottomPanelHeight];
$(children[0]).height(panelHeights[0]);
$(children[1]).height(panelHeights[1]);
}
if (options.resize) {
options.resize(panelHeights[0],panelHeights[1]);
}
}
}
}
return {
create: createPanel
}
})();

View File

@@ -19,14 +19,12 @@ RED.popover = (function() {
"default": {
top: 10,
leftRight: 17,
leftLeft: 25,
leftBottom: 8,
leftLeft: 25
},
"small": {
top: 5,
leftRight: 17,
leftLeft: 16,
leftBottom: 3,
leftLeft: 16
}
}
function createPopover(options) {
@@ -48,39 +46,29 @@ RED.popover = (function() {
var openPopup = function(instant) {
if (active) {
div = $('<div class="red-ui-popover red-ui-popover-'+direction+'"></div>');
div = $('<div class="red-ui-popover red-ui-popover-'+direction+'"></div>').appendTo("body");
if (size !== "default") {
div.addClass("red-ui-popover-size-"+size);
}
if (typeof content === 'function') {
var result = content.call(res);
if (result === null) {
return;
}
if (typeof result === 'string') {
div.text(result);
} else {
div.append(result);
}
content.call(res).appendTo(div);
} else {
div.html(content);
}
if (width !== "auto") {
div.width(width);
}
div.appendTo("body");
var targetPos = target.offset();
var targetWidth = target.outerWidth();
var targetHeight = target.outerHeight();
var targetWidth = target.width();
var targetHeight = target.height();
var divHeight = div.height();
var divWidth = div.width();
if (direction === 'right') {
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left+targetWidth+deltaSizes[size].leftRight});
} else if (direction === 'left') {
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left-deltaSizes[size].leftLeft-divWidth});
} else if (direction === 'bottom') {
div.css({top: targetPos.top+targetHeight+deltaSizes[size].top,left:targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom});
}
if (instant) {
div.show();
@@ -155,17 +143,7 @@ RED.popover = (function() {
}
return {
create: createPopover,
tooltip: function(target,content) {
RED.popover.create({
target:target,
trigger: "hover",
size: "small",
direction: "bottom",
content: content,
delay: { show: 550, hide: 10 }
});
}
create: createPopover
}
})();

View File

@@ -17,15 +17,10 @@
RED.tabs = (function() {
var defaultTabIcon = "fa fa-lemon-o";
function createTabs(options) {
var tabs = {};
var pinnedTabsCount = 0;
var currentTabWidth;
var currentActiveTabWidth = 0;
var collapsibleMenu;
var ul = options.element || $("#"+options.id);
var wrapper = ul.wrap( "<div>" ).parent();
@@ -55,56 +50,6 @@ RED.tabs = (function() {
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,'+=150') }).on('click',function(evt){ evt.preventDefault();});
}
if (options.collapsible) {
// var dropDown = $('<div>',{class:"red-ui-tabs-select"}).appendTo(wrapper);
// ul.hide();
wrapper.addClass("red-ui-tabs-collapsible");
var collapsedButtonsRow = $('<div class="red-ui-tab-link-buttons"></div>').appendTo(wrapper);
var selectButton = $('<a href="#"><i class="fa fa-caret-down"></i></a>').appendTo(collapsedButtonsRow);
selectButton.addClass("red-ui-tab-link-button-menu")
selectButton.click(function(evt) {
evt.preventDefault();
if (!collapsibleMenu) {
var pinnedOptions = [];
var options = [];
ul.children().each(function(i,el) {
var id = $(el).data('tabId');
var opt = {
id:"red-ui-tabs-menu-option-"+id,
icon: tabs[id].iconClass || defaultTabIcon,
label: tabs[id].name,
onselect: function() {
activateTab(id);
}
};
if (tabs[id].pinned) {
pinnedOptions.push(opt);
} else {
options.push(opt);
}
});
options = pinnedOptions.concat(options);
collapsibleMenu = RED.menu.init({id:"debug-message-option-menu",options: options});
collapsibleMenu.css({
position: "absolute"
})
collapsibleMenu.on('mouseleave', function(){ $(this).hide() });
collapsibleMenu.on('mouseup', function() { $(this).hide() });
collapsibleMenu.appendTo("body");
}
var elementPos = selectButton.offset();
collapsibleMenu.css({
top: (elementPos.top+selectButton.height()-20)+"px",
left: (elementPos.left - collapsibleMenu.width() + selectButton.width())+"px"
})
collapsibleMenu.toggle();
})
}
function scrollEventHandler(evt,dir) {
evt.preventDefault();
if ($(this).hasClass('disabled')) {
@@ -173,9 +118,6 @@ RED.tabs = (function() {
ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"});
link.parent().addClass("active");
var parentId = link.parent().attr('id');
wrapper.find(".red-ui-tab-link-button").removeClass("active selected");
$("#"+parentId+"-link-button").addClass("active selected");
if (options.scrollable) {
var pos = link.parent().position().left;
if (pos-21 < 0) {
@@ -213,71 +155,42 @@ RED.tabs = (function() {
var tabs = ul.find("li.red-ui-tab");
var width = wrapper.width();
var tabCount = tabs.size();
var tabWidth;
if (options.collapsible) {
tabWidth = width - collapsedButtonsRow.width()-10;
if (tabWidth < 198) {
var delta = 198 - tabWidth;
var b = collapsedButtonsRow.find("a:last").prev();
while (b.is(":not(:visible)")) {
b = b.prev();
}
if (!b.hasClass("red-ui-tab-link-button-pinned")) {
b.hide();
}
tabWidth = width - collapsedButtonsRow.width()-10;
var tabWidth = (width-12-(tabCount*6))/tabCount;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = currentTabWidth+"%";
if (options.scrollable) {
tabWidth = Math.max(tabWidth,140);
currentTabWidth = tabWidth+"px";
currentActiveTabWidth = 0;
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
ul.width(listWidth);
updateScroll();
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
if (tabWidth < options.minimumActiveTabWidth) {
tabCount -= 1;
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
} else {
var space = width - 198 - collapsedButtonsRow.width();
if (space > 40) {
collapsedButtonsRow.find("a:not(:visible):first").show();
tabWidth = width - collapsedButtonsRow.width()-10;
}
}
tabs.css({width:tabWidth});
} else {
var tabWidth = (width-12-(tabCount*6))/tabCount;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = currentTabWidth+"%";
if (options.scrollable) {
tabWidth = Math.max(tabWidth,140);
currentTabWidth = tabWidth+"px";
currentActiveTabWidth = 0;
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
ul.width(listWidth);
updateScroll();
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
if (tabWidth < options.minimumActiveTabWidth) {
tabCount -= 1;
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
currentTabWidth = (100*tabWidth/width)+"%";
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
} else {
currentActiveTabWidth = 0;
}
}
if (options.collapsible) {
console.log(currentTabWidth);
}
tabs.css({width:currentTabWidth});
if (tabWidth < 50) {
ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide();
ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"})
} else {
ul.find(".red-ui-tab-close").show();
ul.find(".red-ui-tab-icon").show();
ul.find(".red-ui-tab-label").css({paddingLeft:""})
}
if (currentActiveTabWidth !== 0) {
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""})
}
}
tabs.css({width:currentTabWidth});
if (tabWidth < 50) {
ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide();
ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"})
} else {
ul.find(".red-ui-tab-close").show();
ul.find(".red-ui-tab-icon").show();
ul.find(".red-ui-tab-label").css({paddingLeft:""})
}
if (currentActiveTabWidth !== 0) {
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""})
}
}
@@ -297,15 +210,11 @@ RED.tabs = (function() {
activateTab(tab.find("a"));
}
li.remove();
if (tabs[id].pinned) {
pinnedTabsCount--;
}
if (options.onremove) {
options.onremove(tabs[id]);
}
delete tabs[id];
updateTabWidths();
collapsibleMenu = null;
}
return {
@@ -314,48 +223,13 @@ RED.tabs = (function() {
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-")));
li.data("tabId",tab.id);
if (options.maximumTabWidth) {
li.css("maxWidth",options.maximumTabWidth+"px");
}
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
if (tab.icon) {
$('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
} else if (tab.iconClass) {
$('<i>',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link);
}
var span = $('<span/>',{class:"bidiAware"}).text(tab.label).appendTo(link);
span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label));
if (options.collapsible) {
li.addClass("red-ui-tab-pinned");
var pinnedLink = $('<a href="#'+tab.id+'" class="red-ui-tab-link-button"></a>');
if (tab.pinned) {
if (pinnedTabsCount === 0) {
pinnedLink.prependTo(collapsedButtonsRow)
} else {
pinnedLink.insertAfter(collapsedButtonsRow.find("a.red-ui-tab-link-button-pinned:last"));
}
} else {
pinnedLink.insertBefore(collapsedButtonsRow.find("a:last"));
}
pinnedLink.attr('id',li.attr('id')+"-link-button");
if (tab.iconClass) {
$('<i>',{class:tab.iconClass}).appendTo(pinnedLink);
} else {
$('<i>',{class:defaultTabIcon}).appendTo(pinnedLink);
}
pinnedLink.click(function(evt) {
evt.preventDefault();
activateTab(tab.id);
});
if (tab.pinned) {
pinnedLink.addClass("red-ui-tab-link-button-pinned");
pinnedTabsCount++;
}
RED.popover.tooltip($(pinnedLink), tab.name);
}
link.on("click",onTabClick);
link.on("dblclick",onTabDblClick);
if (tab.closeable) {
@@ -367,6 +241,7 @@ RED.tabs = (function() {
removeTab(tab.id);
});
}
updateTabWidths();
if (options.onadd) {
options.onadd(tab);
}
@@ -451,10 +326,6 @@ RED.tabs = (function() {
}
})
}
setTimeout(function() {
updateTabWidths();
},10);
collapsibleMenu = null;
},
removeTab: removeTab,
activateTab: activateTab,

View File

@@ -14,38 +14,10 @@
* limitations under the License.
**/
(function($) {
var contextParse = function(v) {
var parts = RED.utils.parseContextKey(v);
return {
option: parts.store,
value: parts.key
}
}
var contextExport = function(v,opt) {
if (!opt) {
return v;
}
var store = ((typeof opt === "string")?opt:opt.value)
if (store !== RED.settings.context.default) {
return "#:("+store+")::"+v;
} else {
return v;
}
}
var allOptions = {
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression},
flow: {value:"flow",label:"flow.",hasValue:true,
options:[],
validate:RED.utils.validatePropertyExpression,
parse: contextParse,
export: contextExport
},
global: {value:"global",label:"global.",hasValue:true,
options:[],
validate:RED.utils.validatePropertyExpression,
parse: contextParse,
export: contextExport
},
flow: {value:"flow",label:"flow.",validate:RED.utils.validatePropertyExpression},
global: {value:"global",label:"global.",validate:RED.utils.validatePropertyExpression},
str: {value:"str",label:"string",icon:"red/images/typedInput/az.png"},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.png",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]},
@@ -104,51 +76,31 @@
}
})
}
},
env: {
value: "env",
label: "env variable",
icon: "red/images/typedInput/env.png"
}
};
var nlsd = false;
$.widget( "nodered.typedInput", {
_create: function() {
try {
if (!nlsd && RED && RED._) {
for (var i in allOptions) {
if (allOptions.hasOwnProperty(i)) {
allOptions[i].label = RED._("typedInput.type."+i,{defaultValue:allOptions[i].label});
}
}
var contextStores = RED.settings.context.stores;
var contextOptions = contextStores.map(function(store) {
return {value:store,label: store, icon:'<i class="red-ui-typedInput-icon fa fa-database" style="color: #'+(store==='memory'?'ddd':'777')+'"></i>'}
})
if (contextOptions.length < 2) {
allOptions.flow.options = [];
allOptions.global.options = [];
} else {
allOptions.flow.options = contextOptions;
allOptions.global.options = contextOptions;
}
}
nlsd = true;
var that = this;
this.disarmClick = false;
this.input = $('<input type="text"></input>');
this.input.insertAfter(this.element);
this.input.val(this.element.val());
this.element.addClass('red-ui-typedInput');
this.uiWidth = this.element.outerWidth();
this.elementDiv = this.input.wrap("<div>").parent().addClass('red-ui-typedInput-input');
this.elementDiv = this.element.wrap("<div>").parent().addClass('red-ui-typedInput-input');
this.uiSelect = this.elementDiv.wrap( "<div>" ).parent();
var attrStyle = this.element.attr('style');
var m;
if ((m = /width\s*:\s*(calc\s*\(.*\)|\d+(%|px))/i.exec(attrStyle)) !== null) {
this.input.css('width','100%');
this.element.css('width','100%');
this.uiSelect.width(m[1]);
this.uiWidth = null;
} else {
@@ -157,19 +109,17 @@
["Right","Left"].forEach(function(d) {
var m = that.element.css("margin"+d);
that.uiSelect.css("margin"+d,m);
that.input.css("margin"+d,0);
that.element.css("margin"+d,0);
});
this.uiSelect.addClass("red-ui-typedInput-container");
this.element.attr('type','hidden');
this.options.types = this.options.types||Object.keys(allOptions);
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
$('<i class="red-ui-typedInput-icon fa fa-sort-desc"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
if (this.options.types.length > 1) {
$('<i class="fa fa-sort-desc"></i>').appendTo(this.selectTrigger);
}
this.selectLabel = $('<span></span>').appendTo(this.selectTrigger);
this.types(this.options.types);
@@ -183,16 +133,14 @@
this.typeField = $("<input>",{type:'hidden'}).appendTo(this.uiSelect);
}
this.input.on('focus', function() {
this.element.on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
});
this.input.on('blur', function() {
this.element.on('blur', function() {
that.uiSelect.removeClass('red-ui-typedInput-focus');
});
this.input.on('change', function() {
this.element.on('change', function() {
that.validate();
that.element.val(that.value());
that.element.trigger('change',that.propertyType,that.value());
})
this.selectTrigger.click(function(event) {
event.preventDefault();
@@ -208,11 +156,8 @@
})
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
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-sort-desc"></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="fa fa-sort-desc"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
RED.popover.tooltip(this.optionSelectLabel,function() {
return that.optionValue;
});
this.optionSelectTrigger.click(function(event) {
event.preventDefault();
that._showOptionSelectMenu();
@@ -227,18 +172,17 @@
that.uiSelect.addClass('red-ui-typedInput-focus');
});
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect);
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect);
this.type(this.options.default||this.typeList[0].value);
}catch(err) {
console.log(err.stack);
}
},
_showTypeMenu: function() {
if (this.typeList.length > 1) {
this._showMenu(this.menu,this.selectTrigger);
this.menu.find("[value='"+this.propertyType+"']").focus();
} else {
this.input.focus();
this.element.focus();
}
},
_showOptionSelectMenu: function() {
@@ -247,8 +191,8 @@
minWidth:this.optionSelectLabel.width()
});
this._showMenu(this.optionMenu,this.optionSelectTrigger);
var selectedOption = this.optionMenu.find("[value='"+this.optionValue+"']");
this._showMenu(this.optionMenu,this.optionSelectLabel);
var selectedOption = this.optionMenu.find("[value='"+this.value()+"']");
if (selectedOption.length === 0) {
selectedOption = this.optionMenu.children(":first");
}
@@ -260,7 +204,7 @@
$(document).off("mousedown.close-property-select");
menu.hide();
if (this.elementDiv.is(":visible")) {
this.input.focus();
this.element.focus();
} else if (this.optionSelectTrigger.is(":visible")){
this.optionSelectTrigger.focus();
} else {
@@ -279,19 +223,10 @@
op.text(opt.label);
}
if (opt.icon) {
if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(op);
} else if (opt.icon.indexOf("/") !== -1) {
$('<img>',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op);
} else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op);
}
$('<img>',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op);
} else {
op.css({paddingLeft: "18px"});
}
if (!opt.icon && !opt.label) {
op.text(opt.value);
}
op.click(function(event) {
event.preventDefault();
@@ -370,8 +305,7 @@
if (this.uiWidth !== null) {
this.uiSelect.width(this.uiWidth);
}
var type = this.typeMap[this.propertyType];
if (type && type.hasValue === false) {
if (this.typeMap[this.propertyType] && this.typeMap[this.propertyType].hasValue === false) {
this.selectTrigger.addClass("red-ui-typedInput-full-width");
} else {
this.selectTrigger.removeClass("red-ui-typedInput-full-width");
@@ -381,68 +315,13 @@
this.elementDiv.css('right',"22px");
} else {
this.elementDiv.css('right','0');
this.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
}
// if (this.optionSelectTrigger) {
// this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
// }
if (this.optionSelectTrigger) {
if (type && type.options && type.hasValue === true) {
this.optionSelectLabel.css({'left':'auto'})
var lw = this._getLabelWidth(this.optionSelectLabel);
this.optionSelectTrigger.css({'width':(23+lw)+"px"});
this.elementDiv.css('right',(23+lw)+"px");
this.input.css({
'border-top-right-radius': 0,
'border-bottom-right-radius': 0
});
} else {
this.optionSelectLabel.css({'left':'0'})
this.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
if (!this.optionExpandButton.is(":visible")) {
this.elementDiv.css({'right':0});
this.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
}
}
this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
}
}
},
_updateOptionSelectLabel: function(o) {
var opt = this.typeMap[this.propertyType];
this.optionSelectLabel.empty();
if (o.icon) {
if (o.icon.indexOf("<") === 0) {
$(o.icon).prependTo(this.optionSelectLabel);
} else if (o.icon.indexOf("/") !== -1) {
// url
$('<img>',{src:o.icon,style:"height: 18px;"}).prependTo(this.optionSelectLabel);
} else {
// icon class
$('<i>',{class:"red-ui-typedInput-icon "+o.icon}).prependTo(this.optionSelectLabel);
}
} else if (o.label) {
this.optionSelectLabel.text(o.label);
} else {
this.optionSelectLabel.text(o.value);
}
if (opt.hasValue) {
this.optionValue = o.value;
this._resize();
this.input.trigger('change',this.propertyType,this.value());
}
},
_destroy: function() {
if (this.optionMenu) {
this.optionMenu.remove();
}
this.menu.remove();
},
types: function(types) {
@@ -460,18 +339,13 @@
return result;
});
this.selectTrigger.toggleClass("disabled", this.typeList.length === 1);
this.selectTrigger.find(".fa-sort-desc").toggle(this.typeList.length > 1)
if (this.menu) {
this.menu.remove();
}
this.menu = this._createMenu(this.typeList, function(v) { that.type(v) });
if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
this.type(this.typeList[0].value);
} else {
this.propertyType = null;
this.type(currentType);
}
setTimeout(function() {that._resize();},0);
},
width: function(desiredWidth) {
this.uiWidth = desiredWidth;
@@ -479,33 +353,33 @@
},
value: function(value) {
if (!arguments.length) {
var v = this.input.val();
if (this.typeMap[this.propertyType].export) {
v = this.typeMap[this.propertyType].export(v,this.optionValue)
}
return v;
return this.element.val();
} else {
var selectedOption;
if (this.typeMap[this.propertyType].options) {
var validValue = false;
var label;
for (var i=0;i<this.typeMap[this.propertyType].options.length;i++) {
var op = this.typeMap[this.propertyType].options[i];
if (typeof op === "string") {
if (op === value) {
selectedOption = this.activeOptions[op];
label = value;
validValue = true;
break;
}
} else if (op.value === value) {
selectedOption = op;
label = op.label||op.value;
validValue = true;
break;
}
}
if (!selectedOption) {
selectedOption = {value:""}
if (!validValue) {
value = "";
label = "";
}
this._updateOptionSelectLabel(selectedOption)
this.optionSelectLabel.text(label);
}
this.input.val(value);
this.input.trigger('change',this.type(),value);
this.element.val(value);
this.element.trigger('change',this.type(),value);
}
},
type: function(type) {
@@ -516,24 +390,14 @@
var opt = this.typeMap[type];
if (opt && this.propertyType !== type) {
this.propertyType = type;
if (this.typeField) {
this.typeField.val(type);
}
this.typeField.val(type);
this.selectLabel.empty();
var image;
if (opt.icon) {
if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(this.selectLabel);
}
else if (opt.icon.indexOf("/") !== -1) {
image = new Image();
image.name = opt.icon;
image.src = opt.icon;
$('<img>',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
}
else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(this.selectLabel);
}
image = new Image();
image.name = opt.icon;
image.src = opt.icon;
$('<img>',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
} else {
this.selectLabel.text(opt.label);
}
@@ -543,88 +407,37 @@
}
if (this.optionSelectTrigger) {
this.optionSelectTrigger.show();
if (!opt.hasValue) {
this.elementDiv.hide();
} else {
this.elementDiv.show();
}
this.activeOptions = {};
opt.options.forEach(function(o) {
if (typeof o === 'string') {
that.activeOptions[o] = {label:o,value:o};
} else {
that.activeOptions[o.value] = o;
}
});
if (!that.activeOptions.hasOwnProperty(that.optionValue)) {
that.optionValue = null;
}
this.elementDiv.hide();
this.optionMenu = this._createMenu(opt.options,function(v){
that._updateOptionSelectLabel(that.activeOptions[v]);
if (!opt.hasValue) {
that.value(that.activeOptions[v].value)
}
that.optionSelectLabel.text(v);
that.value(v);
});
var currentVal = this.element.val();
var validValue = false;
var op;
if (!opt.hasValue) {
var currentVal = this.input.val();
var validValue = false;
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string") {
if (op === currentVal) {
this.optionSelectLabel.text(currentVal);
validValue = true;
break;
}
}
if (!validValue) {
op = opt.options[0];
if (typeof op === "string") {
this.value(op);
that._updateOptionSelectLabel({value:op});
} else {
this.value(op.value);
that._updateOptionSelectLabel(op);
}
}
} else {
var selectedOption = this.optionValue||opt.options[0];
if (opt.parse) {
var parts = opt.parse(this.input.val());
if (parts.option) {
selectedOption = parts.option;
if (!this.activeOptions.hasOwnProperty(selectedOption)) {
parts.option = Object.keys(this.activeOptions)[0];
selectedOption = parts.option
}
}
this.input.val(parts.value);
if (opt.export) {
this.element.val(opt.export(parts.value,parts.option||selectedOption));
}
}
if (typeof selectedOption === "string") {
this.optionValue = selectedOption;
if (!this.activeOptions.hasOwnProperty(selectedOption)) {
selectedOption = Object.keys(this.activeOptions)[0];
}
if (!selectedOption) {
this.optionSelectTrigger.hide();
} else {
this._updateOptionSelectLabel(this.activeOptions[selectedOption]);
}
} else if (selectedOption) {
this.optionValue = selectedOption.value;
this._updateOptionSelectLabel(selectedOption);
} else {
this.optionSelectTrigger.hide();
} else if (op.value === currentVal) {
this.optionSelectLabel.text(op.label||op.value);
validValue = true;
break;
}
}
if (!validValue) {
op = opt.options[0];
if (typeof op === "string") {
this.value(op);
} else {
this.value(op.value);
}
}
console.log(validValue);
}
} else {
if (this.optionMenu) {
@@ -635,29 +448,27 @@
this.optionSelectTrigger.hide();
}
if (opt.hasValue === false) {
this.oldValue = this.input.val();
this.input.val("");
this.oldValue = this.element.val();
this.element.val("");
this.elementDiv.hide();
} else {
if (this.oldValue !== undefined) {
this.input.val(this.oldValue);
this.element.val(this.oldValue);
delete this.oldValue;
}
this.elementDiv.show();
}
if (this.optionExpandButton) {
if (opt.expand && typeof opt.expand === 'function') {
this.optionExpandButton.show();
this.optionExpandButton.off('click');
this.optionExpandButton.on('click',function(evt) {
evt.preventDefault();
opt.expand.call(that);
})
} else {
this.optionExpandButton.hide();
}
if (opt.expand && typeof opt.expand === 'function') {
this.optionExpandButton.show();
this.optionExpandButton.off('click');
this.optionExpandButton.on('click',function(evt) {
evt.preventDefault();
opt.expand.call(that);
})
} else {
this.optionExpandButton.hide();
}
this.input.trigger('change',this.propertyType,this.value());
this.element.trigger('change',this.propertyType,this.value());
}
if (image) {
image.onload = function() { that._resize(); }

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