mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge remote-tracking branch 'upstream/master' into stop-start-flows
This commit is contained in:
commit
3cef2bb7e0
39
CHANGELOG.md
39
CHANGELOG.md
@ -1,3 +1,42 @@
|
|||||||
|
#### 3.0.0-beta.3: Beta Release
|
||||||
|
|
||||||
|
Editor
|
||||||
|
|
||||||
|
- Add Right-Click content menu (#3678) @knolleary
|
||||||
|
- Fix disable junction (#3671) @HiroyasuNishiyama
|
||||||
|
- Add Japanese translations for v2.2.3 (#3672) @kazuhitoyokoi
|
||||||
|
- Reset mouse state when switching tabs (#3643) @knolleary
|
||||||
|
- Fix uncorrect fix of junction to subflow conversion (#3666) @HiroyasuNishiyama
|
||||||
|
- Fix undoing junction to subflow (#3653) @HiroyasuNishiyama
|
||||||
|
- Fix conversion of junction to subflow (#3652) @HiroyasuNishiyama
|
||||||
|
- Fix to include junction to exported nodes (#3650) @HiroyasuNishiyama
|
||||||
|
- Fix z-index value for shade to cover nodes in palette (#3649) @kazuhitoyokoi
|
||||||
|
- Fix to extend escaped subflow category characters (#3647) @HiroyasuNishiyama
|
||||||
|
- Fix to sanitize tab name (#3646) @HiroyasuNishiyama
|
||||||
|
- Fix selector placement (#3644) @bonanitech
|
||||||
|
- Add Japanese translations for v3.0-beta.2 (#3622) @kazuhitoyokoi
|
||||||
|
- Fix new folder menu of save to library dialog (#3633) @HiroyasuNishiyama
|
||||||
|
- Fix layer of palette node (#3638) @HiroyasuNishiyama
|
||||||
|
- Fix to place a node dragged from palette within the workspace (#3637) @HiroyasuNishiyama
|
||||||
|
- Fix typo in CSS (#3628) @bonanitech
|
||||||
|
- Use the correct variable for the gutter text color (#3615) @bonanitech
|
||||||
|
|
||||||
|
|
||||||
|
Runtime
|
||||||
|
|
||||||
|
- Support loading node modules from `nodesdir` (#3676) @Steve-Mcl
|
||||||
|
- fix buffer parse error message of evaluateNodeProperty (#3624) @HiroyasuNishiyama
|
||||||
|
|
||||||
|
Nodes
|
||||||
|
|
||||||
|
- File: Further simplify file node filename entry UX (v3) (#3677) @Steve-Mcl
|
||||||
|
- Function: Fix initial cursor position of init/finalize tab of function node (#3674) @HiroyasuNishiyama
|
||||||
|
- Function: Fix ESM module loading in Function node (#3645) @knolleary
|
||||||
|
- Inject: Fix JSONata evaluation of inject button (#3632) @HiroyasuNishiyama
|
||||||
|
- TCP: Dont delete TCP socket twice (#3630) @Steve-Mcl
|
||||||
|
- MQTT Node: define noproxy variable (#3626) @Steve-Mcl
|
||||||
|
- Debug: i18n debug sidebar node label (#3623) @HiroyasuNishiyama
|
||||||
|
|
||||||
#### 3.0.0-beta.2: Beta Release
|
#### 3.0.0-beta.2: Beta Release
|
||||||
|
|
||||||
**Migration from 2.x**
|
**Migration from 2.x**
|
||||||
|
@ -193,6 +193,7 @@ module.exports = function(grunt) {
|
|||||||
"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",
|
||||||
|
14
package.json
14
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"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",
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"hash-sum": "2.0.0",
|
"hash-sum": "2.0.0",
|
||||||
"hpagent": "1.0.0",
|
"hpagent": "1.0.0",
|
||||||
"https-proxy-agent": "5.0.1",
|
"https-proxy-agent": "5.0.1",
|
||||||
"i18next": "21.8.2",
|
"i18next": "21.8.10",
|
||||||
"iconv-lite": "0.6.3",
|
"iconv-lite": "0.6.3",
|
||||||
"is-utf8": "0.2.1",
|
"is-utf8": "0.2.1",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
@ -62,7 +62,7 @@
|
|||||||
"moment": "2.29.3",
|
"moment": "2.29.3",
|
||||||
"moment-timezone": "0.5.34",
|
"moment-timezone": "0.5.34",
|
||||||
"mqtt": "4.3.7",
|
"mqtt": "4.3.7",
|
||||||
"multer": "1.4.4",
|
"multer": "1.4.5-lts.1",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
"node-red-admin": "^3.0.0",
|
"node-red-admin": "^3.0.0",
|
||||||
"node-watch": "0.7.3",
|
"node-watch": "0.7.3",
|
||||||
@ -76,7 +76,7 @@
|
|||||||
"semver": "7.3.7",
|
"semver": "7.3.7",
|
||||||
"tar": "6.1.11",
|
"tar": "6.1.11",
|
||||||
"tough-cookie": "4.0.0",
|
"tough-cookie": "4.0.0",
|
||||||
"uglify-js": "3.15.5",
|
"uglify-js": "3.16.0",
|
||||||
"uuid": "8.3.2",
|
"uuid": "8.3.2",
|
||||||
"ws": "7.5.6",
|
"ws": "7.5.6",
|
||||||
"xml2js": "0.4.23"
|
"xml2js": "0.4.23"
|
||||||
@ -105,16 +105,16 @@
|
|||||||
"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.0",
|
"i18next-http-backend": "1.4.1",
|
||||||
"jquery-i18next": "1.2.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.0.15",
|
"marked": "4.0.17",
|
||||||
"minami": "1.2.3",
|
"minami": "1.2.3",
|
||||||
"mocha": "9.2.2",
|
"mocha": "9.2.2",
|
||||||
"node-red-node-test-helper": "^0.2.7",
|
"node-red-node-test-helper": "^0.2.7",
|
||||||
"nodemon": "2.0.16",
|
"nodemon": "2.0.16",
|
||||||
"proxy": "^1.0.2",
|
"proxy": "^1.0.2",
|
||||||
"sass": "1.51.0",
|
"sass": "1.52.3",
|
||||||
"should": "13.2.3",
|
"should": "13.2.3",
|
||||||
"sinon": "11.1.2",
|
"sinon": "11.1.2",
|
||||||
"stoppable": "^1.1.0",
|
"stoppable": "^1.1.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/editor-api",
|
"name": "@node-red/editor-api",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,8 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "3.0.0-beta.2",
|
"@node-red/util": "3.0.0-beta.3",
|
||||||
"@node-red/editor-client": "3.0.0-beta.2",
|
"@node-red/editor-client": "3.0.0-beta.3",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"body-parser": "1.20.0",
|
"body-parser": "1.20.0",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
@ -26,7 +26,7 @@
|
|||||||
"express": "4.18.1",
|
"express": "4.18.1",
|
||||||
"memorystore": "1.6.7",
|
"memorystore": "1.6.7",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"multer": "1.4.4",
|
"multer": "1.4.5-lts.1",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
"oauth2orize": "1.11.1",
|
"oauth2orize": "1.11.1",
|
||||||
"passport-http-bearer": "1.0.1",
|
"passport-http-bearer": "1.0.1",
|
||||||
|
@ -1187,5 +1187,11 @@
|
|||||||
"missing-config": "__prop__: missing configuration node",
|
"missing-config": "__prop__: missing configuration node",
|
||||||
"validation-error": "__prop__: validation error: __node__, __id__: __error__"
|
"validation-error": "__prop__: validation error: __node__, __id__: __error__"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"contextMenu": {
|
||||||
|
"insert": "Insert",
|
||||||
|
"node": "Node",
|
||||||
|
"junction": "Junction",
|
||||||
|
"linkNodes": "Link Nodes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -907,7 +907,8 @@
|
|||||||
"uknownNodes": "未知のノード",
|
"uknownNodes": "未知のノード",
|
||||||
"unusedSubflows": "未使用のサブフロー",
|
"unusedSubflows": "未使用のサブフロー",
|
||||||
"hiddenFlows": "非表示のフロー",
|
"hiddenFlows": "非表示のフロー",
|
||||||
"modifiedNodes": "修正したノードやフロー"
|
"modifiedNodes": "修正したノードやフロー",
|
||||||
|
"thisFlow": "現在のフロー"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"expressionEditor": {
|
"expressionEditor": {
|
||||||
@ -1187,6 +1188,12 @@
|
|||||||
"validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
|
"validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"contextMenu": {
|
||||||
|
"insert": "挿入",
|
||||||
|
"node": "ノード",
|
||||||
|
"junction": "分岐点",
|
||||||
|
"linkNodes": "Linkノード"
|
||||||
|
},
|
||||||
"action-list": {
|
"action-list": {
|
||||||
"toggle-show-tips": "ヒント表示切替",
|
"toggle-show-tips": "ヒント表示切替",
|
||||||
"show-about": "Node-REDの説明を表示",
|
"show-about": "Node-REDの説明を表示",
|
||||||
@ -1301,7 +1308,7 @@
|
|||||||
"search": "検索",
|
"search": "検索",
|
||||||
"search-previous": "前を検索",
|
"search-previous": "前を検索",
|
||||||
"search-next": "次を検索",
|
"search-next": "次を検索",
|
||||||
"show-action-list": "アクション一覧を表示",
|
"show-action-list": "動作一覧を表示",
|
||||||
"confirm-edit-tray": "編集を完了",
|
"confirm-edit-tray": "編集を完了",
|
||||||
"cancel-edit-tray": "編集をキャンセル",
|
"cancel-edit-tray": "編集をキャンセル",
|
||||||
"show-remote-diff": "リモートとの変更差分を表示",
|
"show-remote-diff": "リモートとの変更差分を表示",
|
||||||
@ -1323,6 +1330,11 @@
|
|||||||
"zoom-out": "ズームアウト",
|
"zoom-out": "ズームアウト",
|
||||||
"zoom-reset": "ズームリセット",
|
"zoom-reset": "ズームリセット",
|
||||||
"toggle-navigator": "ナビゲータ表示切替",
|
"toggle-navigator": "ナビゲータ表示切替",
|
||||||
"show-system-info": "システムインフォメーション"
|
"show-system-info": "システム情報",
|
||||||
|
"split-wires-with-junctions": "分岐点によりワイヤーを分割",
|
||||||
|
"new-project": "新しいプロジェクト",
|
||||||
|
"open-project": "プロジェクトを開く",
|
||||||
|
"show-project-settings": "プロジェクト設定を表示",
|
||||||
|
"show-version-control-tab": "バージョンコントロールタブを表示"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}} を押すとプロパティ設定画面が表示されます。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/editor-client",
|
"name": "@node-red/editor-client",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -22,6 +22,14 @@ 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;
|
||||||
@ -514,6 +522,7 @@ 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;
|
||||||
@ -523,7 +532,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(RED.nodes.node(ev.nodes[i]));
|
inverseEv.subflows.push(nodeOrJunction(ev.nodes[i]));
|
||||||
RED.nodes.remove(ev.nodes[i]);
|
RED.nodes.remove(ev.nodes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -738,6 +738,10 @@ RED.nodes = (function() {
|
|||||||
moveGroupToTab(node,z);
|
moveGroupToTab(node,z);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (node.type === "junction") {
|
||||||
|
moveJunctionToTab(node,z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
var oldZ = node.z;
|
var oldZ = node.z;
|
||||||
allNodes.moveNode(node,z);
|
allNodes.moveNode(node,z);
|
||||||
var nl = nodeLinks[node.id];
|
var nl = nodeLinks[node.id];
|
||||||
@ -772,6 +776,39 @@ RED.nodes = (function() {
|
|||||||
RED.events.emit("groups:change",group);
|
RED.events.emit("groups:change",group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function moveJunctionToTab(junction, z) {
|
||||||
|
var index = junctionsByZ[junction.z].indexOf(junction);
|
||||||
|
junctionsByZ[junction.z].splice(index,1);
|
||||||
|
junctionsByZ[z] = junctionsByZ[z] || [];
|
||||||
|
junctionsByZ[z].push(junction);
|
||||||
|
|
||||||
|
var oldZ = junction.z;
|
||||||
|
junction.z = z;
|
||||||
|
|
||||||
|
var nl = nodeLinks[junction.id];
|
||||||
|
if (nl) {
|
||||||
|
nl.in.forEach(function(l) {
|
||||||
|
var idx = linkTabMap[oldZ].indexOf(l);
|
||||||
|
if (idx != -1) {
|
||||||
|
linkTabMap[oldZ].splice(idx, 1);
|
||||||
|
}
|
||||||
|
if ((l.source.z === z) && linkTabMap[z]) {
|
||||||
|
linkTabMap[z].push(l);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
nl.out.forEach(function(l) {
|
||||||
|
var idx = linkTabMap[oldZ].indexOf(l);
|
||||||
|
if (idx != -1) {
|
||||||
|
linkTabMap[oldZ].splice(idx, 1);
|
||||||
|
}
|
||||||
|
if ((l.target.z === z) && linkTabMap[z]) {
|
||||||
|
linkTabMap[z].push(l);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.events.emit("junctions:change",junction);
|
||||||
|
}
|
||||||
|
|
||||||
function removeLink(l) {
|
function removeLink(l) {
|
||||||
var index = links.indexOf(l);
|
var index = links.indexOf(l);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
|
@ -21,28 +21,12 @@ RED.actions = (function() {
|
|||||||
function getAction(name) {
|
function getAction(name) {
|
||||||
return actions[name].handler;
|
return actions[name].handler;
|
||||||
}
|
}
|
||||||
function invokeAction() {
|
function getActionLabel(name) {
|
||||||
var args = Array.prototype.slice.call(arguments);
|
let def = actions[name]
|
||||||
var name = args.shift();
|
if (!def) {
|
||||||
if (actions.hasOwnProperty(name)) {
|
return ''
|
||||||
var handler = actions[name].handler;
|
|
||||||
handler.apply(null, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function listActions() {
|
|
||||||
var result = [];
|
|
||||||
var missing = [];
|
|
||||||
Object.keys(actions).forEach(function(action) {
|
|
||||||
var def = actions[action];
|
|
||||||
var shortcut = RED.keyboard.getShortcut(action);
|
|
||||||
var isUser = false;
|
|
||||||
if (shortcut) {
|
|
||||||
isUser = shortcut.user;
|
|
||||||
} else {
|
|
||||||
isUser = !!RED.keyboard.getUserShortcut(action);
|
|
||||||
}
|
}
|
||||||
if (!def.label) {
|
if (!def.label) {
|
||||||
var name = action;
|
|
||||||
var options = def.options;
|
var options = def.options;
|
||||||
var key = options ? options.label : undefined;
|
var key = options ? options.label : undefined;
|
||||||
if (!key) {
|
if (!key) {
|
||||||
@ -58,12 +42,36 @@ RED.actions = (function() {
|
|||||||
return " "+arguments[4].toUpperCase();
|
return " "+arguments[4].toUpperCase();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
missing.push(key);
|
|
||||||
}
|
}
|
||||||
def.label = label;
|
def.label = label;
|
||||||
}
|
}
|
||||||
//console.log("; missing:", missing);
|
return def.label
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function invokeAction() {
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
var name = args.shift();
|
||||||
|
if (actions.hasOwnProperty(name)) {
|
||||||
|
var handler = actions[name].handler;
|
||||||
|
handler.apply(null, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function listActions() {
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
Object.keys(actions).forEach(function(action) {
|
||||||
|
var def = actions[action];
|
||||||
|
var shortcut = RED.keyboard.getShortcut(action);
|
||||||
|
var isUser = false;
|
||||||
|
if (shortcut) {
|
||||||
|
isUser = shortcut.user;
|
||||||
|
} else {
|
||||||
|
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,
|
||||||
@ -79,6 +87,7 @@ RED.actions = (function() {
|
|||||||
add: addAction,
|
add: addAction,
|
||||||
remove: removeAction,
|
remove: removeAction,
|
||||||
get: getAction,
|
get: getAction,
|
||||||
|
getLabel: getActionLabel,
|
||||||
invoke: invokeAction,
|
invoke: invokeAction,
|
||||||
list: listActions
|
list: listActions
|
||||||
}
|
}
|
||||||
|
@ -709,6 +709,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) {
|
RED.nodes.eachConfig(function(n) {
|
||||||
if (n.z === RED.workspaces.active() && n._def.hasUsers === false) {
|
if (n.z === RED.workspaces.active() && n._def.hasUsers === false) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
RED.menu = (function() {
|
RED.menu = (function() {
|
||||||
|
|
||||||
var menuItems = {};
|
var menuItems = {};
|
||||||
|
let menuItemCount = 0
|
||||||
|
|
||||||
function createMenuItem(opt) {
|
function createMenuItem(opt) {
|
||||||
var item;
|
var item;
|
||||||
@ -59,15 +60,16 @@ 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 pull-left"></i>';
|
linkContent += '<i class="fa fa-square'+(opt.direction!=='right'?" pull-left":"")+'"></i>';
|
||||||
linkContent += '<i class="fa fa-check-square pull-left"></i>';
|
linkContent += '<i class="fa fa-check-square'+(opt.direction!=='right'?" pull-left":"")+'"></i>';
|
||||||
|
|
||||||
}
|
}
|
||||||
if (opt.icon !== undefined) {
|
if (opt.icon !== undefined) {
|
||||||
@ -77,12 +79,15 @@ 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">'+opt.label+'</span>'+
|
linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+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>'+opt.label+'</span></span>'
|
linkContent += '<span class="red-ui-menu-label"><span>'+label+'</span></span>'
|
||||||
}
|
}
|
||||||
|
|
||||||
linkContent += '</a>';
|
linkContent += '</a>';
|
||||||
@ -126,15 +131,38 @@ RED.menu = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (opt.options) {
|
if (opt.options) {
|
||||||
item.addClass("red-ui-menu-dropdown-submenu pull-left");
|
item.addClass("red-ui-menu-dropdown-submenu"+(opt.direction!=='right'?" 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");
|
||||||
@ -150,7 +178,9 @@ 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);
|
||||||
@ -176,9 +206,22 @@ 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);
|
||||||
@ -186,13 +229,21 @@ 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);
|
||||||
}
|
}
|
||||||
@ -201,6 +252,9 @@ 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) {
|
||||||
|
@ -610,10 +610,13 @@ RED.popover = (function() {
|
|||||||
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 = target.offset();
|
var pos = isAbsolutePosition?{left:xPos, top: yPos}:target.offset();
|
||||||
var targetWidth = target.width();
|
var targetWidth = isAbsolutePosition?0:target.width();
|
||||||
var targetHeight = target.outerHeight();
|
var targetHeight = isAbsolutePosition?0:target.outerHeight();
|
||||||
var panelHeight = panel.height();
|
var panelHeight = panel.height();
|
||||||
var panelWidth = panel.width();
|
var panelWidth = panel.width();
|
||||||
|
|
||||||
|
@ -828,7 +828,7 @@ RED.tabs = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// link.attr("title",tab.label);
|
// link.attr("title",tab.label);
|
||||||
RED.popover.tooltip(link,function() { return tab.label})
|
RED.popover.tooltip(link,function() { return RED.utils.sanitize(tab.label); });
|
||||||
|
|
||||||
if (options.onadd) {
|
if (options.onadd) {
|
||||||
options.onadd(tab);
|
options.onadd(tab);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
* - 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
|
||||||
@ -118,6 +119,7 @@
|
|||||||
switch(evt.keyCode) {
|
switch(evt.keyCode) {
|
||||||
case 32: // SPACE
|
case 32: // SPACE
|
||||||
case 13: // ENTER
|
case 13: // ENTER
|
||||||
|
if (!that.options.selectable) { return }
|
||||||
if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
|
if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
176
packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
vendored
Normal file
176
packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
vendored
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
RED.contextMenu = (function() {
|
||||||
|
|
||||||
|
let menu;
|
||||||
|
function createMenu() {
|
||||||
|
// menu = RED.popover.menu({
|
||||||
|
// options: [
|
||||||
|
// {
|
||||||
|
// label: 'delete selection',
|
||||||
|
// onselect: function() {
|
||||||
|
// RED.actions.invoke('core:delete-selection')
|
||||||
|
// RED.view.focus()
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// { label: 'world' }
|
||||||
|
// ],
|
||||||
|
// width: 200,
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function disposeMenu() {
|
||||||
|
$(document).off("mousedown.red-ui-workspace-context-menu");
|
||||||
|
if (menu) {
|
||||||
|
menu.remove();
|
||||||
|
}
|
||||||
|
menu = null;
|
||||||
|
}
|
||||||
|
function show(options) {
|
||||||
|
if (menu) {
|
||||||
|
menu.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
const selection = RED.view.selection()
|
||||||
|
const hasSelection = (selection.nodes && selection.nodes.length > 0);
|
||||||
|
const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
|
||||||
|
const hasLinks = selection.links && selection.links.length > 0;
|
||||||
|
const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1
|
||||||
|
const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1
|
||||||
|
const canDelete = hasSelection || hasLinks
|
||||||
|
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
|
||||||
|
|
||||||
|
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
|
||||||
|
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{ onselect: 'core:show-action-list', onpostselect: function() {} },
|
||||||
|
{
|
||||||
|
label: RED._("contextMenu.insert"),
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: RED._("contextMenu.node"),
|
||||||
|
onselect: function() {
|
||||||
|
RED.view.showQuickAddDialog({
|
||||||
|
position: [ options.x - offset.left, options.y - offset.top ],
|
||||||
|
touchTrigger: true,
|
||||||
|
splice: isSingleLink?selection.links[0]:undefined,
|
||||||
|
// spliceMultiple: isMultipleLinks
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: RED._("contextMenu.junction"),
|
||||||
|
onselect: 'core:split-wires-with-junctions',
|
||||||
|
disabled: hasSelection || !hasLinks
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: RED._("contextMenu.linkNodes"),
|
||||||
|
onselect: 'core:split-wire-with-link-nodes',
|
||||||
|
disabled: hasSelection || !hasLinks
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
// menuItems.push(
|
||||||
|
// {
|
||||||
|
// label: (isSingleLink || isMultipleLinks)?'Insert into wire...':'Add node...',
|
||||||
|
// onselect: function() {
|
||||||
|
// RED.view.showQuickAddDialog({
|
||||||
|
// position: [ options.x - offset.left, options.y - offset.top ],
|
||||||
|
// touchTrigger: true,
|
||||||
|
// splice: isSingleLink?selection.links[0]:undefined,
|
||||||
|
// spliceMultiple: isMultipleLinks
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// )
|
||||||
|
// if (hasLinks && !hasSelection) {
|
||||||
|
// menuItems.push({ onselect: 'core:split-wires-with-junctions', label: 'Insert junction'})
|
||||||
|
// }
|
||||||
|
menuItems.push(
|
||||||
|
null,
|
||||||
|
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 },
|
||||||
|
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
|
||||||
|
null,
|
||||||
|
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection},
|
||||||
|
{ onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
|
||||||
|
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
|
||||||
|
{ onselect: 'core:delete-selection', disabled: !canDelete },
|
||||||
|
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
|
||||||
|
{ onselect: 'core:select-all-nodes' }
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasSelection) {
|
||||||
|
menuItems.push(
|
||||||
|
null,
|
||||||
|
isGroup ?
|
||||||
|
{ onselect: 'core:ungroup-selection', disabled: !isGroup }
|
||||||
|
: { onselect: 'core:group-selection', disabled: !hasSelection }
|
||||||
|
)
|
||||||
|
if (canRemoveFromGroup) {
|
||||||
|
menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
const offset = $("#red-ui-workspace-chart").offset()
|
||||||
|
menu = RED.menu.init({
|
||||||
|
direction: 'right',
|
||||||
|
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();
|
||||||
|
|
||||||
|
// menu.show({
|
||||||
|
// target: $('#red-ui-main-container'),
|
||||||
|
// x: options.x,
|
||||||
|
// y: options.y
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
show: show,
|
||||||
|
hide: disposeMenu
|
||||||
|
}
|
||||||
|
})()
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
const MONACO = "monaco";
|
const MONACO = "monaco";
|
||||||
const ACE = "ace";
|
const ACE = "ace";
|
||||||
const defaultEditor = ACE;
|
const defaultEditor = MONACO;
|
||||||
const DEFAULT_SETTINGS = { lib: defaultEditor, options: {} };
|
const DEFAULT_SETTINGS = { lib: defaultEditor, options: {} };
|
||||||
var selectedCodeEditor = null;
|
var selectedCodeEditor = null;
|
||||||
var initialised = false;
|
var initialised = false;
|
||||||
|
@ -534,6 +534,7 @@
|
|||||||
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) {
|
||||||
|
@ -363,14 +363,22 @@ RED.library = (function() {
|
|||||||
options.onconfirm(item);
|
options.onconfirm(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
|
var itemTools = null;
|
||||||
|
if (options.folderTools) {
|
||||||
|
dirList.on('treelistselect', function(event, item) {
|
||||||
|
if (item.writable !== false && item.treeList) {
|
||||||
|
if (itemTools) {
|
||||||
|
itemTools.remove();
|
||||||
|
}
|
||||||
|
itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
|
||||||
var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
|
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) {
|
.on("click", function(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
var elementPos = menuButton.offset();
|
var elementPos = menuButton.offset();
|
||||||
|
|
||||||
var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu",
|
var menuOptionMenu
|
||||||
|
= RED.menu.init({id:"red-ui-library-browser-menu",
|
||||||
options: [
|
options: [
|
||||||
{id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
|
{id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
|
||||||
var defaultFolderName = "new-folder";
|
var defaultFolderName = "new-folder";
|
||||||
@ -460,9 +468,7 @@ RED.library = (function() {
|
|||||||
}).show();
|
}).show();
|
||||||
|
|
||||||
}).appendTo(itemTools);
|
}).appendTo(itemTools);
|
||||||
if (options.folderTools) {
|
|
||||||
dirList.on('treelistselect', function(event, item) {
|
|
||||||
if (item.writable !== false && item.treeList) {
|
|
||||||
itemTools.appendTo(item.treeList.label);
|
itemTools.appendTo(item.treeList.label);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -208,7 +208,7 @@ RED.palette = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function escapeCategory(category) {
|
function escapeCategory(category) {
|
||||||
return category.replace(/[ /.]/g,"_");
|
return category.replace(/[\x00-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/g,"_");
|
||||||
}
|
}
|
||||||
function addNodeType(nt,def) {
|
function addNodeType(nt,def) {
|
||||||
if (getPaletteNode(nt).length) {
|
if (getPaletteNode(nt).length) {
|
||||||
|
@ -604,6 +604,14 @@ RED.subflow = (function() {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function nodeOrJunction(id) {
|
||||||
|
var node = RED.nodes.node(id);
|
||||||
|
if (node) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
return RED.nodes.junction(id);
|
||||||
|
}
|
||||||
|
|
||||||
function convertToSubflow() {
|
function convertToSubflow() {
|
||||||
var selection = RED.view.selection();
|
var selection = RED.view.selection();
|
||||||
if (!selection.nodes) {
|
if (!selection.nodes) {
|
||||||
@ -792,14 +800,15 @@ RED.subflow = (function() {
|
|||||||
|
|
||||||
subflow.in.forEach(function(input) {
|
subflow.in.forEach(function(input) {
|
||||||
input.wires.forEach(function(wire) {
|
input.wires.forEach(function(wire) {
|
||||||
var link = {source: input, sourcePort: 0, target: RED.nodes.node(wire.id) }
|
var link = {source: input, sourcePort: 0, target: nodeOrJunction(wire.id) }
|
||||||
new_links.push(link);
|
new_links.push(link);
|
||||||
RED.nodes.addLink(link);
|
RED.nodes.addLink(link);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
subflow.out.forEach(function(output,i) {
|
subflow.out.forEach(function(output,i) {
|
||||||
output.wires.forEach(function(wire) {
|
output.wires.forEach(function(wire) {
|
||||||
var link = {source: RED.nodes.node(wire.id), sourcePort: wire.port , target: output }
|
var link = {source: nodeOrJunction(wire.id), sourcePort: wire.port , target: output }
|
||||||
new_links.push(link);
|
new_links.push(link);
|
||||||
RED.nodes.addLink(link);
|
RED.nodes.addLink(link);
|
||||||
});
|
});
|
||||||
@ -815,7 +824,7 @@ RED.subflow = (function() {
|
|||||||
n.links = n.links.filter(function(id) {
|
n.links = n.links.filter(function(id) {
|
||||||
var isLocalLink = nodes.hasOwnProperty(id);
|
var isLocalLink = nodes.hasOwnProperty(id);
|
||||||
if (!isLocalLink) {
|
if (!isLocalLink) {
|
||||||
var otherNode = RED.nodes.node(id);
|
var otherNode = nodeOrJunction(id);
|
||||||
if (otherNode && otherNode.links) {
|
if (otherNode && otherNode.links) {
|
||||||
var i = otherNode.links.indexOf(n.id);
|
var i = otherNode.links.indexOf(n.id);
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
@ -831,7 +840,6 @@ RED.subflow = (function() {
|
|||||||
RED.nodes.moveNodeToTab(n, subflow.id);
|
RED.nodes.moveNodeToTab(n, subflow.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var historyEvent = {
|
var historyEvent = {
|
||||||
t:'createSubflow',
|
t:'createSubflow',
|
||||||
nodes:[subflowInstance.id],
|
nodes:[subflowInstance.id],
|
||||||
|
@ -104,7 +104,9 @@ RED.typeSearch = (function() {
|
|||||||
var index = Math.max(0,selected);
|
var index = Math.max(0,selected);
|
||||||
if (index < children.length) {
|
if (index < children.length) {
|
||||||
var n = $(children[index]).find(".red-ui-editableList-item-content").data('data');
|
var n = $(children[index]).find(".red-ui-editableList-item-content").data('data');
|
||||||
|
if (!/^_action_:/.test(n.type)) {
|
||||||
typesUsed[n.type] = Date.now();
|
typesUsed[n.type] = Date.now();
|
||||||
|
}
|
||||||
if (n.def.outputs === 0) {
|
if (n.def.outputs === 0) {
|
||||||
confirm(n);
|
confirm(n);
|
||||||
} else {
|
} else {
|
||||||
@ -173,6 +175,8 @@ RED.typeSearch = (function() {
|
|||||||
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
|
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
|
||||||
if (object.type === "junction") {
|
if (object.type === "junction") {
|
||||||
nodeDiv.addClass("red-ui-palette-icon-junction");
|
nodeDiv.addClass("red-ui-palette-icon-junction");
|
||||||
|
} else if (/^_action_:/.test(object.type)) {
|
||||||
|
nodeDiv.addClass("red-ui-palette-icon-junction")
|
||||||
} else {
|
} else {
|
||||||
var colour = RED.utils.getNodeColor(object.type,def);
|
var colour = RED.utils.getNodeColor(object.type,def);
|
||||||
nodeDiv.css('backgroundColor',colour);
|
nodeDiv.css('backgroundColor',colour);
|
||||||
@ -182,12 +186,15 @@ RED.typeSearch = (function() {
|
|||||||
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
|
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
|
||||||
RED.utils.createIconElement(icon_url, iconContainer, false);
|
RED.utils.createIconElement(icon_url, iconContainer, false);
|
||||||
|
|
||||||
if (object.type !== "junction" && def.inputs > 0) {
|
|
||||||
|
if (!/^_action_:/.test(object.type) && object.type !== "junction") {
|
||||||
|
if (def.inputs > 0) {
|
||||||
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
|
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
|
||||||
}
|
}
|
||||||
if (object.type !== "junction" && def.outputs > 0) {
|
if (def.outputs > 0) {
|
||||||
$('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
|
$('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
||||||
|
|
||||||
@ -207,7 +214,9 @@ RED.typeSearch = (function() {
|
|||||||
}
|
}
|
||||||
function confirm(def) {
|
function confirm(def) {
|
||||||
hide();
|
hide();
|
||||||
|
if (!/^_action_:/.test(def.type)) {
|
||||||
typesUsed[def.type] = Date.now();
|
typesUsed[def.type] = Date.now();
|
||||||
|
}
|
||||||
addCallback(def.type);
|
addCallback(def.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +325,7 @@ RED.typeSearch = (function() {
|
|||||||
function applyFilter(filter,type,def) {
|
function applyFilter(filter,type,def) {
|
||||||
return !filter ||
|
return !filter ||
|
||||||
(
|
(
|
||||||
|
(!filter.spliceMultiple) &&
|
||||||
(!filter.type || type === filter.type) &&
|
(!filter.type || type === filter.type) &&
|
||||||
(!filter.input || type === 'junction' || def.inputs > 0) &&
|
(!filter.input || type === 'junction' || def.inputs > 0) &&
|
||||||
(!filter.output || type === 'junction' || def.outputs > 0)
|
(!filter.output || type === 'junction' || def.outputs > 0)
|
||||||
@ -330,6 +340,13 @@ RED.typeSearch = (function() {
|
|||||||
'inject','debug','function','change','switch','junction'
|
'inject','debug','function','change','switch','junction'
|
||||||
].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); });
|
].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); });
|
||||||
|
|
||||||
|
// if (opts.filter && opts.filter.input && opts.filter.output && !opts.filter.type) {
|
||||||
|
// if (opts.filter.spliceMultiple) {
|
||||||
|
// common.push('_action_:core:split-wires-with-junctions')
|
||||||
|
// }
|
||||||
|
// common.push('_action_:core:split-wire-with-link-nodes')
|
||||||
|
// }
|
||||||
|
|
||||||
var recentlyUsed = Object.keys(typesUsed);
|
var recentlyUsed = Object.keys(typesUsed);
|
||||||
recentlyUsed.sort(function(a,b) {
|
recentlyUsed.sort(function(a,b) {
|
||||||
return typesUsed[b]-typesUsed[a];
|
return typesUsed[b]-typesUsed[a];
|
||||||
@ -354,6 +371,8 @@ RED.typeSearch = (function() {
|
|||||||
var itemDef = RED.nodes.getType(common[i]);
|
var itemDef = RED.nodes.getType(common[i]);
|
||||||
if (common[i] === 'junction') {
|
if (common[i] === 'junction') {
|
||||||
itemDef = { inputs:1, outputs: 1, label: 'junction', type: 'junction'}
|
itemDef = { inputs:1, outputs: 1, label: 'junction', type: 'junction'}
|
||||||
|
} else if (/^_action_:/.test(common[i]) ) {
|
||||||
|
itemDef = { inputs:1, outputs: 1, label: common[i], type: common[i]}
|
||||||
}
|
}
|
||||||
if (itemDef) {
|
if (itemDef) {
|
||||||
item = {
|
item = {
|
||||||
|
@ -1032,6 +1032,8 @@ RED.utils = (function() {
|
|||||||
return "font-awesome/fa-circle-o"
|
return "font-awesome/fa-circle-o"
|
||||||
} else if (def.category === 'config') {
|
} else if (def.category === 'config') {
|
||||||
return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
|
return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
|
||||||
|
} else if ((node && /^_action_:/.test(node.type)) || /^_action_:/.test(def.type)) {
|
||||||
|
return "font-awesome/fa-cogs"
|
||||||
} else if (node && node.type === 'tab') {
|
} else if (node && node.type === 'tab') {
|
||||||
return "red-ui-icons/red-ui-icons-flow"
|
return "red-ui-icons/red-ui-icons-flow"
|
||||||
// return RED.settings.apiRootUrl+"images/subflow_tab.svg"
|
// return RED.settings.apiRootUrl+"images/subflow_tab.svg"
|
||||||
|
@ -336,17 +336,17 @@ RED.view.tools = (function() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNode() {
|
// function addNode() {
|
||||||
var selection = RED.view.selection();
|
// var selection = RED.view.selection();
|
||||||
if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
|
// if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
|
||||||
var selectedNode = selection.nodes[0];
|
// var selectedNode = selection.nodes[0];
|
||||||
RED.view.showQuickAddDialog([
|
// RED.view.showQuickAddDialog([
|
||||||
selectedNode.x + selectedNode.w + 50,selectedNode.y
|
// selectedNode.x + selectedNode.w + 50,selectedNode.y
|
||||||
])
|
// ])
|
||||||
} else {
|
// } else {
|
||||||
RED.view.showQuickAddDialog();
|
// RED.view.showQuickAddDialog();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
function gotoNearestNode(direction) {
|
function gotoNearestNode(direction) {
|
||||||
@ -815,6 +815,9 @@ RED.view.tools = (function() {
|
|||||||
*/
|
*/
|
||||||
function splitWiresWithLinkNodes(wires) {
|
function splitWiresWithLinkNodes(wires) {
|
||||||
let wiresToSplit = wires || RED.view.selection().links;
|
let wiresToSplit = wires || RED.view.selection().links;
|
||||||
|
if (!wiresToSplit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!Array.isArray(wiresToSplit)) {
|
if (!Array.isArray(wiresToSplit)) {
|
||||||
wiresToSplit = [wiresToSplit];
|
wiresToSplit = [wiresToSplit];
|
||||||
}
|
}
|
||||||
@ -1047,6 +1050,135 @@ RED.view.tools = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addJunctionsToWires(wires) {
|
||||||
|
let wiresToSplit = wires || RED.view.selection().links;
|
||||||
|
if (!wiresToSplit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!Array.isArray(wiresToSplit)) {
|
||||||
|
wiresToSplit = [wiresToSplit];
|
||||||
|
}
|
||||||
|
if (wiresToSplit.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var removedLinks = new Set()
|
||||||
|
var addedLinks = []
|
||||||
|
var addedJunctions = []
|
||||||
|
|
||||||
|
var groupedLinks = {}
|
||||||
|
wiresToSplit.forEach(function(l) {
|
||||||
|
var sourceId = l.source.id+":"+l.sourcePort
|
||||||
|
groupedLinks[sourceId] = groupedLinks[sourceId] || []
|
||||||
|
groupedLinks[sourceId].push(l)
|
||||||
|
|
||||||
|
groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
|
||||||
|
groupedLinks[l.target.id].push(l)
|
||||||
|
});
|
||||||
|
var linkGroups = Object.keys(groupedLinks)
|
||||||
|
linkGroups.sort(function(A,B) {
|
||||||
|
return groupedLinks[B].length - groupedLinks[A].length
|
||||||
|
})
|
||||||
|
linkGroups.forEach(function(gid) {
|
||||||
|
var links = groupedLinks[gid]
|
||||||
|
var junction = {
|
||||||
|
_def: {defaults:{}},
|
||||||
|
type: 'junction',
|
||||||
|
z: RED.workspaces.active(),
|
||||||
|
id: RED.nodes.id(),
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: 0, h: 0,
|
||||||
|
outputs: 1,
|
||||||
|
inputs: 1,
|
||||||
|
dirty: true
|
||||||
|
}
|
||||||
|
links = links.filter(function(l) { return !removedLinks.has(l) })
|
||||||
|
if (links.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let pointCount = 0
|
||||||
|
links.forEach(function(l) {
|
||||||
|
if (l._sliceLocation) {
|
||||||
|
junction.x += l._sliceLocation.x
|
||||||
|
junction.y += l._sliceLocation.y
|
||||||
|
delete l._sliceLocation
|
||||||
|
pointCount++
|
||||||
|
} else {
|
||||||
|
junction.x += l.source.x + l.source.w/2 + l.target.x - l.target.w/2
|
||||||
|
junction.y += l.source.y + l.target.y
|
||||||
|
pointCount += 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
junction.x = Math.round(junction.x/pointCount)
|
||||||
|
junction.y = Math.round(junction.y/pointCount)
|
||||||
|
if (RED.view.snapGrid) {
|
||||||
|
let gridSize = RED.view.gridSize()
|
||||||
|
junction.x = (gridSize*Math.round(junction.x/gridSize));
|
||||||
|
junction.y = (gridSize*Math.round(junction.y/gridSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeGroups = new Set()
|
||||||
|
|
||||||
|
RED.nodes.addJunction(junction)
|
||||||
|
addedJunctions.push(junction)
|
||||||
|
let newLink
|
||||||
|
if (gid === links[0].source.id+":"+links[0].sourcePort) {
|
||||||
|
newLink = {
|
||||||
|
source: links[0].source,
|
||||||
|
sourcePort: links[0].sourcePort,
|
||||||
|
target: junction
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newLink = {
|
||||||
|
source: junction,
|
||||||
|
sourcePort: 0,
|
||||||
|
target: links[0].target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addedLinks.push(newLink)
|
||||||
|
RED.nodes.addLink(newLink)
|
||||||
|
links.forEach(function(l) {
|
||||||
|
removedLinks.add(l)
|
||||||
|
RED.nodes.removeLink(l)
|
||||||
|
let newLink
|
||||||
|
if (gid === l.target.id) {
|
||||||
|
newLink = {
|
||||||
|
source: l.source,
|
||||||
|
sourcePort: l.sourcePort,
|
||||||
|
target: junction
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newLink = {
|
||||||
|
source: junction,
|
||||||
|
sourcePort: 0,
|
||||||
|
target: l.target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addedLinks.push(newLink)
|
||||||
|
RED.nodes.addLink(newLink)
|
||||||
|
nodeGroups.add(l.source.g || "__NONE__")
|
||||||
|
nodeGroups.add(l.target.g || "__NONE__")
|
||||||
|
})
|
||||||
|
if (nodeGroups.size === 1) {
|
||||||
|
var group = nodeGroups.values().next().value
|
||||||
|
if (group !== "__NONE__") {
|
||||||
|
RED.group.addToGroup(RED.nodes.group(group), junction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (addedJunctions.length > 0) {
|
||||||
|
RED.history.push({
|
||||||
|
t: 'add',
|
||||||
|
links: addedLinks,
|
||||||
|
junctions: addedJunctions,
|
||||||
|
removedLinks: Array.from(removedLinks)
|
||||||
|
})
|
||||||
|
RED.nodes.dirty(true)
|
||||||
|
}
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
||||||
@ -1109,6 +1241,7 @@ RED.view.tools = (function() {
|
|||||||
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
|
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
|
||||||
|
|
||||||
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
|
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
|
||||||
|
RED.actions.add("core:split-wires-with-junctions", function () { addJunctionsToWires() });
|
||||||
|
|
||||||
RED.actions.add("core:generate-node-names", generateNodeNames )
|
RED.actions.add("core:generate-node-names", generateNodeNames )
|
||||||
|
|
||||||
|
@ -206,7 +206,15 @@ RED.view = (function() {
|
|||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
chart = $("#red-ui-workspace-chart");
|
chart = $("#red-ui-workspace-chart");
|
||||||
|
chart.on('contextmenu', function(evt) {
|
||||||
|
evt.preventDefault()
|
||||||
|
evt.stopPropagation()
|
||||||
|
RED.contextMenu.show({
|
||||||
|
x:evt.clientX-5,
|
||||||
|
y:evt.clientY-5
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
outer = d3.select("#red-ui-workspace-chart")
|
outer = d3.select("#red-ui-workspace-chart")
|
||||||
.append("svg:svg")
|
.append("svg:svg")
|
||||||
.attr("width", space_width)
|
.attr("width", space_width)
|
||||||
@ -230,6 +238,7 @@ RED.view = (function() {
|
|||||||
.on("mousedown", canvasMouseDown)
|
.on("mousedown", canvasMouseDown)
|
||||||
.on("mouseup", canvasMouseUp)
|
.on("mouseup", canvasMouseUp)
|
||||||
.on("mouseenter", function() {
|
.on("mouseenter", function() {
|
||||||
|
d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
|
||||||
if (lasso) {
|
if (lasso) {
|
||||||
if (d3.event.buttons !== 1) {
|
if (d3.event.buttons !== 1) {
|
||||||
lasso.remove();
|
lasso.remove();
|
||||||
@ -245,6 +254,7 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on("mouseleave", canvasMouseLeave)
|
||||||
.on("touchend", function() {
|
.on("touchend", function() {
|
||||||
d3.event.preventDefault();
|
d3.event.preventDefault();
|
||||||
clearTimeout(touchStartTime);
|
clearTimeout(touchStartTime);
|
||||||
@ -385,6 +395,9 @@ RED.view = (function() {
|
|||||||
drag_lines = [];
|
drag_lines = [];
|
||||||
|
|
||||||
RED.events.on("workspace:change",function(event) {
|
RED.events.on("workspace:change",function(event) {
|
||||||
|
// Just in case the mouse left the workspace whilst doing an action,
|
||||||
|
// put us back into default mode so the refresh works
|
||||||
|
mouse_mode = 0
|
||||||
if (event.old !== 0) {
|
if (event.old !== 0) {
|
||||||
workspaceScrollPositions[event.old] = {
|
workspaceScrollPositions[event.old] = {
|
||||||
left:chart.scrollLeft(),
|
left:chart.scrollLeft(),
|
||||||
@ -526,6 +539,23 @@ RED.view = (function() {
|
|||||||
nn.x = mousePos[0];
|
nn.x = mousePos[0];
|
||||||
nn.y = mousePos[1];
|
nn.y = mousePos[1];
|
||||||
|
|
||||||
|
var minX = nn.w/2 -5;
|
||||||
|
if (nn.x < minX) {
|
||||||
|
nn.x = minX;
|
||||||
|
}
|
||||||
|
var minY = nn.h/2 -5;
|
||||||
|
if (nn.y < minY) {
|
||||||
|
nn.y = minY;
|
||||||
|
}
|
||||||
|
var maxX = space_width -nn.w/2 +5;
|
||||||
|
if (nn.x > maxX) {
|
||||||
|
nn.x = maxX;
|
||||||
|
}
|
||||||
|
var maxY = space_height -nn.h +5;
|
||||||
|
if (nn.y > maxY) {
|
||||||
|
nn.y = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
if (snapGrid) {
|
if (snapGrid) {
|
||||||
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
|
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
|
||||||
nn.x -= gridOffset.x;
|
nn.x -= gridOffset.x;
|
||||||
@ -958,6 +988,7 @@ RED.view = (function() {
|
|||||||
if (RED.view.DEBUG) {
|
if (RED.view.DEBUG) {
|
||||||
console.warn("canvasMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
|
console.warn("canvasMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
|
||||||
}
|
}
|
||||||
|
RED.contextMenu.hide();
|
||||||
if (mouse_mode === RED.state.SELECTING_NODE) {
|
if (mouse_mode === RED.state.SELECTING_NODE) {
|
||||||
d3.event.stopPropagation();
|
d3.event.stopPropagation();
|
||||||
return;
|
return;
|
||||||
@ -970,7 +1001,10 @@ RED.view = (function() {
|
|||||||
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
|
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!mousedown_node && !mousedown_link && !mousedown_group) {
|
if (d3.event.button === 2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!mousedown_node && !mousedown_link && !mousedown_group && !d3.event.shiftKey) {
|
||||||
selectedLinks.clear();
|
selectedLinks.clear();
|
||||||
updateSelection();
|
updateSelection();
|
||||||
}
|
}
|
||||||
@ -1024,6 +1058,7 @@ RED.view = (function() {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
var point = options.position || lastClickPosition;
|
var point = options.position || lastClickPosition;
|
||||||
var spliceLink = options.splice;
|
var spliceLink = options.splice;
|
||||||
|
var spliceMultipleLinks = options.spliceMultiple
|
||||||
var targetGroup = options.group;
|
var targetGroup = options.group;
|
||||||
var touchTrigger = options.touchTrigger;
|
var touchTrigger = options.touchTrigger;
|
||||||
|
|
||||||
@ -1036,6 +1071,10 @@ RED.view = (function() {
|
|||||||
var ox = point[0];
|
var ox = point[0];
|
||||||
var oy = point[1];
|
var oy = point[1];
|
||||||
|
|
||||||
|
const offset = $("#red-ui-workspace-chart").offset()
|
||||||
|
var clientX = ox + offset.left - $("#red-ui-workspace-chart").scrollLeft()
|
||||||
|
var clientY = oy + offset.top - $("#red-ui-workspace-chart").scrollTop()
|
||||||
|
|
||||||
if (RED.settings.get("editor").view['view-snap-grid']) {
|
if (RED.settings.get("editor").view['view-snap-grid']) {
|
||||||
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
|
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
|
||||||
point[0] = Math.round(point[0] / gridSize) * gridSize;
|
point[0] = Math.round(point[0] / gridSize) * gridSize;
|
||||||
@ -1087,8 +1126,12 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
hideDragLines();
|
hideDragLines();
|
||||||
}
|
}
|
||||||
if (spliceLink) {
|
if (spliceLink || spliceMultipleLinks) {
|
||||||
filter = {input:true, output:true}
|
filter = {
|
||||||
|
input:true,
|
||||||
|
output:true,
|
||||||
|
spliceMultiple: spliceMultipleLinks
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rebuildQuickAddLink = function() {
|
var rebuildQuickAddLink = function() {
|
||||||
@ -1113,8 +1156,8 @@ RED.view = (function() {
|
|||||||
var lastAddedWidth;
|
var lastAddedWidth;
|
||||||
|
|
||||||
RED.typeSearch.show({
|
RED.typeSearch.show({
|
||||||
x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
|
x:clientX-mainPos.left-node_width/2 - (ox-point[0]),
|
||||||
y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
|
y:clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
|
||||||
disableFocus: touchTrigger,
|
disableFocus: touchTrigger,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
move: function(dx,dy) {
|
move: function(dx,dy) {
|
||||||
@ -1150,7 +1193,13 @@ RED.view = (function() {
|
|||||||
|
|
||||||
var nn;
|
var nn;
|
||||||
var historyEvent;
|
var historyEvent;
|
||||||
if (type === 'junction') {
|
if (/^_action_:/.test(type)) {
|
||||||
|
const actionName = type.substring(9)
|
||||||
|
quickAddActive = false;
|
||||||
|
ghostNode.remove();
|
||||||
|
RED.actions.invoke(actionName)
|
||||||
|
return
|
||||||
|
} else if (type === 'junction') {
|
||||||
nn = {
|
nn = {
|
||||||
_def: {defaults:{}},
|
_def: {defaults:{}},
|
||||||
type: 'junction',
|
type: 'junction',
|
||||||
@ -1716,7 +1765,14 @@ RED.view = (function() {
|
|||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function canvasMouseLeave() {
|
||||||
|
if (mouse_mode !== 0 && d3.event.buttons !== 0) {
|
||||||
|
d3.select(document).on('mouseup.red-ui-workspace-tracker', function() {
|
||||||
|
d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
|
||||||
|
canvasMouseUp.call(this)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
function canvasMouseUp() {
|
function canvasMouseUp() {
|
||||||
lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor];
|
lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor];
|
||||||
if (RED.view.DEBUG) {
|
if (RED.view.DEBUG) {
|
||||||
@ -1724,6 +1780,9 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
var i;
|
var i;
|
||||||
var historyEvent;
|
var historyEvent;
|
||||||
|
if (d3.event.button === 2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (mouse_mode === RED.state.PANNING) {
|
if (mouse_mode === RED.state.PANNING) {
|
||||||
resetMouseVars();
|
resetMouseVars();
|
||||||
return
|
return
|
||||||
@ -1815,8 +1874,20 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
activeLinks.forEach(function(link) {
|
||||||
|
if (!link.selected) {
|
||||||
|
var sourceY = link.source.y
|
||||||
|
var targetY = link.target.y
|
||||||
|
var sourceX = link.source.x+(link.source.w/2) + 10
|
||||||
|
var targetX = link.target.x-(link.target.w/2) - 10
|
||||||
|
if (
|
||||||
|
sourceX > x && sourceX < x2 && sourceY > y && sourceY < y2 &&
|
||||||
|
targetX > x && targetX < x2 && targetY > y && targetY < y2
|
||||||
|
) {
|
||||||
|
selectedLinks.add(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// var selectionChanged = false;
|
// var selectionChanged = false;
|
||||||
// do {
|
// do {
|
||||||
@ -1864,114 +1935,118 @@ RED.view = (function() {
|
|||||||
slicePath = null;
|
slicePath = null;
|
||||||
RED.view.redraw(true);
|
RED.view.redraw(true);
|
||||||
} else if (mouse_mode == RED.state.SLICING_JUNCTION) {
|
} else if (mouse_mode == RED.state.SLICING_JUNCTION) {
|
||||||
var removedLinks = new Set()
|
RED.actions.invoke("core:split-wires-with-junctions")
|
||||||
var addedLinks = []
|
|
||||||
var addedJunctions = []
|
|
||||||
|
|
||||||
var groupedLinks = {}
|
|
||||||
selectedLinks.forEach(function(l) {
|
|
||||||
var sourceId = l.source.id+":"+l.sourcePort
|
|
||||||
groupedLinks[sourceId] = groupedLinks[sourceId] || []
|
|
||||||
groupedLinks[sourceId].push(l)
|
|
||||||
|
|
||||||
groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
|
|
||||||
groupedLinks[l.target.id].push(l)
|
|
||||||
});
|
|
||||||
var linkGroups = Object.keys(groupedLinks)
|
|
||||||
linkGroups.sort(function(A,B) {
|
|
||||||
return groupedLinks[B].length - groupedLinks[A].length
|
|
||||||
})
|
|
||||||
linkGroups.forEach(function(gid) {
|
|
||||||
var links = groupedLinks[gid]
|
|
||||||
var junction = {
|
|
||||||
_def: {defaults:{}},
|
|
||||||
type: 'junction',
|
|
||||||
z: RED.workspaces.active(),
|
|
||||||
id: RED.nodes.id(),
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
w: 0, h: 0,
|
|
||||||
outputs: 1,
|
|
||||||
inputs: 1,
|
|
||||||
dirty: true
|
|
||||||
}
|
|
||||||
links = links.filter(function(l) { return !removedLinks.has(l) })
|
|
||||||
if (links.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
links.forEach(function(l) {
|
|
||||||
junction.x += l._sliceLocation.x
|
|
||||||
junction.y += l._sliceLocation.y
|
|
||||||
})
|
|
||||||
junction.x = Math.round(junction.x/links.length)
|
|
||||||
junction.y = Math.round(junction.y/links.length)
|
|
||||||
if (snapGrid) {
|
|
||||||
junction.x = (gridSize*Math.round(junction.x/gridSize));
|
|
||||||
junction.y = (gridSize*Math.round(junction.y/gridSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodeGroups = new Set()
|
|
||||||
|
|
||||||
RED.nodes.addJunction(junction)
|
|
||||||
addedJunctions.push(junction)
|
|
||||||
let newLink
|
|
||||||
if (gid === links[0].source.id+":"+links[0].sourcePort) {
|
|
||||||
newLink = {
|
|
||||||
source: links[0].source,
|
|
||||||
sourcePort: links[0].sourcePort,
|
|
||||||
target: junction
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newLink = {
|
|
||||||
source: junction,
|
|
||||||
sourcePort: 0,
|
|
||||||
target: links[0].target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addedLinks.push(newLink)
|
|
||||||
RED.nodes.addLink(newLink)
|
|
||||||
links.forEach(function(l) {
|
|
||||||
removedLinks.add(l)
|
|
||||||
RED.nodes.removeLink(l)
|
|
||||||
let newLink
|
|
||||||
if (gid === l.target.id) {
|
|
||||||
newLink = {
|
|
||||||
source: l.source,
|
|
||||||
sourcePort: l.sourcePort,
|
|
||||||
target: junction
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newLink = {
|
|
||||||
source: junction,
|
|
||||||
sourcePort: 0,
|
|
||||||
target: l.target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addedLinks.push(newLink)
|
|
||||||
RED.nodes.addLink(newLink)
|
|
||||||
nodeGroups.add(l.source.g || "__NONE__")
|
|
||||||
nodeGroups.add(l.target.g || "__NONE__")
|
|
||||||
})
|
|
||||||
if (nodeGroups.size === 1) {
|
|
||||||
var group = nodeGroups.values().next().value
|
|
||||||
if (group !== "__NONE__") {
|
|
||||||
RED.group.addToGroup(RED.nodes.group(group), junction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
slicePath.remove();
|
slicePath.remove();
|
||||||
slicePath = null;
|
slicePath = null;
|
||||||
|
|
||||||
if (addedJunctions.length > 0) {
|
// var removedLinks = new Set()
|
||||||
RED.history.push({
|
// var addedLinks = []
|
||||||
t: 'add',
|
// var addedJunctions = []
|
||||||
links: addedLinks,
|
//
|
||||||
junctions: addedJunctions,
|
// var groupedLinks = {}
|
||||||
removedLinks: Array.from(removedLinks)
|
// selectedLinks.forEach(function(l) {
|
||||||
})
|
// var sourceId = l.source.id+":"+l.sourcePort
|
||||||
RED.nodes.dirty(true)
|
// groupedLinks[sourceId] = groupedLinks[sourceId] || []
|
||||||
}
|
// groupedLinks[sourceId].push(l)
|
||||||
RED.view.redraw(true);
|
//
|
||||||
|
// groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
|
||||||
|
// groupedLinks[l.target.id].push(l)
|
||||||
|
// });
|
||||||
|
// var linkGroups = Object.keys(groupedLinks)
|
||||||
|
// linkGroups.sort(function(A,B) {
|
||||||
|
// return groupedLinks[B].length - groupedLinks[A].length
|
||||||
|
// })
|
||||||
|
// linkGroups.forEach(function(gid) {
|
||||||
|
// var links = groupedLinks[gid]
|
||||||
|
// var junction = {
|
||||||
|
// _def: {defaults:{}},
|
||||||
|
// type: 'junction',
|
||||||
|
// z: RED.workspaces.active(),
|
||||||
|
// id: RED.nodes.id(),
|
||||||
|
// x: 0,
|
||||||
|
// y: 0,
|
||||||
|
// w: 0, h: 0,
|
||||||
|
// outputs: 1,
|
||||||
|
// inputs: 1,
|
||||||
|
// dirty: true
|
||||||
|
// }
|
||||||
|
// links = links.filter(function(l) { return !removedLinks.has(l) })
|
||||||
|
// if (links.length === 0) {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// links.forEach(function(l) {
|
||||||
|
// junction.x += l._sliceLocation.x
|
||||||
|
// junction.y += l._sliceLocation.y
|
||||||
|
// })
|
||||||
|
// junction.x = Math.round(junction.x/links.length)
|
||||||
|
// junction.y = Math.round(junction.y/links.length)
|
||||||
|
// if (snapGrid) {
|
||||||
|
// junction.x = (gridSize*Math.round(junction.x/gridSize));
|
||||||
|
// junction.y = (gridSize*Math.round(junction.y/gridSize));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var nodeGroups = new Set()
|
||||||
|
//
|
||||||
|
// RED.nodes.addJunction(junction)
|
||||||
|
// addedJunctions.push(junction)
|
||||||
|
// let newLink
|
||||||
|
// if (gid === links[0].source.id+":"+links[0].sourcePort) {
|
||||||
|
// newLink = {
|
||||||
|
// source: links[0].source,
|
||||||
|
// sourcePort: links[0].sourcePort,
|
||||||
|
// target: junction
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// newLink = {
|
||||||
|
// source: junction,
|
||||||
|
// sourcePort: 0,
|
||||||
|
// target: links[0].target
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// addedLinks.push(newLink)
|
||||||
|
// RED.nodes.addLink(newLink)
|
||||||
|
// links.forEach(function(l) {
|
||||||
|
// removedLinks.add(l)
|
||||||
|
// RED.nodes.removeLink(l)
|
||||||
|
// let newLink
|
||||||
|
// if (gid === l.target.id) {
|
||||||
|
// newLink = {
|
||||||
|
// source: l.source,
|
||||||
|
// sourcePort: l.sourcePort,
|
||||||
|
// target: junction
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// newLink = {
|
||||||
|
// source: junction,
|
||||||
|
// sourcePort: 0,
|
||||||
|
// target: l.target
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// addedLinks.push(newLink)
|
||||||
|
// RED.nodes.addLink(newLink)
|
||||||
|
// nodeGroups.add(l.source.g || "__NONE__")
|
||||||
|
// nodeGroups.add(l.target.g || "__NONE__")
|
||||||
|
// })
|
||||||
|
// if (nodeGroups.size === 1) {
|
||||||
|
// var group = nodeGroups.values().next().value
|
||||||
|
// if (group !== "__NONE__") {
|
||||||
|
// RED.group.addToGroup(RED.nodes.group(group), junction)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// slicePath.remove();
|
||||||
|
// slicePath = null;
|
||||||
|
//
|
||||||
|
// if (addedJunctions.length > 0) {
|
||||||
|
// RED.history.push({
|
||||||
|
// t: 'add',
|
||||||
|
// links: addedLinks,
|
||||||
|
// junctions: addedJunctions,
|
||||||
|
// removedLinks: Array.from(removedLinks)
|
||||||
|
// })
|
||||||
|
// RED.nodes.dirty(true)
|
||||||
|
// }
|
||||||
|
// RED.view.redraw(true);
|
||||||
}
|
}
|
||||||
if (mouse_mode == RED.state.MOVING_ACTIVE) {
|
if (mouse_mode == RED.state.MOVING_ACTIVE) {
|
||||||
if (movingSet.length() > 0) {
|
if (movingSet.length() > 0) {
|
||||||
@ -2832,6 +2907,7 @@ RED.view = (function() {
|
|||||||
|
|
||||||
function portMouseDown(d,portType,portIndex, evt) {
|
function portMouseDown(d,portType,portIndex, evt) {
|
||||||
if (RED.view.DEBUG) { console.warn("portMouseDown", mouse_mode,d,portType,portIndex); }
|
if (RED.view.DEBUG) { console.warn("portMouseDown", mouse_mode,d,portType,portIndex); }
|
||||||
|
RED.contextMenu.hide();
|
||||||
evt = evt || d3.event;
|
evt = evt || d3.event;
|
||||||
if (evt === 1) {
|
if (evt === 1) {
|
||||||
return;
|
return;
|
||||||
@ -3340,6 +3416,7 @@ RED.view = (function() {
|
|||||||
function nodeMouseDown(d) {
|
function nodeMouseDown(d) {
|
||||||
if (RED.view.DEBUG) { console.warn("nodeMouseDown", mouse_mode,d); }
|
if (RED.view.DEBUG) { console.warn("nodeMouseDown", mouse_mode,d); }
|
||||||
focusView();
|
focusView();
|
||||||
|
RED.contextMenu.hide();
|
||||||
if (d3.event.button === 1) {
|
if (d3.event.button === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3722,6 +3799,7 @@ RED.view = (function() {
|
|||||||
if (RED.view.DEBUG) {
|
if (RED.view.DEBUG) {
|
||||||
console.warn("linkMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
|
console.warn("linkMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
|
||||||
}
|
}
|
||||||
|
RED.contextMenu.hide();
|
||||||
if (mouse_mode === RED.state.SELECTING_NODE) {
|
if (mouse_mode === RED.state.SELECTING_NODE) {
|
||||||
d3.event.stopPropagation();
|
d3.event.stopPropagation();
|
||||||
return;
|
return;
|
||||||
@ -3781,6 +3859,9 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function groupMouseUp(g) {
|
function groupMouseUp(g) {
|
||||||
|
if (RED.view.DEBUG) {
|
||||||
|
console.warn("groupMouseUp", { mouse_mode, event: d3.event });
|
||||||
|
}
|
||||||
if (dblClickPrimed && mousedown_group == g && clickElapsed > 0 && clickElapsed < dblClickInterval) {
|
if (dblClickPrimed && mousedown_group == g && clickElapsed > 0 && clickElapsed < dblClickInterval) {
|
||||||
mouse_mode = RED.state.DEFAULT;
|
mouse_mode = RED.state.DEFAULT;
|
||||||
RED.editor.editGroup(g);
|
RED.editor.editGroup(g);
|
||||||
@ -3796,6 +3877,10 @@ RED.view = (function() {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
if (RED.view.DEBUG) {
|
||||||
|
console.warn("groupMouseDown", { mouse_mode, point: mouse, event: d3.event });
|
||||||
|
}
|
||||||
|
RED.contextMenu.hide();
|
||||||
focusView();
|
focusView();
|
||||||
if (d3.event.button === 1) {
|
if (d3.event.button === 1) {
|
||||||
return;
|
return;
|
||||||
@ -5722,10 +5807,15 @@ RED.view = (function() {
|
|||||||
node.dirty = true;
|
node.dirty = true;
|
||||||
node.dirtyStatus = true;
|
node.dirtyStatus = true;
|
||||||
node.changed = true;
|
node.changed = true;
|
||||||
|
if (node.type === "junction") {
|
||||||
|
RED.events.emit("junctions:change",node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
RED.events.emit("nodes:change",node);
|
RED.events.emit("nodes:change",node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (historyEvents.length > 0) {
|
if (historyEvents.length > 0) {
|
||||||
RED.history.push({
|
RED.history.push({
|
||||||
t:"multi",
|
t:"multi",
|
||||||
|
@ -44,7 +44,7 @@ body {
|
|||||||
|
|
||||||
#red-ui-palette-shade, #red-ui-editor-shade, #red-ui-header-shade, #red-ui-sidebar-shade {
|
#red-ui-palette-shade, #red-ui-editor-shade, #red-ui-header-shade, #red-ui-sidebar-shade {
|
||||||
@include shade;
|
@include shade;
|
||||||
z-index: 2;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
#red-ui-sidebar-shade {
|
#red-ui-sidebar-shade {
|
||||||
left: -8px;
|
left: -8px;
|
||||||
|
@ -54,6 +54,21 @@
|
|||||||
white-space: normal !important;
|
white-space: normal !important;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
& > li.pull-left > a,
|
||||||
|
& > li.pull-left > a:focus {
|
||||||
|
padding: 4px 12px 4px 32px;
|
||||||
|
}
|
||||||
|
&.red-ui-menu-dropdown-noicons > li > a,
|
||||||
|
&.red-ui-menu-dropdown-noicons > li > a:focus {
|
||||||
|
padding: 4px 12px 4px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.red-ui-menu-dropdown-submenus > li > a,
|
||||||
|
&.red-ui-menu-dropdown-submenus > li > a:focus {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
& > .active > a,
|
& > .active > a,
|
||||||
& > .active > a:hover,
|
& > .active > a:hover,
|
||||||
@ -145,8 +160,8 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
& > .red-ui-menu-dropdown {
|
& > .red-ui-menu-dropdown {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 100%;
|
left: calc(100% - 5px);
|
||||||
margin-top: -6px;
|
margin-top: 0;
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
}
|
}
|
||||||
&.open > .red-ui-menu-dropdown,
|
&.open > .red-ui-menu-dropdown,
|
||||||
@ -175,10 +190,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.red-ui-menu-dropdown-submenu>a:after {
|
.red-ui-menu-dropdown-submenu.pull-left>a:after {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.red-ui-menu-dropdown-submenu>a:before {
|
.red-ui-menu-dropdown-submenu.pull-left>a:before {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
width: 0;
|
width: 0;
|
||||||
@ -192,7 +207,25 @@
|
|||||||
border-width: 5px 5px 5px 0;
|
border-width: 5px 5px 5px 0;
|
||||||
content: " ";
|
content: " ";
|
||||||
}
|
}
|
||||||
|
.red-ui-menu-dropdown-direction-right {
|
||||||
|
.red-ui-menu-dropdown-submenu>a:after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.red-ui-menu-dropdown-submenu>a:before {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: -15px;
|
||||||
|
/* Caret Arrow */
|
||||||
|
border-color: transparent;
|
||||||
|
border-left-color: $menuCaret;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 5px 0 5px 5px;
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
.red-ui-menu-dropdown-submenu.disabled > a:before {
|
.red-ui-menu-dropdown-submenu.disabled > a:before {
|
||||||
border-right-color: $menuCaret;
|
border-right-color: $menuCaret;
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,7 @@
|
|||||||
width: 120px;
|
width: 120px;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
z-index: 4;
|
||||||
&:not(.red-ui-palette-node-config):not(.red-ui-palette-node-small):first-child {
|
&:not(.red-ui-palette-node-config):not(.red-ui-palette-node-small):first-child {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
background-color: $primary-background;
|
background-color: $primary-background;
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: '';
|
||||||
@ -105,3 +104,4 @@
|
|||||||
background-color: $grip-color;
|
background-color: $grip-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png
vendored
Normal file
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -1,15 +1,30 @@
|
|||||||
export default {
|
export default {
|
||||||
version: "3.0.0-beta.1",
|
version: "3.0.0-beta.3",
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
titleIcon: "fa fa-map-o",
|
titleIcon: "fa fa-map-o",
|
||||||
title: {
|
title: {
|
||||||
"en-US": "Welcome to Node-RED 3.0 Beta 1!",
|
"en-US": "Welcome to Node-RED 3.0 Beta 3!",
|
||||||
"ja": "Node-RED 3.0 ベータ1へようこそ!"
|
"ja": "Node-RED 3.0 ベータ3へようこそ!"
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
"en-US": "<p>This is the first Beta release of Node-RED 3.0. It contains just about everything we have planned for the final release.</p><p>Let's take a moment to discover the new features in this release.</p>",
|
"en-US": "<p>This is the final beta release of Node-RED 3.0.</p><p>Let's take a moment to discover the new features in this release.</p>",
|
||||||
"ja": "<p>これはNode-RED 3.0の最初のベータリリースです。これには、最終リリースで計画しているほぼ全ての機能が含まれています。</p><p>本リリースの新機能を見つけてみましょう。</p>"
|
"ja": "<p>これはNode-RED 3.0の最後のベータリリースです。</p><p>本リリースの新機能を見つけてみましょう。</p>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: {
|
||||||
|
"en-US": "Context Menu",
|
||||||
|
"ja": "コンテキストメニュー"
|
||||||
|
},
|
||||||
|
image: 'images/context-menu.png',
|
||||||
|
description: {
|
||||||
|
"en-US": `<p>The editor now has its own context menu when you
|
||||||
|
right-click in the workspace.</p>
|
||||||
|
<p>This makes many of the built-in actions much easier
|
||||||
|
to access.</p>`,
|
||||||
|
"ja": `<p>ワークスペースで右クリックすると、エディタに独自のコンテキストメニューが表示されるようになりました。</p>
|
||||||
|
<p>これによって多くの組み込み動作を、より簡単に利用できます。</p>`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -19,12 +34,13 @@ export default {
|
|||||||
},
|
},
|
||||||
image: 'images/junction-slice.gif',
|
image: 'images/junction-slice.gif',
|
||||||
description: {
|
description: {
|
||||||
"en-US": `<p>To make it easier to route wires around your flows, it is now possible to
|
"en-US": `<p>To make it easier to route wires around your flows,
|
||||||
add junction nodes that give you more control.</p>
|
it is now possible to add junction nodes that give
|
||||||
<p>Junctions can be added to wires by holding the Shift key, then click and drag with
|
you more control.</p>
|
||||||
the right-hand mouse button across the wires.</p>`,
|
<p>Junctions can be added to wires by holding both the Alt key and the Shift key
|
||||||
|
then click and drag the mouse across the wires.</p>`,
|
||||||
"ja": `<p>フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。</p>
|
"ja": `<p>フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。</p>
|
||||||
<p>シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。</p>`
|
<p>Altキーとシフトキーを押しながらマウスをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。</p>`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -109,9 +109,10 @@ module.exports = function(RED) {
|
|||||||
if (!property) return;
|
if (!property) return;
|
||||||
|
|
||||||
if (valueType === "jsonata") {
|
if (valueType === "jsonata") {
|
||||||
if (p.exp) {
|
if (p.v) {
|
||||||
try {
|
try {
|
||||||
var val = RED.util.evaluateJSONataExpression(p.exp, msg);
|
var exp = RED.util.prepareJSONataExpression(p.v, node);
|
||||||
|
var val = RED.util.evaluateJSONataExpression(exp, msg);
|
||||||
RED.util.setMessageProperty(msg, property, val, true);
|
RED.util.setMessageProperty(msg, property, val, true);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
|
@ -460,7 +460,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs) {
|
var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs, offset) {
|
||||||
var editor = RED.editor.createEditor({
|
var editor = RED.editor.createEditor({
|
||||||
id: id,
|
id: id,
|
||||||
mode: 'ace/mode/nrjavascript',
|
mode: 'ace/mode/nrjavascript',
|
||||||
@ -484,14 +484,14 @@
|
|||||||
extraLibs: extraLibs
|
extraLibs: extraLibs
|
||||||
});
|
});
|
||||||
if (defaultValue && value === "") {
|
if (defaultValue && value === "") {
|
||||||
editor.moveCursorTo(defaultValue.split("\n").length - 1, 0);
|
editor.moveCursorTo(defaultValue.split("\n").length +offset, 0);
|
||||||
}
|
}
|
||||||
editor.__stateId = stateId;
|
editor.__stateId = stateId;
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
this.initEditor = buildEditor('node-input-init-editor', this.id + "/" + "initEditor", false, $("#node-input-initialize").val(), RED._("node-red:function.text.initialize"))
|
this.initEditor = buildEditor('node-input-init-editor', this.id + "/" + "initEditor", false, $("#node-input-initialize").val(), RED._("node-red:function.text.initialize"), undefined, 0);
|
||||||
this.editor = buildEditor('node-input-func-editor', this.id + "/" + "editor", true, $("#node-input-func").val(), undefined, that.libs || [])
|
this.editor = buildEditor('node-input-func-editor', this.id + "/" + "editor", true, $("#node-input-func").val(), undefined, that.libs || [], undefined, -1);
|
||||||
this.finalizeEditor = buildEditor('node-input-finalize-editor', this.id + "/" + "finalizeEditor", false, $("#node-input-finalize").val(), RED._("node-red:function.text.finalize"))
|
this.finalizeEditor = buildEditor('node-input-finalize-editor', this.id + "/" + "finalizeEditor", false, $("#node-input-finalize").val(), RED._("node-red:function.text.finalize"), undefined, 0);
|
||||||
|
|
||||||
RED.library.create({
|
RED.library.create({
|
||||||
url:"functions", // where to get the data from
|
url:"functions", // where to get the data from
|
||||||
|
@ -198,8 +198,8 @@
|
|||||||
category: 'storage',
|
category: 'storage',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: {value:""},
|
name: {value:""},
|
||||||
filename: {value:"filename"},
|
filename: {value:""},
|
||||||
filenameType: {value:"msg"},
|
filenameType: {value:"str"},
|
||||||
appendNewline: {value:true},
|
appendNewline: {value:true},
|
||||||
createDir: {value:false},
|
createDir: {value:false},
|
||||||
overwriteFile: {value:"false"},
|
overwriteFile: {value:"false"},
|
||||||
@ -236,8 +236,8 @@
|
|||||||
label: node._("file.encoding.setbymsg")
|
label: node._("file.encoding.setbymsg")
|
||||||
}).text(label).appendTo(encSel);
|
}).text(label).appendTo(encSel);
|
||||||
$("#node-input-filename").typedInput({
|
$("#node-input-filename").typedInput({
|
||||||
default: "msg",
|
default: "str",
|
||||||
types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"],
|
types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
|
||||||
typeField: $("#node-input-filenameType")
|
typeField: $("#node-input-filenameType")
|
||||||
});
|
});
|
||||||
if(typeof node.filenameType == 'undefined') {
|
if(typeof node.filenameType == 'undefined') {
|
||||||
@ -297,8 +297,8 @@
|
|||||||
category: 'storage',
|
category: 'storage',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: {value:""},
|
name: {value:""},
|
||||||
filename: {value:"filename"},
|
filename: {value:""},
|
||||||
filenameType: {value:"msg"},
|
filenameType: {value:"str"},
|
||||||
format: {value:"utf8"},
|
format: {value:"utf8"},
|
||||||
chunk: {value:false},
|
chunk: {value:false},
|
||||||
sendError: {value: false},
|
sendError: {value: false},
|
||||||
@ -341,8 +341,8 @@
|
|||||||
label: label
|
label: label
|
||||||
}).text(label).appendTo(encSel);
|
}).text(label).appendTo(encSel);
|
||||||
$("#node-input-filename").typedInput({
|
$("#node-input-filename").typedInput({
|
||||||
default: "msg",
|
default: "str",
|
||||||
types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"],
|
types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
|
||||||
typeField: $("#node-input-filenameType")
|
typeField: $("#node-input-filenameType")
|
||||||
});
|
});
|
||||||
if(typeof node.filenameType == 'undefined') {
|
if(typeof node.filenameType == 'undefined') {
|
||||||
|
3
packages/node_modules/@node-red/nodes/locales/en-US/messages.json
vendored
Executable file → Normal file
3
packages/node_modules/@node-red/nodes/locales/en-US/messages.json
vendored
Executable file → Normal file
@ -494,7 +494,6 @@
|
|||||||
"invalid-action-alreadyconnected": "Disconnect from broker before connecting",
|
"invalid-action-alreadyconnected": "Disconnect from broker before connecting",
|
||||||
"invalid-action-badsubscription": "msg.topic is missing or invalid",
|
"invalid-action-badsubscription": "msg.topic is missing or invalid",
|
||||||
"invalid-client-id": "Missing Client ID"
|
"invalid-client-id": "Missing Client ID"
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"httpin": {
|
"httpin": {
|
||||||
@ -646,7 +645,6 @@
|
|||||||
"connection-closed": "connection closed from __host__:__port__",
|
"connection-closed": "connection closed from __host__:__port__",
|
||||||
"connections": "__count__ connection",
|
"connections": "__count__ connection",
|
||||||
"connections_plural": "__count__ connections"
|
"connections_plural": "__count__ connections"
|
||||||
|
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"connection-lost": "connection lost to __host__:__port__",
|
"connection-lost": "connection lost to __host__:__port__",
|
||||||
@ -930,6 +928,7 @@
|
|||||||
"write": "write file",
|
"write": "write file",
|
||||||
"read": "read file",
|
"read": "read file",
|
||||||
"filename": "Filename",
|
"filename": "Filename",
|
||||||
|
"path": "path",
|
||||||
"action": "Action",
|
"action": "Action",
|
||||||
"addnewline": "Add newline (\\n) to each payload?",
|
"addnewline": "Add newline (\\n) to each payload?",
|
||||||
"createdir": "Create directory if it doesn't exist?",
|
"createdir": "Create directory if it doesn't exist?",
|
||||||
|
@ -928,6 +928,7 @@
|
|||||||
"write": "write file",
|
"write": "write file",
|
||||||
"read": "read file",
|
"read": "read file",
|
||||||
"filename": "ファイル名",
|
"filename": "ファイル名",
|
||||||
|
"path": "パス",
|
||||||
"action": "動作",
|
"action": "動作",
|
||||||
"addnewline": "メッセージの入力のたびに改行を追加",
|
"addnewline": "メッセージの入力のたびに改行を追加",
|
||||||
"createdir": "ディレクトリが存在しない場合は作成",
|
"createdir": "ディレクトリが存在しない場合は作成",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/nodes",
|
"name": "@node-red/nodes",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -36,7 +36,7 @@
|
|||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"media-typer": "1.1.0",
|
"media-typer": "1.1.0",
|
||||||
"mqtt": "4.3.7",
|
"mqtt": "4.3.7",
|
||||||
"multer": "1.4.4",
|
"multer": "1.4.5-lts.1",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
"node-watch": "0.7.3",
|
"node-watch": "0.7.3",
|
||||||
"on-headers": "1.0.2",
|
"on-headers": "1.0.2",
|
||||||
|
@ -11,6 +11,7 @@ const exec = require("@node-red/util").exec;
|
|||||||
const log = require("@node-red/util").log;
|
const log = require("@node-red/util").log;
|
||||||
const hooks = require("@node-red/util").hooks;
|
const hooks = require("@node-red/util").hooks;
|
||||||
const url = require("url");
|
const url = require("url");
|
||||||
|
const { createRequire } = require("module");
|
||||||
|
|
||||||
const BUILTIN_MODULES = require('module').builtinModules;
|
const BUILTIN_MODULES = require('module').builtinModules;
|
||||||
|
|
||||||
@ -139,10 +140,15 @@ function importModule(module) {
|
|||||||
}
|
}
|
||||||
const externalModuleDir = getInstallDir();
|
const externalModuleDir = getInstallDir();
|
||||||
const moduleDir = path.join(externalModuleDir,"node_modules",module);
|
const moduleDir = path.join(externalModuleDir,"node_modules",module);
|
||||||
|
// To handle both CJS and ESM we need to resolve the module to the
|
||||||
|
// specific file that is loaded when the module is required/imported
|
||||||
|
// As this won't be on the natural module search path, we use createRequire
|
||||||
|
// to access the module
|
||||||
|
const modulePath = createRequire(moduleDir).resolve(module)
|
||||||
// Import needs the full path to the module's main .js file
|
// Import needs the full path to the module's main .js file
|
||||||
// It also needs to be a file:// url for Windows
|
// It also needs to be a file:// url for Windows
|
||||||
const moduleFile = url.pathToFileURL(require.resolve(moduleDir));
|
const moduleUrl = url.pathToFileURL(modulePath);
|
||||||
return import(moduleFile);
|
return import(moduleUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseModuleName(module) {
|
function parseModuleName(module) {
|
||||||
|
@ -88,9 +88,10 @@ function getLocalFile(file) {
|
|||||||
/**
|
/**
|
||||||
* Synchronously walks the directory looking for node files.
|
* Synchronously walks the directory looking for node files.
|
||||||
* @param dir the directory to search
|
* @param dir the directory to search
|
||||||
|
* @param skipValidNodeRedModules a flag to skip lading icons & files if the directory a valid node-red module
|
||||||
* @return an array of fully-qualified paths to .js files
|
* @return an array of fully-qualified paths to .js files
|
||||||
*/
|
*/
|
||||||
function getLocalNodeFiles(dir) {
|
function getLocalNodeFiles(dir, skipValidNodeRedModules) {
|
||||||
dir = path.resolve(dir);
|
dir = path.resolve(dir);
|
||||||
|
|
||||||
var result = [];
|
var result = [];
|
||||||
@ -102,6 +103,14 @@ function getLocalNodeFiles(dir) {
|
|||||||
return {files: [], icons: []};
|
return {files: [], icons: []};
|
||||||
}
|
}
|
||||||
files.sort();
|
files.sort();
|
||||||
|
// when loading local files, if the path is a valid node-red module
|
||||||
|
// dont include it (will be picked up in scanTreeForNodesModules)
|
||||||
|
if(skipValidNodeRedModules && files.indexOf("package.json") >= 0) {
|
||||||
|
const package = getPackageDetails(dir)
|
||||||
|
if(package.isNodeRedModule) {
|
||||||
|
return {files: [], icons: []};
|
||||||
|
}
|
||||||
|
}
|
||||||
files.forEach(function(fn) {
|
files.forEach(function(fn) {
|
||||||
var stats = fs.statSync(path.join(dir,fn));
|
var stats = fs.statSync(path.join(dir,fn));
|
||||||
if (stats.isFile()) {
|
if (stats.isFile()) {
|
||||||
@ -114,7 +123,7 @@ function getLocalNodeFiles(dir) {
|
|||||||
} else if (stats.isDirectory()) {
|
} else if (stats.isDirectory()) {
|
||||||
// Ignore /.dirs/, /lib/ /node_modules/
|
// Ignore /.dirs/, /lib/ /node_modules/
|
||||||
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
|
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
|
||||||
var subDirResults = getLocalNodeFiles(path.join(dir,fn));
|
var subDirResults = getLocalNodeFiles(path.join(dir,fn), skipValidNodeRedModules);
|
||||||
result = result.concat(subDirResults.files);
|
result = result.concat(subDirResults.files);
|
||||||
icons = icons.concat(subDirResults.icons);
|
icons = icons.concat(subDirResults.icons);
|
||||||
} else if (fn === "icons") {
|
} else if (fn === "icons") {
|
||||||
@ -126,11 +135,19 @@ function getLocalNodeFiles(dir) {
|
|||||||
return {files: result, icons: icons}
|
return {files: result, icons: icons}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scanDirForNodesModules(dir,moduleName) {
|
function scanDirForNodesModules(dir,moduleName,package) {
|
||||||
var results = [];
|
let results = [];
|
||||||
var scopeName;
|
let scopeName;
|
||||||
|
let files
|
||||||
try {
|
try {
|
||||||
var files = fs.readdirSync(dir);
|
let isNodeRedModule = false
|
||||||
|
if(package) {
|
||||||
|
dir = path.join(package.moduleDir,'..')
|
||||||
|
files = [path.basename(package.moduleDir)]
|
||||||
|
moduleName = (package.package ? package.package.name : null) || moduleName
|
||||||
|
isNodeRedModule = package.isNodeRedModule
|
||||||
|
} else {
|
||||||
|
files = fs.readdirSync(dir);
|
||||||
if (moduleName) {
|
if (moduleName) {
|
||||||
var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName);
|
var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName);
|
||||||
if (m) {
|
if (m) {
|
||||||
@ -138,9 +155,10 @@ function scanDirForNodesModules(dir,moduleName) {
|
|||||||
moduleName = m[2];
|
moduleName = m[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var i=0;i<files.length;i++) {
|
}
|
||||||
var fn = files[i];
|
for (let i=0;i<files.length;i++) {
|
||||||
if (/^@/.test(fn)) {
|
let fn = files[i];
|
||||||
|
if (!isNodeRedModule && /^@/.test(fn)) {
|
||||||
if (scopeName && scopeName === fn) {
|
if (scopeName && scopeName === fn) {
|
||||||
// Looking for a specific scope/module
|
// Looking for a specific scope/module
|
||||||
results = results.concat(scanDirForNodesModules(path.join(dir,fn),moduleName));
|
results = results.concat(scanDirForNodesModules(path.join(dir,fn),moduleName));
|
||||||
@ -149,16 +167,18 @@ function scanDirForNodesModules(dir,moduleName) {
|
|||||||
results = results.concat(scanDirForNodesModules(path.join(dir,fn),moduleName));
|
results = results.concat(scanDirForNodesModules(path.join(dir,fn),moduleName));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isIncluded(fn) && !isExcluded(fn) && (!moduleName || fn == moduleName)) {
|
if ((isNodeRedModule || (!moduleName || fn == moduleName)) && (isIncluded(fn) && !isExcluded(fn))) {
|
||||||
var pkgfn = path.join(dir,fn,"package.json");
|
|
||||||
try {
|
try {
|
||||||
var pkg = require(pkgfn);
|
const moduleDir = isNodeRedModule ? package.moduleDir : path.join(dir,fn);
|
||||||
if (pkg['node-red']) {
|
const pkg = package || getPackageDetails(moduleDir)
|
||||||
if (!registryUtil.checkModuleAllowed(pkg.name,pkg.version,loadAllowList,loadDenyList)) {
|
if(pkg.error) {
|
||||||
log.debug("! Module: "+pkg.name+" "+pkg.version+ " *ignored due to denyList*");
|
throw pkg.error
|
||||||
|
}
|
||||||
|
if (pkg.isNodeRedModule) {
|
||||||
|
if (!pkg.allowed) {
|
||||||
|
log.debug("! Module: "+pkg.package.name+" "+pkg.package.version+ " *ignored due to denyList*");
|
||||||
} else {
|
} else {
|
||||||
var moduleDir = path.join(dir,fn);
|
results.push({dir:moduleDir,package:pkg.package});
|
||||||
results.push({dir:moduleDir,package:pkg});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
@ -183,10 +203,13 @@ function scanDirForNodesModules(dir,moduleName) {
|
|||||||
* @return a list of node modules: {dir,package}
|
* @return a list of node modules: {dir,package}
|
||||||
*/
|
*/
|
||||||
function scanTreeForNodesModules(moduleName) {
|
function scanTreeForNodesModules(moduleName) {
|
||||||
var dir = settings.coreNodesDir;
|
let coreNodesDir = settings.coreNodesDir;
|
||||||
var results = [];
|
let results = [];
|
||||||
var userDir;
|
let userDir;
|
||||||
|
let nodesDir;
|
||||||
|
if(settings.nodesDir) {
|
||||||
|
nodesDir = Array.isArray(settings.nodesDir) ? settings.nodesDir : [settings.nodesDir]
|
||||||
|
}
|
||||||
if (settings.userDir) {
|
if (settings.userDir) {
|
||||||
packageList = getPackageList();
|
packageList = getPackageList();
|
||||||
userDir = path.join(settings.userDir,"node_modules");
|
userDir = path.join(settings.userDir,"node_modules");
|
||||||
@ -201,15 +224,46 @@ function scanTreeForNodesModules(moduleName) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir) {
|
if (coreNodesDir) {
|
||||||
var up = path.resolve(path.join(dir,".."));
|
var up = path.resolve(path.join(coreNodesDir,".."));
|
||||||
while (up !== dir) {
|
while (up !== coreNodesDir) {
|
||||||
var pm = path.join(dir,"node_modules");
|
var pm = path.join(coreNodesDir,"node_modules");
|
||||||
if (pm != userDir) {
|
if (pm != userDir) {
|
||||||
results = results.concat(scanDirForNodesModules(pm,moduleName));
|
results = results.concat(scanDirForNodesModules(pm,moduleName));
|
||||||
}
|
}
|
||||||
dir = up;
|
coreNodesDir = up;
|
||||||
up = path.resolve(path.join(dir,".."));
|
up = path.resolve(path.join(coreNodesDir,".."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan nodesDir for any node-red modules
|
||||||
|
/*
|
||||||
|
1. if !exist(package.json) || !package.json.has(node-red) => look for node_modules
|
||||||
|
2. exist(package.json) && package.json.has(node-red) => load this only
|
||||||
|
3. in original scan of nodesDir, ignore if:(exist(package.json) && package.json.has(node-red))
|
||||||
|
*/
|
||||||
|
if (nodesDir) {
|
||||||
|
for (let dirIndex = 0; dirIndex < nodesDir.length; dirIndex++) {
|
||||||
|
const nodeDir = nodesDir[dirIndex];
|
||||||
|
const packageDetails = getPackageDetails(nodeDir)
|
||||||
|
if(packageDetails.isNodeRedModule) {
|
||||||
|
//we have found a node-red module, scan it
|
||||||
|
const nrModules = scanDirForNodesModules(nodeDir, packageDetails.package.name, packageDetails);
|
||||||
|
results = results.concat(nrModules);
|
||||||
|
|
||||||
|
} else if (packageDetails.has_node_modules) {
|
||||||
|
//If this dir has a `node_modues` dir, scan it
|
||||||
|
const nodeModulesDir = path.join(nodeDir, 'node_modules')
|
||||||
|
const nrModules = scanDirForNodesModules(nodeModulesDir, moduleName );
|
||||||
|
results = results.concat(nrModules);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//If this is not a node-red module AND it does NOT have a node_modules dir,
|
||||||
|
//it may be a directory of project directories or a node_modules dir?
|
||||||
|
//scan this instead
|
||||||
|
const nrModules = scanDirForNodesModules(nodeDir, moduleName);
|
||||||
|
results = results.concat(nrModules);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
@ -274,24 +328,26 @@ function getModuleNodeFiles(module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getNodeFiles(disableNodePathScan) {
|
function getNodeFiles(disableNodePathScan) {
|
||||||
var dir;
|
|
||||||
// Find all of the nodes to load
|
// Find all of the nodes to load
|
||||||
var nodeFiles = [];
|
let results;
|
||||||
var results;
|
let nodesDir;
|
||||||
|
if(settings.nodesDir) {
|
||||||
var dir;
|
nodesDir = Array.isArray(settings.nodesDir) ? settings.nodesDir : [settings.nodesDir]
|
||||||
var iconList = [];
|
}
|
||||||
|
let dir;
|
||||||
|
let nodeFiles = [];
|
||||||
|
let iconList = [];
|
||||||
if (settings.coreNodesDir) {
|
if (settings.coreNodesDir) {
|
||||||
results = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
|
results = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
|
||||||
nodeFiles = nodeFiles.concat(results.files);
|
nodeFiles = nodeFiles.concat(results.files);
|
||||||
iconList = iconList.concat(results.icons);
|
iconList = iconList.concat(results.icons);
|
||||||
var defaultLocalesPath = path.join(settings.coreNodesDir,"locales");
|
let defaultLocalesPath = path.join(settings.coreNodesDir,"locales");
|
||||||
i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json");
|
i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.userDir) {
|
if (settings.userDir) {
|
||||||
dir = path.join(settings.userDir,"lib","icons");
|
dir = path.join(settings.userDir,"lib","icons");
|
||||||
var icons = scanIconDir(dir);
|
let icons = scanIconDir(dir);
|
||||||
if (icons.length > 0) {
|
if (icons.length > 0) {
|
||||||
iconList.push({path:dir,icons:icons});
|
iconList.push({path:dir,icons:icons});
|
||||||
}
|
}
|
||||||
@ -301,13 +357,9 @@ function getNodeFiles(disableNodePathScan) {
|
|||||||
nodeFiles = nodeFiles.concat(results.files);
|
nodeFiles = nodeFiles.concat(results.files);
|
||||||
iconList = iconList.concat(results.icons);
|
iconList = iconList.concat(results.icons);
|
||||||
}
|
}
|
||||||
if (settings.nodesDir) {
|
if (nodesDir) {
|
||||||
dir = settings.nodesDir;
|
for (let i = 0; i < nodesDir.length; i++) {
|
||||||
if (typeof settings.nodesDir == "string") {
|
results = getLocalNodeFiles(nodesDir[i], true);
|
||||||
dir = [dir];
|
|
||||||
}
|
|
||||||
for (var i=0;i<dir.length;i++) {
|
|
||||||
results = getLocalNodeFiles(dir[i]);
|
|
||||||
nodeFiles = nodeFiles.concat(results.files);
|
nodeFiles = nodeFiles.concat(results.files);
|
||||||
iconList = iconList.concat(results.icons);
|
iconList = iconList.concat(results.icons);
|
||||||
}
|
}
|
||||||
@ -479,7 +531,52 @@ function getPackageList() {
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Gets the package json object for the supplied `dir`.
|
||||||
|
* If there is no package.json or the `node-red` section is missing, `result.isNodeRedModule` will be `false`.
|
||||||
|
* If there is no package.json `isPackage` will be `false`.
|
||||||
|
* If an error occurs, `result.error` will contain the error.
|
||||||
|
* @param {string} dir The directory to inspect
|
||||||
|
*/
|
||||||
|
function getPackageDetails(dir) {
|
||||||
|
const result = {
|
||||||
|
/** @type {string} The package directory */
|
||||||
|
moduleDir: dir,
|
||||||
|
/** @type {string} The full file path of package.json for this package */
|
||||||
|
packageFile: null,
|
||||||
|
/** @type {boolean} True if this is a valid node-red module */
|
||||||
|
isNodeRedModule: false,
|
||||||
|
/** @type {boolean} True if a package.json file is present */
|
||||||
|
isPackage: false,
|
||||||
|
/** @type {boolean} True if this a node-red module and passes the checks */
|
||||||
|
allowed: false,
|
||||||
|
/** @type {object} The contents of package.json */
|
||||||
|
package: null,
|
||||||
|
}
|
||||||
|
if (!dir) { return result }
|
||||||
|
try {
|
||||||
|
const packagefile = path.join(dir,'package.json')
|
||||||
|
result.has_node_modules = fs.existsSync(path.join(dir,'node_modules'))
|
||||||
|
if(!fs.existsSync(packagefile)) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
result.packageFile = packagefile
|
||||||
|
const pkg = require(packagefile)
|
||||||
|
result.package = pkg
|
||||||
|
if(result.package) {
|
||||||
|
result.allowed = true
|
||||||
|
result.isPackage = true
|
||||||
|
result.isNodeRedModule = typeof result.package['node-red'] === 'object'
|
||||||
|
if(result.isNodeRedModule) {
|
||||||
|
result.isNodeRedModule = true;
|
||||||
|
result.allowed = registryUtil.checkModuleAllowed(pkg.name,pkg.version,loadAllowList,loadDenyList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
result.error = err; // this is not a package we are interested in!
|
||||||
|
}
|
||||||
|
return result || result;
|
||||||
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: init,
|
init: init,
|
||||||
getNodeFiles: getNodeFiles,
|
getNodeFiles: getNodeFiles,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/registry",
|
"name": "@node-red/registry",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,11 +16,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "3.0.0-beta.2",
|
"@node-red/util": "3.0.0-beta.3",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "10.1.0",
|
||||||
"semver": "7.3.7",
|
"semver": "7.3.7",
|
||||||
"tar": "6.1.11",
|
"tar": "6.1.11",
|
||||||
"uglify-js": "3.15.5"
|
"uglify-js": "3.16.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ var api = module.exports = {
|
|||||||
safeSettings.context = runtime.nodes.listContextStores();
|
safeSettings.context = runtime.nodes.listContextStores();
|
||||||
if (runtime.settings.editorTheme && runtime.settings.editorTheme.codeEditor) {
|
if (runtime.settings.editorTheme && runtime.settings.editorTheme.codeEditor) {
|
||||||
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
safeSettings.codeEditor = runtime.settings.editorTheme.codeEditor || {};
|
||||||
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "ace";
|
safeSettings.codeEditor.lib = safeSettings.codeEditor.lib || "monaco";
|
||||||
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
safeSettings.codeEditor.options = safeSettings.codeEditor.options || {};
|
||||||
}
|
}
|
||||||
safeSettings.libraries = runtime.library.getLibraries();
|
safeSettings.libraries = runtime.library.getLibraries();
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
"httpStatic": "HTTP Static : __path__"
|
"httpStatic": "HTTP Static : __path__"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"server": {
|
"server": {
|
||||||
"loading": "Loading palette nodes",
|
"loading": "Loading palette nodes",
|
||||||
"palette-editor": {
|
"palette-editor": {
|
||||||
@ -61,7 +60,6 @@
|
|||||||
"function-required": "httpsRefreshInterval requires https property to be a function"
|
"function-required": "httpsRefreshInterval requires https property to be a function"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"api": {
|
"api": {
|
||||||
"flows": {
|
"flows": {
|
||||||
"error-save": "Error saving flows: __message__",
|
"error-save": "Error saving flows: __message__",
|
||||||
@ -79,13 +77,11 @@
|
|||||||
"error-enable": "Failed to enable node:"
|
"error-enable": "Failed to enable node:"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"comms": {
|
"comms": {
|
||||||
"error": "Communication channel error: __message__",
|
"error": "Communication channel error: __message__",
|
||||||
"error-server": "Communication server error: __message__",
|
"error-server": "Communication server error: __message__",
|
||||||
"error-send": "Communication send error: __message__"
|
"error-send": "Communication send error: __message__"
|
||||||
},
|
},
|
||||||
|
|
||||||
"settings": {
|
"settings": {
|
||||||
"user-not-available": "Cannot save user settings: __message__",
|
"user-not-available": "Cannot save user settings: __message__",
|
||||||
"not-available": "Settings not available",
|
"not-available": "Settings not available",
|
||||||
@ -150,7 +146,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"storage": {
|
"storage": {
|
||||||
"index": {
|
"index": {
|
||||||
"forbidden-flow-name": "forbidden flow name"
|
"forbidden-flow-name": "forbidden flow name"
|
||||||
@ -180,7 +175,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"context": {
|
"context": {
|
||||||
"log-store-init": "Context store : '__name__' [__info__]",
|
"log-store-init": "Context store : '__name__' [__info__]",
|
||||||
"error-loading-module": "Error loading context store: __message__",
|
"error-loading-module": "Error loading context store: __message__",
|
||||||
@ -195,5 +189,4 @@
|
|||||||
"error-write": "Error writing context: __message__"
|
"error-write": "Error writing context: __message__"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/runtime",
|
"name": "@node-red/runtime",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -16,8 +16,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/registry": "3.0.0-beta.2",
|
"@node-red/registry": "3.0.0-beta.3",
|
||||||
"@node-red/util": "3.0.0-beta.2",
|
"@node-red/util": "3.0.0-beta.3",
|
||||||
"async-mutex": "0.3.2",
|
"async-mutex": "0.3.2",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"express": "4.18.1",
|
"express": "4.18.1",
|
||||||
|
@ -641,7 +641,12 @@ function evaluateNodeProperty(value, type, node, msg, callback) {
|
|||||||
result = Date.now();
|
result = Date.now();
|
||||||
} else if (type === 'bin') {
|
} else if (type === 'bin') {
|
||||||
var data = JSON.parse(value);
|
var data = JSON.parse(value);
|
||||||
|
if (Array.isArray(data) || (typeof(data) === "string")) {
|
||||||
result = Buffer.from(data);
|
result = Buffer.from(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw createError("INVALID_BUFFER_DATA", "Not string or array");
|
||||||
|
}
|
||||||
} else if (type === 'msg' && msg) {
|
} else if (type === 'msg' && msg) {
|
||||||
try {
|
try {
|
||||||
result = getMessageProperty(msg,value);
|
result = getMessageProperty(msg,value);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@node-red/util",
|
"name": "@node-red/util",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "10.1.0",
|
||||||
"i18next": "21.8.2",
|
"i18next": "21.8.10",
|
||||||
"json-stringify-safe": "5.0.1",
|
"json-stringify-safe": "5.0.1",
|
||||||
"jsonata": "1.8.6",
|
"jsonata": "1.8.6",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
10
packages/node_modules/node-red/package.json
vendored
10
packages/node_modules/node-red/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red",
|
"name": "node-red",
|
||||||
"version": "3.0.0-beta.2",
|
"version": "3.0.0-beta.3",
|
||||||
"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",
|
||||||
@ -31,10 +31,10 @@
|
|||||||
"flow"
|
"flow"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/editor-api": "3.0.0-beta.2",
|
"@node-red/editor-api": "3.0.0-beta.3",
|
||||||
"@node-red/runtime": "3.0.0-beta.2",
|
"@node-red/runtime": "3.0.0-beta.3",
|
||||||
"@node-red/util": "3.0.0-beta.2",
|
"@node-red/util": "3.0.0-beta.3",
|
||||||
"@node-red/nodes": "3.0.0-beta.2",
|
"@node-red/nodes": "3.0.0-beta.3",
|
||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"express": "4.18.1",
|
"express": "4.18.1",
|
||||||
|
21
packages/node_modules/node-red/settings.js
vendored
21
packages/node_modules/node-red/settings.js
vendored
@ -302,6 +302,27 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** Configure the logging output */
|
||||||
|
logging: {
|
||||||
|
/** Only console logging is currently supported */
|
||||||
|
console: {
|
||||||
|
/** Level of logging to be recorded. Options are:
|
||||||
|
* fatal - only those errors which make the application unusable should be recorded
|
||||||
|
* error - record errors which are deemed fatal for a particular request + fatal errors
|
||||||
|
* warn - record problems which are non fatal + errors + fatal errors
|
||||||
|
* info - record information about the general running of the application + warn + error + fatal errors
|
||||||
|
* debug - record information which is more verbose than info + info + warn + error + fatal errors
|
||||||
|
* trace - record very detailed logging + debug + info + warn + error + fatal errors
|
||||||
|
* off - turn off all logging (doesn't affect metrics or audit)
|
||||||
|
*/
|
||||||
|
level: "info",
|
||||||
|
/** Whether or not to include metric events in the log output */
|
||||||
|
metrics: false,
|
||||||
|
/** Whether or not to include audit events in the log output */
|
||||||
|
audit: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/** Context Storage
|
/** Context Storage
|
||||||
* The following property can be used to enable context storage. The configuration
|
* The following property can be used to enable context storage. The configuration
|
||||||
* provided here will enable file-based context that flushes to disk every 30 seconds.
|
* provided here will enable file-based context that flushes to disk every 30 seconds.
|
||||||
|
@ -906,6 +906,7 @@ describe('inject node', function() {
|
|||||||
msg.should.have.property("str1", "1"); //injected prop
|
msg.should.have.property("str1", "1"); //injected prop
|
||||||
msg.should.have.property("num1", 1); //injected prop
|
msg.should.have.property("num1", 1); //injected prop
|
||||||
msg.should.have.property("bool1", true); //injected prop
|
msg.should.have.property("bool1", true); //injected prop
|
||||||
|
msg.should.have.property("jsonata1", "AB"); //injected prop
|
||||||
|
|
||||||
helper.clearFlows().then(function() {
|
helper.clearFlows().then(function() {
|
||||||
done();
|
done();
|
||||||
@ -919,6 +920,7 @@ describe('inject node', function() {
|
|||||||
{p:"str1", v:"1", vt:"str"}, //new prop
|
{p:"str1", v:"1", vt:"str"}, //new prop
|
||||||
{p:"num1", v:"1", vt:"num"}, //new prop
|
{p:"num1", v:"1", vt:"num"}, //new prop
|
||||||
{p:"bool1", v:"true", vt:"bool"}, //new prop
|
{p:"bool1", v:"true", vt:"bool"}, //new prop
|
||||||
|
{p:"jsonata1", v:'"A" & "B"', vt:"jsonata"}, //new prop
|
||||||
]})
|
]})
|
||||||
.expect(200).end(function(err) {
|
.expect(200).end(function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -14,26 +14,41 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var should = require("should");
|
const should = require("should");
|
||||||
var sinon = require("sinon");
|
const sinon = require("sinon");
|
||||||
var path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
var NR_TEST_UTILS = require("nr-test-utils");
|
const NR_TEST_UTILS = require("nr-test-utils");
|
||||||
|
|
||||||
var localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem");
|
const localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem");
|
||||||
|
|
||||||
var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
|
const resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
|
||||||
var userDir = path.resolve(path.join(__dirname,"resources","userDir"));
|
const userDir = path.resolve(path.join(__dirname,"resources","userDir"));
|
||||||
var moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule"));
|
|
||||||
|
|
||||||
var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
|
const nodesDir1 = path.resolve(path.join(__dirname,"resources","nodesDir1"))
|
||||||
|
const nodesDir2 = path.resolve(path.join(__dirname,"resources","nodesDir2"))
|
||||||
|
const nodesDir3 =path.resolve(path.join(__dirname,"resources","nodesDir3"))
|
||||||
|
|
||||||
|
const moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule"));
|
||||||
|
|
||||||
|
const i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
|
||||||
|
|
||||||
describe("red/nodes/registry/localfilesystem",function() {
|
describe("red/nodes/registry/localfilesystem",function() {
|
||||||
|
var stubs = [];
|
||||||
|
function stubPathJoin() {
|
||||||
|
var _join = path.join;
|
||||||
|
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
||||||
|
if (arguments[0] == resourcesDir) {
|
||||||
|
// This stops the module tree scan from going any higher
|
||||||
|
// up the tree than resourcesDir.
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
return _join.apply(null,arguments);
|
||||||
|
}));
|
||||||
|
}
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
stubs.push(sinon.stub(i18n,"registerMessageCatalog").callsFake(function() { return Promise.resolve(); }));
|
stubs.push(sinon.stub(i18n,"registerMessageCatalog").callsFake(function() { return Promise.resolve(); }));
|
||||||
})
|
})
|
||||||
|
|
||||||
var stubs = [];
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
while(stubs.length) {
|
while(stubs.length) {
|
||||||
stubs.pop().restore();
|
stubs.pop().restore();
|
||||||
@ -129,16 +144,76 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
|
checkNodes(nm.nodes,['TestNode5'],['TestNode1']);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
it("Finds nodes module path",function(done) {
|
it("Finds nodes and icons only in nodesDir with files, icons and valid node-red packages",function(done) {
|
||||||
var _join = path.join;
|
localfilesystem.init({nodesDir:nodesDir1});
|
||||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
const nodeList = localfilesystem.getNodeFiles(true);
|
||||||
if (arguments[0] == resourcesDir) {
|
nodeList.should.have.a.property("node-red");
|
||||||
// This stops the module tree scan from going any higher
|
const nm = nodeList['node-red'];
|
||||||
// up the tree than resourcesDir.
|
nm.should.have.a.property('name','node-red');
|
||||||
return arguments[0];
|
nm.should.have.a.property("nodes");
|
||||||
|
nm.should.have.a.property("icons");
|
||||||
|
checkNodes(nm.nodes,['loose1', 'loose2'], []);
|
||||||
|
//1 icon in nodesDir1/icons/ - should be found
|
||||||
|
//2 icons in nodesDir1/loose2/icons/ - should be found
|
||||||
|
//1 icons in nodesDir1/node-red-node-testnode/icons/ - should be found
|
||||||
|
//1 icons in nodesDir1/regular_module/icons/ - should NOT be found
|
||||||
|
//total icon sets 3, total icons 4
|
||||||
|
nm.icons.should.have.a.property("length", 3);
|
||||||
|
nm.icons[0].should.have.a.property("path")
|
||||||
|
nm.icons[0].should.have.a.property("icons", ['loose1.svg'])
|
||||||
|
nm.icons[1].should.have.a.property("path")
|
||||||
|
nm.icons[1].should.have.a.property("icons", ['loose2.svg', 'loose2b.svg'])
|
||||||
|
nm.icons[2].should.have.a.property("path")
|
||||||
|
nm.icons[2].should.have.a.property("icons", ['test.svg'])
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it("Should not find node-red node in nodesDir with files, icons and valid node-red packages",function(done) {
|
||||||
|
// path contains a regular node module and a node-red node module
|
||||||
|
localfilesystem.init({nodesDir:path.join(nodesDir1)});
|
||||||
|
const nodeList = localfilesystem.getNodeFiles(true);
|
||||||
|
nodeList.should.have.a.property("node-red");
|
||||||
|
const nm = nodeList['node-red'];
|
||||||
|
nm.should.have.a.property('name','node-red');
|
||||||
|
nm.should.have.a.property("nodes");
|
||||||
|
nm.nodes.should.have.a.property("loose1");
|
||||||
|
nm.nodes.should.have.a.property("loose2");
|
||||||
|
nm.nodes.should.not.have.a.property("regular_module");
|
||||||
|
nm.nodes.should.not.have.a.property("node-red-node-testnode");
|
||||||
|
for (let key of Object.keys(nm.nodes)) {
|
||||||
|
const n = nm.nodes[key];
|
||||||
|
n.file.indexOf("regular_module").should.eql(-1, `found icons in a node-red module`)
|
||||||
|
n.file.indexOf("node-red-node-testnode").should.eql(-1, `found icons in a node-red module`)
|
||||||
}
|
}
|
||||||
return _join.apply(null,arguments);
|
//1 icon in nodesDir1/icons/ - should be found
|
||||||
}));
|
//2 icons in nodesDir1/loose2/icons/ - should be found
|
||||||
|
//1 icons in nodesDir1/node-red-node-testnode/icons/ - should be found
|
||||||
|
//1 icons in nodesDir1/regular_module/icons/ - should NOT be found
|
||||||
|
//total icon sets 3, total icons 4
|
||||||
|
nm.should.have.a.property("icons");
|
||||||
|
nm.icons.should.have.a.property("length", 3);
|
||||||
|
let iconCount = 0;
|
||||||
|
for (let index = 0; index < nm.icons.length; index++) {
|
||||||
|
const iconDir = nm.icons[index];
|
||||||
|
iconCount += iconDir.icons.length
|
||||||
|
iconDir.path.indexOf("node-red-node-testnode").should.eql(-1, `should not find icons in a node-red module`)
|
||||||
|
}
|
||||||
|
should(iconCount).eql(4, "Should find only 4 icons")
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it("Should not find node-red node in nodesDir when regular package and valid node-red packages",function(done) {
|
||||||
|
localfilesystem.init({nodesDir:path.join(nodesDir1,"regular_module")});
|
||||||
|
const nodeList = localfilesystem.getNodeFiles(true);
|
||||||
|
nodeList.should.have.a.property("node-red");
|
||||||
|
const nm = nodeList['node-red'];
|
||||||
|
nm.should.have.a.property('name','node-red');
|
||||||
|
nm.should.have.a.property("nodes", {});
|
||||||
|
nm.should.have.a.property("icons");
|
||||||
|
nm.icons.should.have.a.property("length", 1); //should find 1 icons folder
|
||||||
|
nm.icons[0].should.have.a.property("icons", [ 'test.svg' ]); //should find 1 icon in regular package
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it("Finds nodes module path",function(done) {
|
||||||
|
stubPathJoin()
|
||||||
localfilesystem.init({coreNodesDir:moduleDir});
|
localfilesystem.init({coreNodesDir:moduleDir});
|
||||||
var nodeList = localfilesystem.getNodeFiles();
|
var nodeList = localfilesystem.getNodeFiles();
|
||||||
nodeList.should.have.a.property("node-red");
|
nodeList.should.have.a.property("node-red");
|
||||||
@ -166,8 +241,6 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(moduleDir,"locales")));
|
i18n.registerMessageCatalog.lastCall.args[1].should.eql(path.resolve(path.join(moduleDir,"locales")));
|
||||||
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
|
i18n.registerMessageCatalog.lastCall.args[2].should.eql('messages.json');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
it.skip("finds locales directory");
|
it.skip("finds locales directory");
|
||||||
@ -205,15 +278,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
});
|
});
|
||||||
describe("#getModuleFiles",function() {
|
describe("#getModuleFiles",function() {
|
||||||
it("gets a nodes module files",function(done) {
|
it("gets a nodes module files",function(done) {
|
||||||
var _join = path.join;
|
stubPathJoin()
|
||||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
|
||||||
if (arguments[0] == resourcesDir) {
|
|
||||||
// This stops the module tree scan from going any higher
|
|
||||||
// up the tree than resourcesDir.
|
|
||||||
return arguments[0];
|
|
||||||
}
|
|
||||||
return _join.apply(null,arguments);
|
|
||||||
}));
|
|
||||||
localfilesystem.init({coreNodesDir:moduleDir});
|
localfilesystem.init({coreNodesDir:moduleDir});
|
||||||
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
|
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
|
||||||
nodeModule.should.have.a.property('TestNodeModule');
|
nodeModule.should.have.a.property('TestNodeModule');
|
||||||
@ -230,16 +295,87 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
it("Finds only 1 node-red node in nodesDir amongst legacy nodes and regular nodes",function(done) {
|
||||||
|
stubPathJoin()
|
||||||
|
localfilesystem.init({nodesDir:[path.join(nodesDir1,"node-red-node-testnode")]});
|
||||||
|
const nodeModule = localfilesystem.getModuleFiles();
|
||||||
|
const loaded = Object.keys(nodeModule)
|
||||||
|
loaded.should.have.a.property("length", 1)
|
||||||
|
loaded.indexOf('node-red-node-testnode').should.greaterThan(-1, "Should load node-red-node-testnode")
|
||||||
|
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('name','node-red-node-testnode');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('version','1.0.0');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('nodes');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('path');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('user', false);
|
||||||
|
checkNodes(nodeModule['node-red-node-testnode'].nodes,['testnode'],[],'node-red-node-testnode');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it("Finds a node-red node in nodesDir with a sub dir containing valid node-red package",function(done) {
|
||||||
|
stubPathJoin()
|
||||||
|
localfilesystem.init({nodesDir:[path.join(nodesDir1,"node-red-node-testnode")]});
|
||||||
|
const nodeModule = localfilesystem.getModuleFiles();
|
||||||
|
const loaded = Object.keys(nodeModule)
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('name','node-red-node-testnode');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('version','1.0.0');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('nodes');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('path');
|
||||||
|
nodeModule['node-red-node-testnode'].should.have.a.property('user', false);
|
||||||
|
checkNodes(nodeModule['node-red-node-testnode'].nodes,['testnode'],[],'node-red-node-testnode');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it("Finds 2 node-red modules and 1 plugin in nodesDir (in root of dir)",function(done) {
|
||||||
|
stubPathJoin()
|
||||||
|
localfilesystem.init({nodesDir:[nodesDir2]});
|
||||||
|
const nodeModule = localfilesystem.getModuleFiles();
|
||||||
|
const loaded = Object.keys(nodeModule)
|
||||||
|
loaded.should.have.a.property("length", 3)
|
||||||
|
loaded.indexOf('@test/testnode').should.greaterThan(-1, "Should load @test/testnode")
|
||||||
|
loaded.indexOf('testnode2').should.greaterThan(-1, "Should load testnode2")
|
||||||
|
loaded.indexOf('test-theme2').should.greaterThan(-1, "Should load test-theme2")
|
||||||
|
|
||||||
|
nodeModule['@test/testnode'].should.have.a.property('name','@test/testnode');
|
||||||
|
nodeModule['@test/testnode'].should.have.a.property('version','1.0.0');
|
||||||
|
nodeModule['@test/testnode'].should.have.a.property('nodes');
|
||||||
|
nodeModule['@test/testnode'].should.have.a.property('path');
|
||||||
|
nodeModule['@test/testnode'].should.have.a.property('user', false);
|
||||||
|
|
||||||
|
nodeModule['testnode2'].should.have.a.property('name','testnode2');
|
||||||
|
nodeModule['testnode2'].should.have.a.property('version','1.0.0');
|
||||||
|
nodeModule['testnode2'].should.have.a.property('nodes');
|
||||||
|
nodeModule['testnode2'].should.have.a.property('path');
|
||||||
|
nodeModule['testnode2'].should.have.a.property('user', false);
|
||||||
|
|
||||||
|
nodeModule['test-theme2'].should.have.a.property('name','test-theme2');
|
||||||
|
|
||||||
|
nodeModule['test-theme2'].should.have.a.property('version','0.0.1');
|
||||||
|
nodeModule['test-theme2'].should.have.a.property('nodes', {});
|
||||||
|
nodeModule['test-theme2'].should.have.a.property('path');
|
||||||
|
nodeModule['test-theme2'].should.have.a.property('user', false);
|
||||||
|
nodeModule['test-theme2'].should.have.a.property('plugins');
|
||||||
|
nodeModule['test-theme2'].plugins.should.have.a.property('test-theme2');
|
||||||
|
nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('name','test-theme2');
|
||||||
|
nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('module','test-theme2');
|
||||||
|
nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('version', '0.0.1');
|
||||||
|
nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('file');
|
||||||
|
nodeModule['test-theme2'].plugins['test-theme2'].should.have.a.property('local', false);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
it("Finds 2 node-red modules and 1 plugin in nodesDir pointing to a node_modules dir",function(done) {
|
||||||
|
stubPathJoin()
|
||||||
|
localfilesystem.init({nodesDir:[path.join(nodesDir3, "node_modules")]});
|
||||||
|
const nodeModule = localfilesystem.getModuleFiles();
|
||||||
|
const loaded = Object.keys(nodeModule)
|
||||||
|
loaded.should.have.a.property("length", 3)
|
||||||
|
|
||||||
|
loaded.indexOf('@test/testnode').should.greaterThan(-1, "Should load @test/testnode")
|
||||||
|
loaded.indexOf('@test/test-theme3').should.greaterThan(-1, "Should load test-theme3")
|
||||||
|
loaded.indexOf('testnode3').should.greaterThan(-1, "Should load testnode3")
|
||||||
|
done();
|
||||||
|
});
|
||||||
it("throws an error if a node isn't found",function(done) {
|
it("throws an error if a node isn't found",function(done) {
|
||||||
var _join = path.join;
|
stubPathJoin()
|
||||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
|
||||||
if (arguments[0] == resourcesDir) {
|
|
||||||
// This stops the module tree scan from going any higher
|
|
||||||
// up the tree than resourcesDir.
|
|
||||||
return arguments[0];
|
|
||||||
}
|
|
||||||
return _join.apply(null,arguments);
|
|
||||||
}));
|
|
||||||
localfilesystem.init({coreNodesDir:moduleDir});
|
localfilesystem.init({coreNodesDir:moduleDir});
|
||||||
/*jshint immed: false */
|
/*jshint immed: false */
|
||||||
(function(){
|
(function(){
|
||||||
@ -250,15 +386,7 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
it.skip("finds locales directory");
|
it.skip("finds locales directory");
|
||||||
it.skip("finds icon path directory");
|
it.skip("finds icon path directory");
|
||||||
it("scans icon files with a module file",function(done) {
|
it("scans icon files with a module file",function(done) {
|
||||||
var _join = path.join;
|
stubPathJoin()
|
||||||
stubs.push(sinon.stub(path,"join").callsFake(function() {
|
|
||||||
if (arguments[0] == resourcesDir) {
|
|
||||||
// This stops the module tree scan from going any higher
|
|
||||||
// up the tree than resourcesDir.
|
|
||||||
return arguments[0];
|
|
||||||
}
|
|
||||||
return _join.apply(null,arguments);
|
|
||||||
}));
|
|
||||||
localfilesystem.init({
|
localfilesystem.init({
|
||||||
coreNodesDir: moduleDir
|
coreNodesDir: moduleDir
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M10.004 14.499h20M10.004 46.503h20M10.004 22.5h20M10.004 30.501h20M10.004 38.502h20" stroke="#fff" stroke-width="2.9997000000000003"/></svg>
|
After Width: | Height: | Size: 236 B |
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
console.log("hello from loose1.html")
|
||||||
|
})()
|
||||||
|
</script>
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from loose1.js")
|
||||||
|
})()
|
@ -0,0 +1 @@
|
|||||||
|
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M30.999 31.005v-3h-6.762s.812-12.397 1.162-14 .597-3.35 2.628-3.103 1.971 3.103 1.971 3.103l4.862-.016s-.783-3.984-2.783-5.984-7.946-1.7-9.633.03c-1.687 1.73-2.302 5.065-2.597 6.422-.588 4.5-.854 9.027-1.248 13.547h-8.6v3H18.1s-.812 12.398-1.162 14-.597 3.35-2.628 3.103-1.972-3.102-1.972-3.102l-4.862.015s.783 3.985 2.783 5.985c2 2 7.946 1.699 9.634-.031 1.687-1.73 2.302-5.065 2.597-6.422.587-4.5.854-9.027 1.248-13.547z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 539 B |
@ -0,0 +1 @@
|
|||||||
|
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M7 38.98v3.983h11v12l13-23H19l-.463.017c-1.28 4.048-5.066 6.983-9.537 6.983zm12-11.017h12l-13-23v12H7V20.9l2 .064c4.467 0 8.25 2.93 9.534 6.972zM6.95 24.22a6 6 0 1 1-.083 11.456" fill="#fff" style="isolation:auto;mix-blend-mode:normal"/></svg>
|
After Width: | Height: | Size: 339 B |
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
console.log("hello from loose2.html")
|
||||||
|
})()
|
||||||
|
</script>
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from loose2.js")
|
||||||
|
})()
|
@ -0,0 +1 @@
|
|||||||
|
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M30.999 31.005v-3h-6.762s.812-12.397 1.162-14 .597-3.35 2.628-3.103 1.971 3.103 1.971 3.103l4.862-.016s-.783-3.984-2.783-5.984-7.946-1.7-9.633.03c-1.687 1.73-2.302 5.065-2.597 6.422-.588 4.5-.854 9.027-1.248 13.547h-8.6v3H18.1s-.812 12.398-1.162 14-.597 3.35-2.628 3.103-1.972-3.102-1.972-3.102l-4.862.015s.783 3.985 2.783 5.985c2 2 7.946 1.699 9.634-.031 1.687-1.73 2.302-5.065 2.597-6.422.587-4.5.854-9.027 1.248-13.547z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 539 B |
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from regular module main.js")
|
||||||
|
})()
|
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "node-red-node-testnode",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A node-red node that does nothing other than exist",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node-red"
|
||||||
|
],
|
||||||
|
"node-red": {
|
||||||
|
"nodes": {
|
||||||
|
"testnode": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author": "@testyMcTersterson",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M30.999 31.005v-3h-6.762s.812-12.397 1.162-14 .597-3.35 2.628-3.103 1.971 3.103 1.971 3.103l4.862-.016s-.783-3.984-2.783-5.984-7.946-1.7-9.633.03c-1.687 1.73-2.302 5.065-2.597 6.422-.588 4.5-.854 9.027-1.248 13.547h-8.6v3H18.1s-.812 12.398-1.162 14-.597 3.35-2.628 3.103-1.972-3.102-1.972-3.102l-4.862.015s.783 3.985 2.783 5.985c2 2 7.946 1.699 9.634-.031 1.687-1.73 2.302-5.065 2.597-6.422.587-4.5.854-9.027 1.248-13.547z" fill="#fff"/></svg>
|
After Width: | Height: | Size: 539 B |
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from regular module main.js")
|
||||||
|
})()
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "regular_node",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A regular node that does nothing other than exist",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"author": "@testyMcTersterson",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
console.log("hello from @test/testnode index.html")
|
||||||
|
})()
|
||||||
|
</script>
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from @test/testnode index.js")
|
||||||
|
})()
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "@test/testnode",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A test node that does nothing other than exist",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node-red",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"node-red": {
|
||||||
|
"nodes": {
|
||||||
|
"testnode": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author": "@testyMcTersterson",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
console.log("hello from testnode2 index.js")
|
||||||
|
})()
|
||||||
|
</script>
|
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from testnode2 index.js")
|
||||||
|
})()
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "testnode2",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A test node that does nothing other than exist",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node-red",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"node-red": {
|
||||||
|
"nodes": {
|
||||||
|
"testnode2": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author": "@testyMcTersterson",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
(function() {
|
||||||
|
console.log("Hi from test plugin client side")
|
||||||
|
})()
|
@ -0,0 +1,14 @@
|
|||||||
|
module.exports = function (RED) {
|
||||||
|
RED.plugins.registerPlugin('test-theme', {
|
||||||
|
type: 'node-red-theme',
|
||||||
|
scripts: [
|
||||||
|
'files/clientside.js'
|
||||||
|
],
|
||||||
|
css: [
|
||||||
|
'files/theme.css',
|
||||||
|
],
|
||||||
|
monacoOptions: {
|
||||||
|
theme: "vs"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
:root{--red-ui-primary-background: #f2f3fb;}
|
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "test-theme2",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "test theme for Node-RED",
|
||||||
|
|
||||||
|
"keywords": [
|
||||||
|
"node-red",
|
||||||
|
"plugin",
|
||||||
|
"theme"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "testy-McTesterson"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"node-red": {
|
||||||
|
"version": ">=2.2.0",
|
||||||
|
"plugins": {
|
||||||
|
"test-theme2": "files/plugin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.x"
|
||||||
|
}
|
||||||
|
}
|
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
generated
vendored
Normal file
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
console.log("hello from @test/testnode index.html")
|
||||||
|
})()
|
||||||
|
</script>
|
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
generated
vendored
Normal file
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from @test/testnode index.js")
|
||||||
|
})()
|
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
generated
vendored
Normal file
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "@test/testnode",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A test node that does nothing other than exist",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node-red",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"node-red": {
|
||||||
|
"nodes": {
|
||||||
|
"testnode": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author": "@testyMcTersterson",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
3
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
generated
vendored
Normal file
3
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
(function() {
|
||||||
|
console.log("Hi from test plugin client side")
|
||||||
|
})()
|
14
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
generated
vendored
Normal file
14
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module.exports = function (RED) {
|
||||||
|
RED.plugins.registerPlugin('test-theme', {
|
||||||
|
type: 'node-red-theme',
|
||||||
|
scripts: [
|
||||||
|
'files/clientside.js'
|
||||||
|
],
|
||||||
|
css: [
|
||||||
|
'files/theme.css',
|
||||||
|
],
|
||||||
|
monacoOptions: {
|
||||||
|
theme: "vs"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
1
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
generated
vendored
Normal file
1
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
:root{--red-ui-primary-background: #f2f3fb;}
|
24
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
generated
vendored
Normal file
24
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "@test/test-theme3",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "test theme for Node-RED",
|
||||||
|
|
||||||
|
"keywords": [
|
||||||
|
"node-red",
|
||||||
|
"plugin",
|
||||||
|
"theme"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "testy-McTesterson"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"node-red": {
|
||||||
|
"version": ">=2.2.0",
|
||||||
|
"plugins": {
|
||||||
|
"test-theme3": "files/plugin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.x"
|
||||||
|
}
|
||||||
|
}
|
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
generated
vendored
Normal file
5
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
console.log("hello from testnode3 index.js")
|
||||||
|
})()
|
||||||
|
</script>
|
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
generated
vendored
Normal file
4
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
(function() {
|
||||||
|
console.log("hello from testnode3 index.js")
|
||||||
|
})()
|
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
generated
vendored
Normal file
20
test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "testnode3",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A test node that does nothing other than exist",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node-red",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"node-red": {
|
||||||
|
"nodes": {
|
||||||
|
"testnode3": "index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"author": "@testyMcTersterson",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
@ -388,6 +388,19 @@ describe("@node-red/util/util", function() {
|
|||||||
result[0].should.eql(1);
|
result[0].should.eql(1);
|
||||||
result[1].should.eql(2);
|
result[1].should.eql(2);
|
||||||
});
|
});
|
||||||
|
it('throws an error if buffer data is not array or string', function (done) {
|
||||||
|
try {
|
||||||
|
var result = util.evaluateNodeProperty('12','bin');
|
||||||
|
done("should throw an error");
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code === "INVALID_BUFFER_DATA") {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
done("should throw an error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
it('returns msg property',function() {
|
it('returns msg property',function() {
|
||||||
var result = util.evaluateNodeProperty('foo.bar','msg',{},{foo:{bar:"123"}});
|
var result = util.evaluateNodeProperty('foo.bar','msg',{},{foo:{bar:"123"}});
|
||||||
result.should.eql("123");
|
result.should.eql("123");
|
||||||
|
Loading…
Reference in New Issue
Block a user