Compare commits

..

70 Commits

Author SHA1 Message Date
Dave Conway-Jones
7518987083 Add subflows to context sidebar 2019-06-19 09:51:48 +01:00
Dave Conway-Jones
5a7592a953 Add name to node and flow context view labels
slight adjust spacing for context view
2019-06-18 21:14:14 +01:00
Nick O'Leary
60b1a05894 Fix styling of Debug pop-out window 2019-06-18 11:40:13 +01:00
Nick O'Leary
f955d63707 Merge branch 'disable-node' into dev 2019-06-18 11:33:20 +01:00
Nick O'Leary
f106019938 Add runtime test for disabled nodes 2019-06-18 11:02:31 +01:00
Nick O'Leary
2473249c8b Allow config nodes to be disabled, tidy css and add actions 2019-06-17 22:46:34 +01:00
Nick O'Leary
d13dc4fba3 Don't allow a link node virtual wire to connect to normal port 2019-06-17 15:37:45 +01:00
Nick O'Leary
41a0af032c Enable individual flow nodes to be disabled 2019-06-14 22:12:47 +01:00
Nick O'Leary
70cf7b0c5a Do not save subflow env vars with blank names 2019-06-14 11:18:07 +01:00
Nick O'Leary
14f6788ab9 Set autocomplete to disabled in form input elements 2019-06-14 11:17:49 +01:00
Nick O'Leary
bb67049d90 Ensure focus returns to the right element after dialogs shown 2019-06-14 10:57:12 +01:00
Nick O'Leary
ae2162beaf Handle subflow internal node wired to a non-existant node
Fixes #2202
2019-06-13 14:23:46 +01:00
Nick O'Leary
19f2c5e07f Merge branch 'master' into dev 2019-06-13 09:37:36 +01:00
Nick O'Leary
8abc5b3889 Add actions to change deploy type 2019-06-12 10:06:58 +01:00
Nick O'Leary
4d37c28bc7 Merge pull request #2197 from node-red/commandPrompt
Add Command prompt dialog
2019-06-11 22:47:30 +01:00
Nick O'Leary
cc0933eee4 Rename commandPrompt to actionList 2019-06-11 22:43:28 +01:00
Nick O'Leary
2de9a804a0 Tidy up nls of command prompt and selection handling 2019-06-11 22:43:28 +01:00
Nick O'Leary
ffeb2e91f4 Add command prompt dialog 2019-06-11 22:43:28 +01:00
Nick O'Leary
8cf5ec9e5a Update UI tests for new editor css 2019-06-11 17:12:31 +01:00
Nick O'Leary
ea0526f29a Add insertItemAt doc to editableList 2019-06-11 17:12:31 +01:00
Nick O'Leary
cfcb3a69e5 Merge pull request #2198 from node-red-hitachi/allow-env-in-switch-node
Allow environment variable as target of switch node
2019-06-11 15:13:46 +01:00
Nick O'Leary
e3e0378857 Add visual json editor 2019-06-11 14:44:44 +01:00
Nick O'Leary
ccc3809daa Make 'anything else' template more explicit 2019-06-09 17:32:14 +01:00
Nick O'Leary
c97786e12c Improve handling of file upload in request node
formData can only be Strings or Buffers - anything else will cause
errors. To help matters, we now look for invalid types and json-encode
them where needed.
2019-06-08 20:42:14 +01:00
Nick O'Leary
400071879f Add enable/disable-flow actions 2019-06-07 15:14:21 +01:00
Nick O'Leary
4cd6e20c91 Fix undo of flow disable state change 2019-06-07 15:13:49 +01:00
Nick O'Leary
460e3ad395 Fix select-all action in main view 2019-06-07 14:35:22 +01:00
Nick O'Leary
6f08bd6fc5 Fix delete-all action on config node sidebar 2019-06-07 14:35:10 +01:00
Nick O'Leary
eed3a749db Fix undefined error on typedInput due to valueLabel used before being added 2019-06-07 14:34:35 +01:00
Hiroyasu Nishiyama
6587d12fbd update info text 2019-06-07 21:39:12 +09:00
Hiroyasu Nishiyama
f8dd68ecc4 Add support for env var propety in switch node 2019-06-07 21:35:36 +09:00
Nick O'Leary
f0aef2b853 Add show-library dialog actions 2019-06-07 11:35:04 +01:00
Nick O'Leary
7d27df1b97 Add shift-cursor handling for moving quick-add dialog 2019-06-06 17:17:44 +01:00
Nick O'Leary
457ec86c25 Do not allow tab focus on clipboard hidden element 2019-06-06 17:17:05 +01:00
Nick O'Leary
a24c66958f Fix display of node help when clicking in palette
Fixes #2194
2019-06-06 14:38:21 +01:00
Nick O'Leary
617628b886 Ensure node help is loaded in the right language
Fixes #2195
2019-06-06 14:16:19 +01:00
Nick O'Leary
6b7e623d33 Remove some hardcoded css colors 2019-06-06 11:34:20 +01:00
Nick O'Leary
5ca85b7e83 Merge branch 'pr_2187' into dev 2019-06-04 22:58:18 +01:00
Nick O'Leary
5965bf3332 Merge pull request #2190 from node-red-hitachi/fix-typedinput-appearance
Fix typedinput width calculation
2019-06-04 20:56:30 +01:00
Nick O'Leary
baf2dd293b Merge pull request #2189 from bonanitech/patch-1
Update build-custom-theme.js
2019-06-04 16:50:36 +01:00
Dave Conway-Jones
2cc19e7e32 stop join tripping up if last message of buffer is blank. 2019-06-01 23:49:27 +01:00
Dave Conway-Jones
53ab6f8569 Add popovers to context sidebar mini buttons 2019-06-01 13:21:21 +01:00
Hiroyasu Nishiyama
cf8faac7ef fix width calculation of typedInput 2019-05-31 22:20:54 +09:00
Mauricio Bonani
86947a384d Update build-custom-theme.js 2019-05-31 08:33:22 -04:00
Dave Conway-Jones
22855279bd ensure input box has focus on repeated quick add 2019-05-30 14:33:11 +01:00
Paul Williams
e56fdecdc6 Add new shortcut to clear debug message list
Clearing the debug message list is globally scoped by default to
`ctrl+alt+l`. Mnemonic: similar to clearing a terminal shell using
ctrl+l.
2019-05-30 09:36:44 +00:00
Dave Conway-Jones
dc75a5812f Handle webscoket item being parseable but not an object better
and add test
2019-05-29 12:49:35 +01:00
Dave Conway-Jones
33e20c9969 Only add copypath popover if button exists. 2019-05-28 21:43:21 +01:00
Nick O'Leary
109204897f Fix clipboard export download button 2019-05-28 16:10:21 +01:00
Nick O'Leary
3b3a2d62f8 Merge pull request #2175 from node-red-hitachi/update-language-selector
update editor language selection UI for i18n
2019-05-28 13:26:38 +01:00
Nick O'Leary
b1b4b3fb63 Ensure tooltip popover doesn't replace normal popover 2019-05-28 13:25:03 +01:00
Nick O'Leary
d583c68de5 Fix error handling in Websocket broadcast function
Fixes #2182
2019-05-28 11:51:34 +01:00
Nick O'Leary
d360f30af6 Ensure library list has an item selected when opened 2019-05-28 11:23:03 +01:00
Nick O'Leary
ed033565a4 Handle empty list of example flows
Fixes #2171
2019-05-28 11:21:53 +01:00
Nick O'Leary
2d6acfae1b Restore tray component css for compatibility. Mark as deprecated 2019-05-28 09:50:29 +01:00
Hiroyasu Nishiyama
10da894124 fix function name & string compare function 2019-05-28 08:55:00 +09:00
Nick O'Leary
6dda8f21e4 Merge pull request #2176 from node-red-hitachi/update-editor-message-jp
Update Japanese message catalogue for editor
2019-05-27 22:18:18 +01:00
Nick O'Leary
1a9d759002 Merge pull request #2177 from node-red-hitachi/i18n-library-ui
Update I18n support for library ui
2019-05-27 22:18:00 +01:00
Nick O'Leary
df24e13eb5 Merge pull request #2178 from node-red-hitachi/update-nodes-message-jp
update Japanese message for nodes
2019-05-27 22:17:19 +01:00
Nick O'Leary
2ab19937af Fix pinned debug item css 2019-05-27 21:23:41 +01:00
Nick O'Leary
390b86cd8e Revert treeList children function signature change 2019-05-27 21:11:50 +01:00
Nick O'Leary
423aba5bab Ensure ndoe status icon is shown when value set 2019-05-27 21:07:27 +01:00
Dave Conway-Jones
dc0b9231cd Add popover tooltips to debug sidebar,function and template
path, value, pin buttons in debug
expand buttons in function and template.
2019-05-27 15:48:06 +01:00
Hiroyasu Nishiyama
3b177bedf8 update Japanese message for nodes 2019-05-27 14:25:03 +09:00
Hiroyasu Nishiyama
12ce719213 make new library folder interface i18n ready 2019-05-27 13:34:47 +09:00
Hiroyasu Nishiyama
320433b1bf update Japanese message catalogue 2019-05-27 13:13:25 +09:00
Hiroyasu Nishiyama
7f35e2280e update editor language selection UI for i18n 2019-05-27 11:28:36 +09:00
Nick O'Leary
c514d988df Revealing node position needs to account for zoom level
Fixes #2172
2019-05-25 22:11:05 +01:00
Nick O'Leary
749a080397 Fix typedInput option selection
Fixes #2174
2019-05-25 21:19:31 +01:00
Nick O'Leary
b105a12505 Fix palette node id handling so search works
Fixes #2173
2019-05-24 22:13:21 +01:00
66 changed files with 1943 additions and 442 deletions

View File

@@ -7,8 +7,11 @@ assignees: ''
---
Please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
Please DO NOT raise an issue.
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
We DO NOT use the issue tracker for general support or feature requests. Only bug reports should be raised here using the 'Bug report' template.
For general support, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack). You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
That way the whole Node-RED user community can help, rather than rely on the core development team.
For feature requests, please use the Node-RED Forum](https://discourse.nodered.org). Many ideas have already been discussed there and you should search that for your request before starting a new discussion.

View File

@@ -169,6 +169,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/notifications.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/search.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",

View File

@@ -351,7 +351,8 @@
"pasteNode": "Paste nodes",
"undoChange": "Undo the last change performed",
"searchBox": "Open search box",
"managePalette": "Manage palette"
"managePalette": "Manage palette",
"actionList":"Action list"
},
"library": {
"library": "Library",
@@ -365,6 +366,7 @@
"savedNodes": "Saved nodes",
"savedType": "Saved __type__",
"saveFailed": "Save failed: __message__",
"newFolder": "New folder",
"types": {
"local": "Local",
"examples": "Examples"
@@ -527,10 +529,13 @@
"refresh": "refresh to load",
"empty": "empty",
"node": "Node",
"subflow": "Subflow",
"flow": "Flow",
"global": "Global",
"deleteConfirm": "Are you sure you want to delete this item?",
"autoRefresh": "Auto-refresh"
"autoRefresh": "Auto-refresh",
"refrsh": "Refresh",
"delete": "Delete"
},
"palette": {
"name": "Palette management",
@@ -736,7 +741,16 @@
},
"jsonEditor": {
"title": "JSON editor",
"format": "format JSON"
"format": "format JSON",
"rawMode": "Edit JSON",
"uiMode": "Visual editor",
"insertAbove": "Insert above",
"insertBelow": "Insert below",
"addItem": "Add item",
"copyPath": "Copy path to item",
"expandItems": "Expand items",
"collapseItems": "Collapse items",
"duplicate": "Duplicate"
},
"markdownEditor": {
"title": "Markdown editor",
@@ -929,5 +943,12 @@
"description": "Description",
"appearance": "Appearance",
"env": "Environment Variables"
},
"languages" : {
"de": "German",
"en-US": "English",
"ja": "Japanese",
"ko": "Korean",
"zh-CN": "Chinese(Simplified)"
}
}

View File

@@ -28,7 +28,8 @@
"status": "状態",
"enabled": "有効",
"disabled": "無効",
"info": "詳細"
"info": "詳細",
"selectNodes": "ノードをクリックして選択"
},
"menu": {
"label": {
@@ -42,7 +43,9 @@
"defaultDir": "標準",
"ltr": "左から右",
"rtl": "右から左",
"auto": "文脈"
"auto": "文脈",
"language": "表示言語",
"browserDefault": "ブラウザのデフォルト"
},
"sidebar": {
"show": "サイドバーを表示"
@@ -179,7 +182,11 @@
"all": "全てのタブ",
"compact": "インデントのないJSONフォーマット",
"formatted": "インデント付きのJSONフォーマット",
"copy": "書き出し"
"copy": "書き出し",
"export": "ライブラリに書き出し",
"exportAs": "書き出し先",
"overwrite": "更新",
"exists": "<p><b>\"__file__\"</b>は既に存在します。</p><p>更新しますか?</p>"
},
"import": {
"import": "読み込み先",
@@ -315,7 +322,8 @@
"show": "表示",
"hide": "非表示",
"errors": {
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします"
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします",
"invalidProperties": "プロパティが不正です:"
}
},
"keyboard": {
@@ -351,12 +359,15 @@
"saveToLibrary": "ライブラリへ保存",
"typeLibrary": "__type__ ライブラリ",
"unnamedType": "名前なし __type__",
"exportedToLibrary": "ライブラリにノードを書き出しました",
"dialogSaveOverwrite": "__libraryName__ という __libraryType__ は既に存在しています 上書きしますか?",
"invalidFilename": "不正なファイル名",
"savedNodes": "フローを保存しました",
"savedType": "__type__ を保存しました",
"saveFailed": "保存に失敗しました: __message__",
"newFolder": "新規フォルダ",
"types": {
"local": "ローカル",
"examples": "サンプル"
}
},
@@ -519,7 +530,8 @@
"node": "Node",
"flow": "Flow",
"global": "Global",
"deleteConfirm": "データを削除しても良いですか?"
"deleteConfirm": "データを削除しても良いですか?",
"autoRefresh": "自動更新"
},
"palette": {
"name": "パレットの管理",
@@ -719,6 +731,9 @@
"jsEditor": {
"title": "JavaScriptエディタ"
},
"textEditor": {
"title": "テキストエディタ"
},
"jsonEditor": {
"title": "JSONエディタ",
"format": "JSONフォーマット"
@@ -914,5 +929,12 @@
"description": "説明",
"appearance": "外観",
"env": "環境変数"
},
"languages" : {
"de": "ドイツ語",
"en-US": "英語",
"ja": "日本語",
"ko": "韓国語",
"zh-CN": "中国語(簡体)"
}
}

View File

@@ -214,6 +214,10 @@ RED.history = (function() {
ev.node[i] = ev.changes[i];
}
}
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) {
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!ev.node.disabled);
}
if (ev.subflow) {
if (ev.subflow.hasOwnProperty('inputCount')) {
if (ev.node.in.length > ev.subflow.inputCount) {

View File

@@ -51,7 +51,7 @@ RED.i18n = (function() {
},
loadNodeCatalog: function(namespace,done) {
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length;
languageList.forEach(function(lang) {
$.ajax({
@@ -73,7 +73,7 @@ RED.i18n = (function() {
},
loadNodeCatalogs: function(done) {
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length;
languageList.forEach(function(lang) {

View File

@@ -1,6 +1,6 @@
{
"*": {
"ctrl-shift-p":"core:manage-palette",
"alt-shift-p":"core:manage-palette",
"ctrl-f": "core:search",
"ctrl-shift-f": "core:list-flows",
"ctrl-=": "core:zoom-in",
@@ -17,11 +17,13 @@
"ctrl-space": "core:toggle-sidebar",
"ctrl-p": "core:toggle-palette",
"ctrl-,": "core:show-user-settings",
"ctrl-alt-l": "core:clear-debug-messages",
"ctrl-alt-r": "core:show-remote-diff",
"ctrl-alt-n": "core:new-project",
"ctrl-alt-o": "core:open-project",
"ctrl-g v": "core:show-version-control-tab",
"ctrl-shift-l": "core:show-event-log"
"ctrl-shift-l": "core:show-event-log",
"ctrl-shift-p":"core:show-action-list"
},
"red-ui-sidebar-node-config": {
"backspace": "core:delete-config-selection",

View File

@@ -463,7 +463,9 @@ RED.nodes = (function() {
node.id = n.id;
node.type = n.type;
node.z = n.z;
if (n.d === true) {
node.d = true;
}
if (node.type == "unknown") {
for (var p in n._orig) {
if (n._orig.hasOwnProperty(p)) {
@@ -967,6 +969,9 @@ RED.nodes = (function() {
users:[],
_config:{}
};
if (n.hasOwnProperty('d')) {
configNode.d = n.d;
}
for (d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d];
@@ -1016,6 +1021,9 @@ RED.nodes = (function() {
if (n.hasOwnProperty('l')) {
node.l = n.l;
}
if (n.hasOwnProperty('d')) {
node.d = n.d;
}
if (createNewIds) {
if (subflow_blacklist[n.z]) {
continue;

View File

@@ -107,9 +107,12 @@ var RED = (function() {
}
function loadNodes() {
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html"
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes',
@@ -448,6 +451,7 @@ var RED = (function() {
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
{id:"menu-item-event-log",label:RED._("eventLog.title"),onselect:"core:show-event-log"},
{id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"},
null
]});
menuOptions.push(null);
@@ -518,6 +522,7 @@ var RED = (function() {
RED.subflow.init();
RED.clipboard.init();
RED.search.init();
RED.actionList.init();
RED.editor.init();
RED.diff.init();

View File

@@ -0,0 +1,211 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.actionList = (function() {
var disabled = false;
var dialog = null;
var searchInput;
var searchResults;
var selected = -1;
var visible = false;
var filterTerm = "";
var previousActiveElement;
function ensureSelectedIsVisible() {
var selectedEntry = searchResults.find("li.selected");
if (selectedEntry.length === 1) {
var scrollWindow = searchResults.parent();
var scrollHeight = scrollWindow.height();
var scrollOffset = scrollWindow.scrollTop();
var y = selectedEntry.position().top;
var h = selectedEntry.height();
if (y+h > scrollHeight) {
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
} else if (y<0) {
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
}
}
}
function createDialog() {
dialog = $("<div>",{id:"red-ui-actionList",class:"red-ui-search"}).appendTo("#red-ui-main-container");
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
searchInput = $('<input type="text" data-i18n="[placeholder]keyboard.filterActions">').appendTo(searchDiv).searchBox({
change: function() {
filterTerm = $(this).val();
searchResults.editableList('filter');
searchResults.find("li.selected").removeClass("selected");
}
});
searchInput.on('keydown',function(evt) {
var selectedChild;
if (evt.keyCode === 40) {
// Down
selectedChild = searchResults.find("li.selected");
if (!selectedChild.length) {
var children = searchResults.children(":visible");
if (children.length) {
$(children[0]).addClass('selected');
RED.a = children[0];
}
} else {
var nextChild = selectedChild.nextAll(":visible").first();
if (nextChild.length) {
selectedChild.removeClass('selected');
nextChild.addClass('selected');
}
}
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 38) {
// Up
selectedChild = searchResults.find("li.selected");
var nextChild = selectedChild.prevAll(":visible").first();
if (nextChild.length) {
selectedChild.removeClass('selected');
nextChild.addClass('selected');
}
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 13) {
// Enter
selectedChild = searchResults.find("li.selected");
selectCommand(searchResults.editableList('getItem',selectedChild));
}
});
searchInput.i18n();
var searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
searchResults = $('<ol>',{style:"position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;"}).appendTo(searchResultsDiv).editableList({
addButton: false,
addItem: function(container,i,action) {
if (action.id === undefined) {
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
} else {
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
var contentDiv = $('<div>',{class:"red-ui-search-result-action"}).appendTo(div);
$('<div>').text(action.label).appendTo(contentDiv);
// $('<div>',{class:"red-ui-search-result-node-type"}).text(node.type).appendTo(contentDiv);
// $('<div>',{class:"red-ui-search-result-node-id"}).text(node.id).appendTo(contentDiv);
if (action.key) {
$('<div>',{class:"red-ui-search-result-action-key"}).html(RED.keyboard.formatKey(action.key)).appendTo(contentDiv);
}
div.on("click", function(evt) {
evt.preventDefault();
selectCommand(action);
});
}
},
scrollOnAdd: false,
filter: function(item) {
if (filterTerm !== "" && item.label.toLowerCase().indexOf(filterTerm) === -1) {
return false;
}
return true;
}
});
}
function selectCommand(command) {
hide();
if (command) {
RED.actions.invoke(command.id);
}
}
function show(v) {
if (disabled) {
return;
}
if (!visible) {
previousActiveElement = document.activeElement;
RED.keyboard.add("*","escape",function(){hide()});
$("#red-ui-header-shade").show();
$("#red-ui-editor-shade").show();
$("#red-ui-palette-shade").show();
$("#red-ui-sidebar-shade").show();
$("#red-ui-sidebar-separator").hide();
if (dialog === null) {
createDialog();
}
dialog.slideDown(300);
searchInput.searchBox('value',v)
searchResults.editableList('empty');
results = [];
var actions = RED.actions.list();
actions.sort(function(A,B) {
return A.id.localeCompare(B.id);
});
actions.forEach(function(action) {
action.label = action.id.replace(/:/,": ").replace(/-/g," ").replace(/(^| )./g,function() { return arguments[0].toUpperCase()});
searchResults.editableList('addItem',action)
})
RED.events.emit("actionList:open");
visible = true;
}
searchInput.trigger("focus");
}
function hide() {
if (visible) {
RED.keyboard.remove("escape");
visible = false;
$("#red-ui-header-shade").hide();
$("#red-ui-editor-shade").hide();
$("#red-ui-palette-shade").hide();
$("#red-ui-sidebar-shade").hide();
$("#red-ui-sidebar-separator").show();
if (dialog !== null) {
dialog.slideUp(200,function() {
searchInput.searchBox('value','');
});
}
RED.events.emit("actionList:close");
if (previousActiveElement) {
$(previousActiveElement).trigger("focus");
previousActiveElement = null;
}
}
}
function init() {
RED.actions.add("core:show-action-list",show);
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("search:open",function() { disabled = true; });
RED.events.on("search:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });
$("#red-ui-header-shade").on('mousedown',hide);
$("#red-ui-editor-shade").on('mousedown',hide);
$("#red-ui-palette-shade").on('mousedown',hide);
$("#red-ui-sidebar-shade").on('mousedown',hide);
}
return {
init: init,
show: show,
hide: hide
};
})();

View File

@@ -59,7 +59,7 @@ RED.clipboard = (function() {
element.setAttribute('download', "flows.json");
element.style.display = 'none';
document.body.appendChild(element);
element.trigger("click");
element.click();
document.body.removeChild(element);
$( this ).dialog( "close" );
}
@@ -396,14 +396,6 @@ RED.clipboard = (function() {
label: RED._("library.types.examples")
});
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
if (mode === 'clipboard') {
setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100)
}
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable");
@@ -475,6 +467,14 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
})
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
if (mode === 'clipboard') {
setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100)
}
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
popover = RED.popover.create({
target: $("#red-ui-clipboard-dialog-import-text"),
@@ -521,8 +521,6 @@ RED.clipboard = (function() {
label: RED._("library.library")
});
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable");
@@ -638,6 +636,7 @@ RED.clipboard = (function() {
} else {
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click");
}
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
$("#red-ui-clipboard-dialog-export-text").trigger("focus");
@@ -655,7 +654,7 @@ RED.clipboard = (function() {
// icon: 'fa fa-hdd-o',
// label: RED._("library.types.examples"),
// path: "",
// children: function(item,done) {
// children: function(done,item) {
// RED.library.loadLibraryFolder("_examples_","flows","",function(children) {
// item.children = children;
// done(children);
@@ -670,13 +669,14 @@ RED.clipboard = (function() {
label: label,
path: "",
expanded: true,
children: function(item,done) {
children: function(done, item) {
RED.library.loadLibraryFolder(library,"flows","",function(children) {
item.children = children;
done(children);
})
}
}]);
}], true);
}
function hideDropTarget() {
@@ -730,17 +730,20 @@ RED.clipboard = (function() {
init: function() {
setupDialogs();
$('<input type="text" id="red-ui-clipboard-hidden">').appendTo("#red-ui-editor");
$('<input type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
RED.actions.add("core:show-export-dialog",exportNodes);
RED.actions.add("core:show-import-dialog",importNodes);
RED.actions.add("core:library-export",function() { exportNodes('library') });
RED.actions.add("core:show-library-export-dialog",function() { exportNodes('library') });
RED.actions.add("core:show-library-import-dialog",function() { importNodes('library') });
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("search:open",function() { disabled = true; });
RED.events.on("search:close",function() { disabled = false; });
RED.events.on("actionList:open",function() { disabled = true; });
RED.events.on("actionList:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });

View File

@@ -32,6 +32,7 @@
* - scrollOnAdd : boolean - whether to scroll to newly added items
* methods:
* - addItem(itemData)
* - insertItemAt : function(data,index) - add an item at the specified index
* - removeItem(itemData)
* - width(width)
* - height(height)
@@ -185,6 +186,7 @@
}
},
_destroy: function() {
this.topContainer.remove();
},
_refreshFilter: function() {
var that = this;
@@ -230,7 +232,7 @@
this.uiHeight = desiredHeight;
this._resize();
},
addItem: function(data) {
insertItemAt: function(data,index) {
var that = this;
data = data || {};
var li = $('<li>');
@@ -248,7 +250,13 @@
});
}
if (!added) {
li.appendTo(this.element);
if (index <= 0) {
li.prependTo(this.element);
} else if (index > that.element.children().length-1) {
li.appendTo(this.element);
} else {
li.insertBefore(this.element.children().eq(index));
}
}
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
row.data('data',data);
@@ -293,6 +301,9 @@
},0);
}
},
addItem: function(data) {
this.insertItemAt(data,this.element.children().length)
},
addItems: function(items) {
for (var i=0; i<items.length;i++) {
this.addItem(items[i]);
@@ -312,6 +323,7 @@
},
empty: function() {
this.element.empty();
this.uiContainer.scrollTop(0);
},
filter: function(filter) {
if (filter !== undefined) {
@@ -335,6 +347,14 @@
if (items.length > 0) {
this.uiContainer.scrollTop(this.uiContainer.scrollTop()+items.position().top)
}
},
getItem: function(li) {
var el = li.find(".red-ui-editableList-item-content");
if (el.length) {
return el.data('data');
} else {
return null;
}
}
});
})(jQuery);

View File

@@ -98,21 +98,10 @@ RED.menu = (function() {
return;
}
if (opt.toggle) {
var selected = isSelected(opt.id);
if (typeof opt.toggle === "string") {
if (!selected) {
for (var m in menuItems) {
if (menuItems.hasOwnProperty(m)) {
var mi = menuItems[m];
if (mi.id != opt.id && opt.toggle == mi.toggle) {
setSelected(mi.id,false);
}
}
}
setSelected(opt.id,true);
}
if (opt.toggle === true) {
setSelected(opt.id, !isSelected(opt.id));
} else {
setSelected(opt.id, !selected);
setSelected(opt.id, true);
}
} else {
triggerAction(opt.id);
@@ -209,8 +198,9 @@ RED.menu = (function() {
}
function setSelected(id,state) {
var alreadySet = false;
if (isSelected(id) == state) {
return;
alreadySet = true;
}
var opt = menuItems[id];
if (state) {
@@ -218,10 +208,26 @@ RED.menu = (function() {
} else {
$("#"+id).removeClass("active");
}
if (opt && opt.onselect) {
triggerAction(opt.id,state);
if (opt) {
if (opt.toggle && typeof opt.toggle === "string") {
if (state) {
for (var m in menuItems) {
if (menuItems.hasOwnProperty(m)) {
var mi = menuItems[m];
if (mi.id != opt.id && opt.toggle == mi.toggle) {
setSelected(mi.id,false);
}
}
}
}
}
if (!alreadySet && opt.onselect) {
triggerAction(opt.id,state);
}
}
if (!alreadySet) {
RED.settings.set(opt.setting||("menu-"+opt.id), state);
}
RED.settings.set(opt.setting||("menu-"+opt.id), state);
}
function toggleSelected(id) {

View File

@@ -52,6 +52,11 @@ RED.popover = (function() {
var openPopup = function(instant) {
if (active) {
var existingPopover = target.data("red-ui-popover");
if (options.tooltip && existingPopover) {
active = false;
return;
}
div = $('<div class="red-ui-popover"></div>');
if (size !== "default") {
div.addClass("red-ui-popover-size-"+size);
@@ -122,7 +127,10 @@ RED.popover = (function() {
}
}
div.addClass('red-ui-popover-'+d).css({top: top, left: left});
if (existingPopover) {
existingPopover.close(true);
}
target.data("red-ui-popover",res)
if (instant) {
div.show();
} else {
@@ -142,6 +150,7 @@ RED.popover = (function() {
});
}
div = null;
target.removeData("red-ui-popover",res)
}
}
}
@@ -236,6 +245,7 @@ RED.popover = (function() {
}
}
return RED.popover.create({
tooltip: true,
target:target,
trigger: "hover",
size: "small",

View File

@@ -87,6 +87,7 @@
that._trigger("change");
},this.options.delay);
} else {
this.lastSent = this.element.val();
this._trigger("change");
}
}

View File

@@ -42,12 +42,11 @@
var enabledLabel = this.options.enabledLabel || RED._("editor:workspace.enabled");
var disabledLabel = this.options.disabledLabel || RED._("editor:workspace.disabled");
this.element.addClass("red-ui-toggleButton");
this.element.css("display","none");
this.element.on("focus", function() {
that.button.focus();
});
this.button = $('<button type="button" class="'+baseClass+' toggle single"><i class="fa"></i> <span></span></button>');
this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"><i class="fa"></i> <span></span></button>');
if (this.options.class) {
this.button.addClass(this.options.class)
}

View File

@@ -20,6 +20,10 @@
* - data : array - initial items to display in tree
* - multi : boolean - if true, .selected will return an array of results
* otherwise, returns the first selected item
* - sortable: boolean/string - TODO: see editableList
* - rootSortable: boolean - if 'sortable' is set, then setting this to
* false, prevents items being sorted to the
* top level of the tree
*
* methods:
* - data(items) - clears existing items and replaces with new data
@@ -27,25 +31,57 @@
* events:
* - treelistselect : function(event, item) {}
* - treelistconfirm : function(event,item) {}
* - treelistchangeparent: function(event,item, oldParent, newParent) {}
*
* data:
* [
* {
* label: 'Local', // label for the item
* sublabel: 'Local', // a sub-label for the item
* icon: 'fa fa-rocket', // (optional) icon for the item
* selected: true/false, // (optional) if present, display checkbox accordingly
* children: [] | function(item,done) // (optional) an array of child items, or a function
* children: [] | function(done,item) // (optional) an array of child items, or a function
* // that will call the `done` callback with an array
* // of child items
* expanded: true/false, // show the child items by default
* deferBuild: true/false, // don't build any ui elements for the item's children
* until it is expanded by the user.
* element: // custom dom element to use for the item - ignored if `label` is set
* }
* ]
*
*
*
* var treeList = $("<div>").css({width: "100%", height: "100%"}).treeList({data:[...]})
* treeList.on('treelistselect', function(e,item) { console.log(item)})
* treeList.treeList('data',[ ... ] )
*
*
* After `data` has been added to the tree, each item is augmented the following
* properties and functions:
*
* item.parent - set to the parent item
* item.treeList.container
* item.treeList.label - the label element for the item
* item.treeList.depth - the depth in the tree (0 == root)
* item.treeList.parentList - the editableList instance this item is in
* item.treeList.remove() - removes the item from the tree
* item.treeList.makeLeaf(detachChildElements) - turns an element with children into a leaf node,
* removing the UI decoration etc.
* detachChildElements - any children with custom
* elements will be detached rather than removed
* so jQuery event handlers are preserved in case
* the child elements need to be reattached later
* item.treeList.makeParent(children) - turns an element into a parent node, adding the necessary
* UI decoration.
* item.treeList.insertChildAt(newItem,position,select) - adds a child item an the specified position.
* Optionally selects the item after adding.
* item.treeList.addChild(newItem,select) - appends a child item.
* Optionally selects the item after adding.
* item.treeList.expand(done) - expands the parent item to show children. Optional 'done' callback.
* item.treeList.collapse() - collapse the parent item to hide children.
*
*
*
*
*/
$.widget( "nodered.treeList", {
@@ -116,20 +152,30 @@
});
this._data = [];
this._topList = $('<ol>').css({
this._topList = $('<ol class="red-ui-treeList-list">').css({
position:'absolute',
top: 0,
left:0,
right:0,
bottom:0
}).appendTo(wrapper).editableList({
}).appendTo(wrapper);
var topListOptions = {
addButton: false,
scrollOnAdd: false,
height: '100%',
addItem: function(container,i,item) {
that._addSubtree(that._topList,container,item,0);
}
})
};
if (this.options.rootSortable !== false && !!this.options.sortable) {
topListOptions.sortable = this.options.sortable;
topListOptions.connectWith = '.red-ui-treeList-sortable';
this._topList.addClass('red-ui-treeList-sortable');
}
this._topList.editableList(topListOptions)
if (this.options.data) {
this.data(this.options.data);
}
@@ -171,23 +217,82 @@
},
_addChildren: function(container,parent,children,depth) {
var that = this;
var subtree = $('<ol>').appendTo(container).editableList({
var subtree = $('<ol class="red-ui-treeList-list">').appendTo(container).editableList({
connectWith: ".red-ui-treeList-sortable",
sortable: that.options.sortable,
addButton: false,
scrollOnAdd: false,
height: 'auto',
addItem: function(container,i,item) {
that._addSubtree(subtree,container,item,depth+1);
},
sortItems: function(data) {
var children = [];
var reparented = [];
data.each(function() {
var child = $(this).data('data');
children.push(child);
var evt = that._fixDepths(parent,child);
if (evt) {
reparented.push(evt);
}
})
if (Array.isArray(parent.children)) {
parent.children = children;
}
reparented.forEach(function(evt) {
that._trigger("changeparent",null,evt);
});
that._trigger("sort",null,parent);
}
});
if (!!that.options.sortable) {
subtree.addClass('red-ui-treeList-sortable');
}
for (var i=0;i<children.length;i++) {
children[i].parent = parent;
subtree.editableList('addItem',children[i])
}
return subtree;
},
_fixDepths: function(parent,child) {
// If child has just been moved into parent in the UI
// this will fix up the internal data structures to match.
// The calling function must take care of getting child
// into the parent.children array. The rest is up to us.
var that = this;
var reparentedEvent = null;
if (child.parent !== parent) {
reparented = true;
var oldParent = child.parent;
child.parent = parent;
reparentedEvent = {
item: child,
old: oldParent,
}
}
if (child.depth !== parent.depth+1) {
child.depth = parent.depth+1;
var labelPaddingWidth = ((child.gutter?child.gutter.width()+2:0)+(child.depth*20));
child.treeList.labelPadding.width(labelPaddingWidth+'px');
if (child.element) {
$(child.element).css({
width: "calc(100% - "+(labelPaddingWidth+20+(child.icon?20:0))+"px)"
})
}
// This corrects all child item depths
if (child.children && Array.isArray(child.children)) {
child.children.forEach(function(item) {
that._fixDepths(child,item);
})
}
}
return reparentedEvent;
},
_addSubtree: function(parentList, container, item, depth) {
var that = this;
item.treeList = {};
item.treeList.depth = depth;
item.treeList.container = container;
item.treeList.parentList = parentList;
@@ -196,87 +301,80 @@
if (item.parent) {
var index = item.parent.children.indexOf(item);
item.parent.children.splice(index,1)
that._trigger("sort",null,item.parent);
}
}
var labelNodeType = "<div>";
// if (item.children && item.hasOwnProperty('selected')) {
// labelNodeType = "<div>";
// }
var label = $(labelNodeType,{class:"red-ui-treeList-label"}).appendTo(container);
var label = $("<div>",{class:"red-ui-treeList-label"}).appendTo(container);
item.treeList.label = label;
if (item.class) {
label.addClass(item.class);
}
label.css({
paddingLeft: (depth*15)+'px'
})
if (item.gutter) {
item.gutter.css({
position: 'absolute'
}).appendTo(label)
}
var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
item.treeList.labelPadding = $('<span>').css({
display: "inline-block",
width: labelPaddingWidth+'px'
}).appendTo(label);
label.on('mouseover',function(e) { that._trigger('itemmouseover',e,item); })
label.on('mouseout',function(e) { that._trigger('itemmouseout',e,item); })
label.on('mouseenter',function(e) { that._trigger('itemmouseenter',e,item); })
label.on('mouseleave',function(e) { that._trigger('itemmouseleave',e,item); })
if (item.children) {
item.treeList.addChild = function(newItem,select) {
item.treeList.childList.editableList('addItem',newItem)
newItem.parent = item;
item.children.push(newItem);
if (select) {
setTimeout(function() {
that.select(newItem)
},100);
}
item.treeList.makeLeaf = function(detachChildElements) {
if (!treeListIcon.children().length) {
// Already a leaf
return
}
item.treeList.expand = function(done) {
if (container.hasClass("expanded")) {
done && done();
return;
}
if (!container.hasClass("built") && typeof item.children === 'function') {
container.addClass('built');
var childrenAdded = false;
var spinner;
var startTime = 0;
item.children(item,function(children) {
childrenAdded = true;
item.treeList.childList = that._addChildren(container,item,children,depth).hide();
var delta = Date.now() - startTime;
if (delta < 400) {
setTimeout(function() {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
}
},400-delta);
} else {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
if (detachChildElements && item.children) {
var detachChildren = function(item) {
if (item.children) {
item.children.forEach(function(child) {
if (child.element) {
child.element.detach();
}
}
done && done();
that._trigger("childrenloaded",null,item)
});
if (!childrenAdded) {
startTime = Date.now();
spinner = $('<div class="red-ui-treeList-spinner">').css({
"background-position": (35+depth*15)+'px 50%'
}).appendTo(container);
if (child.gutter) {
child.gutter.detach();
}
detachChildren(child);
});
}
} else {
item.treeList.childList.slideDown('fast');
done && done();
}
container.addClass("expanded");
detachChildren(item);
}
item.treeList.collapse = function() {
item.treeList.childList.slideUp('fast');
container.removeClass("expanded");
treeListIcon.empty();
if (!item.deferBuild) {
item.treeList.childList.remove();
delete item.treeList.childList;
}
$('<span class="red-ui-treeList-icon"><i class="fa fa-angle-right" /></span>').appendTo(label);
label.off("click.red-ui-treeList-expand");
treeListIcon.off("click.red-ui-treeList-expand");
delete item.children;
container.removeClass("expanded");
}
item.treeList.makeParent = function(children) {
if (treeListIcon.children().length) {
// Already a parent because we've got the angle-right icon
return;
}
$('<i class="fa fa-angle-right" />').appendTo(treeListIcon);
treeListIcon.on("click.red-ui-treeList-expand", function(e) {
e.stopPropagation();
e.preventDefault();
if (container.hasClass("expanded")) {
item.treeList.collapse();
} else {
item.treeList.expand();
}
});
// $('<span class="red-ui-treeList-icon"><i class="fa fa-folder-o" /></span>').appendTo(label);
label.on("click", function(e) {
label.on("click.red-ui-treeList-expand", function(e) {
if (container.hasClass("expanded")) {
if (item.hasOwnProperty('selected') || label.hasClass("selected")) {
item.treeList.collapse();
@@ -285,9 +383,97 @@
item.treeList.expand();
}
})
} else {
$('<span class="red-ui-treeList-icon"></span>').appendTo(label);
if (!item.children) {
item.children = children||[];
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
}
}
item.treeList.insertChildAt = function(newItem,position,select) {
newItem.parent = item;
item.children.splice(position,0,newItem);
if (!item.deferBuild) {
item.treeList.childList.editableList('insertItemAt',newItem,position)
if (select) {
setTimeout(function() {
that.select(newItem)
},100);
}
that._trigger("sort",null,item);
}
}
item.treeList.addChild = function(newItem,select) {
item.treeList.insertChildAt(newItem,item.children.length,select);
}
item.treeList.expand = function(done) {
if (!item.children) {
return;
}
if (container.hasClass("expanded")) {
done && done();
return;
}
if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) {
container.addClass('built');
var childrenAdded = false;
var spinner;
var startTime = 0;
var completeBuild = function(children) {
childrenAdded = true;
item.treeList.childList = that._addChildren(container,item,children,depth).hide();
var delta = Date.now() - startTime;
if (delta < 400) {
setTimeout(function() {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
}
},400-delta);
} else {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
}
}
done && done();
that._trigger("childrenloaded",null,item)
}
if (typeof item.children === 'function') {
item.children(completeBuild,item);
} else {
delete item.deferBuild;
completeBuild(item.children);
}
if (!childrenAdded) {
startTime = Date.now();
spinner = $('<div class="red-ui-treeList-spinner">').css({
"background-position": (35+depth*20)+'px 50%'
}).appendTo(container);
}
} else {
if (that._loadingData) {
item.treeList.childList.show();
} else {
item.treeList.childList.slideDown('fast');
}
done && done();
}
container.addClass("expanded");
}
item.treeList.collapse = function() {
if (!item.children) {
return;
}
item.treeList.childList.slideUp('fast');
container.removeClass("expanded");
}
var treeListIcon = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
if (item.children) {
item.treeList.makeParent();
}
if (item.hasOwnProperty('selected')) {
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
var cb = $('<input class="red-ui-treeList-checkbox" type="checkbox">').prop('checked',item.selected).appendTo(selectWrapper);
@@ -326,19 +512,22 @@
if (item.icon) {
$('<span class="red-ui-treeList-icon"><i class="'+item.icon+'" /></span>').appendTo(label);
}
if (item.label || item.sublabel) {
if (item.label) {
if (item.hasOwnProperty('label') || item.hasOwnProperty('sublabel')) {
if (item.hasOwnProperty('label')) {
$('<span class="red-ui-treeList-label-text"></span>').text(item.label).appendTo(label);
}
if (item.sublabel) {
if (item.hasOwnProperty('sublabel')) {
$('<span class="red-ui-treeList-sublabel-text"></span>').text(item.sublabel).appendTo(label);
}
} else if (item.element) {
$(item.element).appendTo(label);
$(item.element).css({
width: "calc(100% - "+(labelPaddingWidth+20+(item.icon?20:0))+"px)"
})
}
if (item.children) {
if (Array.isArray(item.children)) {
if (Array.isArray(item.children) && !item.deferBuild) {
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
}
if (item.expanded) {
@@ -350,12 +539,17 @@
this._topList.editableList('empty');
},
data: function(items) {
var that = this;
if (items !== undefined) {
this._data = items;
this._topList.editableList('empty');
this._loadingData = true;
for (var i=0; i<items.length;i++) {
this._topList.editableList('addItem',items[i]);
}
setTimeout(function() {
delete that._loadingData;
},200);
this._trigger("select")
} else {
@@ -384,7 +578,11 @@
})
return res;
}
return s.parent().data('data');
if (s.length) {
return s.parent().data('data');
} else {
return undefined;
}
}
});

View File

@@ -209,7 +209,7 @@
that.input.css("margin"+d,0);
});
["type","placeholder"].forEach(function(d) {
["type","placeholder","autocomplete"].forEach(function(d) {
var m = that.element.attr(d);
that.input.attr(d,m);
});
@@ -225,6 +225,8 @@
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
this.valueLabelContainer = $('<div class="red-ui-typedInput-value-label">').appendTo(this.uiSelect)
this.types(this.options.types);
if (this.options.typeField) {
@@ -247,9 +249,15 @@
that.validate();
that.element.val(that.value());
that.element.trigger('change',that.propertyType,that.value());
});
this.input.on('keydown', function(evt) {
if (evt.keyCode >= 37 && evt.keyCode <= 40) {
evt.stopPropagation();
}
})
this.selectTrigger.on("click", function(event) {
event.preventDefault();
event.stopPropagation();
that._showTypeMenu();
});
this.selectTrigger.on('keydown',function(evt) {
@@ -257,12 +265,11 @@
// Down
that._showTypeMenu();
}
evt.stopPropagation();
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
})
this.valueLabelContainer = $('<div class="red-ui-typedInput-value-label">').appendTo(this.uiSelect)
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
@@ -271,12 +278,14 @@
});
this.optionSelectTrigger.on("click", function(event) {
event.preventDefault();
event.stopPropagation();
that._showOptionSelectMenu();
}).on('keydown', function(evt) {
if (evt.keyCode === 40) {
// Down
that._showOptionSelectMenu();
}
evt.stopPropagation();
}).on('blur', function() {
that.uiSelect.removeClass('red-ui-typedInput-focus');
}).on('focus', function() {
@@ -357,6 +366,7 @@
op.on("click", function(event) {
event.preventDefault();
event.stopPropagation();
callback(opt.value);
that._hideMenu(menu);
});
@@ -376,9 +386,11 @@
// UP
$(this).children(":focus").prev().trigger("focus");
} else if (evt.keyCode === 27) {
// ESCAPE
evt.preventDefault();
that._hideMenu(menu);
}
evt.stopPropagation();
})
@@ -426,6 +438,7 @@
if (labelWidth === 0) {
var container = $('<div class="red-ui-typedInput-container"></div>').css({
position:"absolute",
"white-space": "nowrap",
top:0
}).appendTo(document.body);
var newTrigger = label.clone().appendTo(container);
@@ -515,6 +528,7 @@
this.optionMenu.remove();
}
this.menu.remove();
this.uiSelect.remove();
},
types: function(types) {
var that = this;
@@ -573,6 +587,7 @@
if (!selectedOption) {
selectedOption = {value:""}
}
this.input.val(value);
this._updateOptionSelectLabel(selectedOption)
} else {
this.input.val(value);

View File

@@ -99,7 +99,13 @@ RED.deploy = (function() {
});
RED.actions.add("core:deploy-flows",save);
RED.actions.add("core:restart-flows",restart);
if (type === "default") {
RED.actions.add("core:restart-flows",restart);
RED.actions.add("core:set-deploy-type-to-full",function() { RED.menu.setSelected("deploymenu-item-full",true);});
RED.actions.add("core:set-deploy-type-to-modified-flows",function() { RED.menu.setSelected("deploymenu-item-flow",true); });
RED.actions.add("core:set-deploy-type-to-modified-nodes",function() { RED.menu.setSelected("deploymenu-item-node",true); });
}
RED.events.on('nodes:change',function(state) {

View File

@@ -567,13 +567,13 @@ RED.editor = (function() {
type: "text",
style: "margin-left: 5px; width: calc(40% - 8px)",
placeholder: RED._("common.label.name")
}).appendTo(row).val(opt.name);
}).attr("autocomplete","disable").appendTo(row).val(opt.name);
}
var valueField = $('<input/>',{
class: "node-input-env-value",
type: "text",
style: "margin-left: 5px; width: calc(60% - 8px)"
}).appendTo(row)
}).attr("autocomplete","disable").appendTo(row)
valueField.typedInput({default:'str',
types:['str','num','bool','json','bin','env']
@@ -667,17 +667,19 @@ RED.editor = (function() {
list.each(function(i) {
var entry = $(this);
var item = entry.data('data');
var name = item.parent?item.name:entry.find(".node-input-env-name").val();
var valueInput = entry.find(".node-input-env-value");
var value = valueInput.typedInput("value");
var type = valueInput.typedInput("type");
if (!item.parent || (item.parent.value !== value || item.parent.type !== type)) {
var item = {
name: name,
type: type,
value: value
};
env.push(item);
var name = (item.parent?item.name:entry.find(".node-input-env-name").val()).trim();
if (name !== "") {
var valueInput = entry.find(".node-input-env-value");
var value = valueInput.typedInput("value");
var type = valueInput.typedInput("type");
if (!item.parent || (item.parent.value !== value || item.parent.type !== type)) {
var item = {
name: name,
type: type,
value: value
};
env.push(item);
}
}
});
return env;
@@ -721,6 +723,7 @@ RED.editor = (function() {
$('<input type="password" style="display: none;" />').prependTo(dialogForm);
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
dialogForm.find('input').attr("autocomplete","disable");
return dialogForm;
}
@@ -952,34 +955,19 @@ RED.editor = (function() {
$('<div class="form-row">'+
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
'<button type="button" id="node-input-show-label-btn" class="red-ui-button" style="min-width: 80px; text-align: left;" type="button"><i id="node-input-show-label-btn-i" class="fa fa-toggle-on"></i> <span id="node-input-show-label-label"></span></button> '+
'<input type="checkbox" id="node-input-show-label" style="display: none;"/>'+
'<input type="checkbox" id="node-input-show-label"/>'+
'</div>').appendTo(dialogForm);
var setToggleState = function(state) {
var i = $("#node-input-show-label-btn-i");
if (!state) {
i.addClass('fa-toggle-off');
i.removeClass('fa-toggle-on');
$("#node-input-show-label").prop("checked",false);
$("#node-input-show-label-label").text(RED._("editor.hide"));
} else {
i.addClass('fa-toggle-on');
i.removeClass('fa-toggle-off');
$("#node-input-show-label").prop("checked",true);
$("#node-input-show-label-label").text(RED._("editor.show"));
}
}
dialogForm.find('#node-input-show-label-btn').on("click",function(e) {
e.preventDefault();
var i = $("#node-input-show-label-btn-i");
setToggleState(i.hasClass('fa-toggle-off'));
$("#node-input-show-label").toggleButton({
enabledLabel: RED._("editor.show"),
disabledLabel: RED._("editor.hide")
})
if (!node.hasOwnProperty("l")) {
// Show label if type not link
node.l = !/^link (in|out)$/.test(node._def.type);
}
setToggleState(node.l);
$("#node-input-show-label").prop("checked",node.l).trigger("change");
// If a node has icon property in defaults, the icon of the node cannot be modified. (e.g, ui_button node in dashboard)
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
@@ -1393,6 +1381,20 @@ RED.editor = (function() {
node.l = true;
}
}
if ($("#node-input-node-disabled").prop('checked')) {
if (node.d !== true) {
changes.d = node.d;
changed = true;
node.d = true;
}
} else {
if (node.d === true) {
changes.d = node.d;
changed = true;
delete node.d;
}
}
node.resize = true;
var oldInfo = node.info;
@@ -1495,6 +1497,14 @@ RED.editor = (function() {
var trayBody = tray.find('.red-ui-tray-body');
trayBody.parent().css('overflow','hidden');
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
$('<input id="node-input-node-disabled" type="checkbox">').prop("checked",!!node.d).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
var editorTabEl = $('<ul></ul>').appendTo(trayBody);
var editorContent = $('<div></div>').appendTo(trayBody);
@@ -1672,9 +1682,17 @@ RED.editor = (function() {
var trayHeader = tray.find(".red-ui-tray-header");
var trayBody = tray.find('.red-ui-tray-body');
var trayFooter = tray.find(".red-ui-tray-footer");
var userCountDiv;
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
$('<input id="node-config-input-node-disabled" type="checkbox">').prop("checked",!!editing_config_node.d).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
if (node_def.hasUsers !== false) {
userCountDiv = $('<div class="red-ui-tray-footer-left"><i class="fa fa-info-circle"></i> <span></span></div>').prependTo(trayFooter);
$('<span><i class="fa fa-info-circle"></i> <span id="red-ui-editor-config-user-count"></span></span>').css("margin-left", "10px").appendTo(trayFooterLeft);
}
trayFooter.append('<span class="red-ui-tray-footer-right"><span id="red-ui-editor-config-scope-warning" data-i18n="[title]editor.errors.scopeChange"><i class="fa fa-warning"></i></span><select id="red-ui-editor-config-scope"></select></span>');
@@ -1768,8 +1786,8 @@ RED.editor = (function() {
}
});
}
if (node_def.hasUsers !== false && userCountDiv) {
userCountDiv.find("span").text(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
if (node_def.hasUsers !== false) {
$("#red-ui-editor-config-user-count").text(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
}
trayBody.i18n();
trayFooter.i18n();
@@ -1904,6 +1922,16 @@ RED.editor = (function() {
editing_config_node.label = configTypeDef.label;
editing_config_node.z = scope;
if ($("#node-config-input-node-disabled").prop('checked')) {
if (editing_config_node.d !== true) {
editing_config_node.d = true;
}
} else {
if (editing_config_node.d === true) {
delete editing_config_node.d;
}
}
if (scope) {
// Search for nodes that use this one that are no longer
// in scope, so must be removed
@@ -2058,7 +2086,7 @@ RED.editor = (function() {
RED.nodes.eachConfig(function(config) {
if (config.type == type && (!config.z || config.z === activeWorkspace.id)) {
var label = RED.utils.getNodeLabel(config,config.id);
config.__label__ = label;
config.__label__ = label+(config.d?" ["+RED._("workspace.disabled")+"]":"");
configNodes.push(config);
}
});

View File

@@ -16,7 +16,419 @@
(function() {
var template = '<script type="text/x-red" data-template-name="_json"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button></div><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div></div></script>';
// var template = '<script type="text/x-red" data-template-name="_json"></script>';
var template = '<script type="text/x-red" data-template-name="_json">'+
'<ul id="red-ui-editor-type-json-tabs"></ul>'+
'<div id="red-ui-editor-type-json-tab-raw" class="red-ui-editor-type-json-tab-content hide">'+
'<div class="form-row" style="margin-bottom: 3px; text-align: right;">'+
'<button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button>'+
'</div>'+
'<div class="form-row node-text-editor-row">'+
'<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>'+
'</div>'+
'</div>'+
'<div id="red-ui-editor-type-json-tab-ui" class="red-ui-editor-type-json-tab-content hide">'+
'<div id="red-ui-editor-type-json-tab-ui-container"></div>'+
'</div>'+
'</script>';
var activeTab;
function insertNewItem(parent,index,copyIndex) {
var newValue = "";
if (parent.children.length > 0) {
switch (parent.children[Math.max(0,Math.min(parent.children.length-1,copyIndex))].type) {
case 'string': newValue = ""; break;
case 'number': newValue = 0; break;
case 'boolean': newValue = true; break;
case 'null': newValue = null; break;
case 'object': newValue = {}; break;
case 'array': newValue = []; break;
}
}
var newKey;
if (parent.type === 'array') {
newKey = parent.children.length;
} else {
var usedKeys = {};
parent.children.forEach(function(child) { usedKeys[child.key] = true })
var keyRoot = "item";
var keySuffix = 2;
newKey = keyRoot;
while(usedKeys[newKey]) {
newKey = keyRoot+"-"+(keySuffix++);
}
}
var newItem = handleItem(newKey,newValue,parent.depth+1,parent);
parent.treeList.insertChildAt(newItem, index, true);
parent.treeList.expand();
}
function showObjectMenu(button,item) {
var elementPos = button.offset();
var options = [];
if (item.parent) {
options.push({id:"red-ui-editor-type-json-menu-insert-above", icon:"fa fa-toggle-up", label:RED._('jsonEditor.insertAbove'),onselect:function(){
var index = item.parent.children.indexOf(item);
insertNewItem(item.parent,index,index);
}});
options.push({id:"red-ui-editor-type-json-menu-insert-below", icon:"fa fa-toggle-down", label:RED._('jsonEditor.insertBelow'),onselect:function(){
var index = item.parent.children.indexOf(item)+1;
insertNewItem(item.parent,index,index-1);
}});
}
if (item.type === 'array' || item.type === 'object') {
options.push({id:"red-ui-editor-type-json-menu-add-child", icon:"fa fa-plus", label:RED._('jsonEditor.addItem'),onselect:function(){
insertNewItem(item,item.children.length,item.children.length-1);
}});
}
if (item.parent) {
options.push({id:"red-ui-editor-type-json-menu-copy-path", icon:"fa fa-terminal", label:RED._('jsonEditor.copyPath'),onselect:function(){
var i = item;
var path = "";
var newPath;
while(i.parent) {
if (i.parent.type === "array") {
newPath = "["+i.key+"]";
} else {
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(i.key)) {
newPath = i.key;
} else {
newPath = "[\""+i.key.replace(/"/,"\\\"")+"\"]"
}
}
path = newPath+(path.length>0 && path[0] !== "["?".":"")+path;
i = i.parent;
}
RED.clipboard.copyText(path,item.element,"clipboard.copyMessagePath");
}});
options.push({id:"red-ui-editor-type-json-menu-duplicate", icon:"fa fa-copy", label:RED._("jsonEditor.duplicate"),onselect:function(){
var newKey = item.key;
if (item.parent.type === 'array') {
newKey = parent.children.length;
} else {
var m = /^(.*?)(-(\d+))?$/.exec(newKey);
var usedKeys = {};
item.parent.children.forEach(function(child) { usedKeys[child.key] = true })
var keyRoot = m[1];
var keySuffix = 2;
if (m[3] !== undefined) {
keySuffix = parseInt(m[3]);
}
newKey = keyRoot;
while(usedKeys[newKey]) {
newKey = keyRoot+"-"+(keySuffix++);
}
}
var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent);
var index = item.parent.children.indexOf(item)+1;
item.parent.treeList.insertChildAt(newItem, index, true);
item.parent.treeList.expand();
}});
options.push({id:"red-ui-editor-type-json-menu-delete", icon:"fa fa-times", label:RED._('common.label.delete'),onselect:function(){
item.treeList.remove();
}});
}
if (item.type === 'array' || item.type === 'object') {
options.push(null)
options.push({id:"red-ui-editor-type-json-menu-expand-children",icon:"fa fa-angle-double-down", label:RED._('jsonEditor.expandItems'),onselect:function(){
item.treeList.expand();
item.children.forEach(function(child) {
child.treeList.expand();
})
}});
options.push({id:"red-ui-editor-type-json-menu-collapse-children",icon:"fa fa-angle-double-up", label:RED._('jsonEditor.collapseItems'),onselect:function(){
item.children.forEach(function(child) {
child.treeList.collapse();
})
}});
}
var menuOptionMenu = RED.menu.init({
id:"red-ui-editor-type-json-menu",
options: options
});
menuOptionMenu.css({
position: "absolute"
})
menuOptionMenu.on('mouseleave', function(){ $(this).hide() });
menuOptionMenu.on('mouseup', function() { $(this).hide() });
menuOptionMenu.appendTo("body");
var top = elementPos.top;
var height = menuOptionMenu.height();
var winHeight = $(window).height();
if (top+height > winHeight) {
top -= (top+height)-winHeight + 20;
}
menuOptionMenu.css({
top: top+"px",
left: elementPos.left+"px"
})
menuOptionMenu.show();
}
function parseObject(obj,depth,parent) {
var result = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
result.push(handleItem(prop,obj[prop],depth,parent));
}
}
return result;
}
function parseArray(obj,depth,parent) {
var result = [];
var l = obj.length;
for (var i=0;i<l;i++) {
result.push(handleItem(i,obj[i],depth,parent));
}
return result;
}
function handleItem(key,val,depth,parent) {
var item = {depth:depth, type: typeof val};
var container = $('<span class="red-ui-editor-type-json-editor-label">');
if (key != null) {
item.key = key;
var keyText;
if (typeof key === 'string') {
keyText = '"'+key+'"';
} else {
keyText = key;
}
var keyLabel = $('<span class="red-ui-debug-msg-object-key red-ui-editor-type-json-editor-label-key">').text(keyText).appendTo(container);
keyLabel.addClass('red-ui-debug-msg-type-'+(typeof key));
if (parent && parent.type === "array") {
keyLabel.addClass("red-ui-editor-type-json-editor-label-array-key")
}
keyLabel.on("click", function(evt) {
if (item.parent.type === 'array') {
return;
}
evt.preventDefault();
evt.stopPropagation();
var w = Math.max(150,keyLabel.width());
var keyInput = $('<input type="text" class="red-ui-editor-type-json-editor-key">').css({width:w+"px"}).val(""+item.key).insertAfter(keyLabel).typedInput({types:['str']});
$(document).on("mousedown.nr-ui-json-editor", function(evt) {
var typedInputElement = keyInput.next(".red-ui-typedInput-container")[0];
var target = evt.target;
while (target.nodeName !== 'BODY' && target !== typedInputElement && !$(target).hasClass("red-ui-typedInput-options")) {
target = target.parentElement;
}
if (target.nodeName === 'BODY') {
var newKey = keyInput.typedInput("value");
item.key = newKey;
var keyText;
if (typeof newKey === 'string') {
keyText = '"'+newKey+'"';
} else {
keyText = newKey;
}
keyLabel.text(keyText);
keyInput.remove();
keyLabel.show();
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
});
$(document).on("keydown.nr-ui-json-editor",function(evt) {
if (evt.keyCode === 27) {
// Escape
keyInput.remove();
keyLabel.show();
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
});
keyLabel.hide();
});
$('<span>').text(" : ").appendTo(container);
}
if (Array.isArray(val)) {
item.expanded = depth < 2;
item.type = "array";
item.deferBuild = depth >= 2;
item.children = parseArray(val,depth+1,item);
} else if (val !== null && item.type === "object") {
item.expanded = depth < 2;
item.children = parseObject(val,depth+1,item);
item.deferBuild = depth >= 2;
} else {
item.value = val;
if (val === null) {
item.type = 'null'
}
}
var valType;
var valValue = "";
var valClass;
switch(item.type) {
case 'string': valType = 'str'; valValue = '"'+item.value+'"'; valClass = "red-ui-debug-msg-type-string"; break;
case 'number': valType = 'num'; valValue = item.value; valClass = "red-ui-debug-msg-type-number";break;
case 'boolean': valType = 'bool'; valValue = item.value; valClass = "red-ui-debug-msg-type-other";break;
case 'null': valType = item.type; valValue = item.type; valClass = "red-ui-debug-msg-type-null";break;
case 'object':
valType = item.type;
valValue = item.type;//+"{"+item.children.length+"}";
valClass = "red-ui-debug-msg-type-meta";
break;
case 'array':
valType = item.type;
valValue = item.type+"["+item.children.length+"]";
valClass = "red-ui-debug-msg-type-meta";
break;
}
//
var orphanedChildren;
var valueLabel = $('<span class="red-ui-editor-type-json-editor-label-value">').addClass(valClass).text(valValue).appendTo(container);
valueLabel.on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
if (valType === 'str') {
valValue = valValue.substring(1,valValue.length-1);
} else if (valType === 'array') {
valValue = "";
} else if (valType === 'object') {
valValue = "";
}
var w = Math.max(150,valueLabel.width());
var val = $('<input type="text" class="red-ui-editor-type-json-editor-value">').css({width:w+"px"}).val(""+valValue).insertAfter(valueLabel).typedInput({
types:[
'str','num','bool',
{value:"null",label:"null",hasValue:false},
{value:"array",label:"array",hasValue:false},
{value:"object",label:"object",hasValue:false}
],
default: valType
});
$(document).on("mousedown.nr-ui-json-editor", function(evt) {
var typedInputElement = val.next(".red-ui-typedInput-container")[0];
var target = evt.target;
while (target.nodeName !== 'BODY' && target !== typedInputElement && !$(target).hasClass("red-ui-typedInput-options")) {
target = target.parentElement;
}
if (target.nodeName === 'BODY') {
valType = val.typedInput("type");
valValue = val.typedInput("value");
if (valType === 'num') {
valValue = valValue.trim();
if (isNaN(valValue)) {
valType = 'str';
} else if (valValue === "") {
valValue = 0;
}
}
item.value = valValue;
var valClass;
switch(valType) {
case 'str': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "string"; valClass = "red-ui-debug-msg-type-string"; valValue = '"'+valValue+'"'; break;
case 'num': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; break;
case 'bool': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "boolean"; valClass = "red-ui-debug-msg-type-other"; item.value = (valValue === "true"); break;
case 'null': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "null"; valClass = "red-ui-debug-msg-type-null"; item.value = valValue = "null"; break;
case 'object':
item.treeList.makeParent(orphanedChildren);
item.type = "object";
valClass = "red-ui-debug-msg-type-meta";
item.value = valValue = "object";
item.children.forEach(function(child,i) {
if (child.hasOwnProperty('_key')) {
child.key = child._key;
delete child._key;
var keyText;
var keyLabel = child.element.find(".red-ui-editor-type-json-editor-label-key");
keyLabel.removeClass("red-ui-editor-type-json-editor-label-array-key");
if (typeof child.key === 'string') {
keyText = '"'+child.key+'"';
keyLabel.addClass('red-ui-debug-msg-type-string');
keyLabel.removeClass('red-ui-debug-msg-type-number');
} else {
keyText = child.key;
keyLabel.removeClass('red-ui-debug-msg-type-string');
keyLabel.addClass('red-ui-debug-msg-type-number');
}
keyLabel.text(keyText);
}
})
break;
case 'array':
item.treeList.makeParent(orphanedChildren);
item.type = "array";
valClass = "red-ui-debug-msg-type-meta";
item.value = valValue = "array["+(item.children.length)+"]";
item.children.forEach(function(child,i) {
child._key = child.key;
child.key = i;
child.element.find(".red-ui-editor-type-json-editor-label-key")
.addClass("red-ui-editor-type-json-editor-label-array-key")
.text(""+child.key)
.removeClass('red-ui-debug-msg-type-string')
.addClass('red-ui-debug-msg-type-number');
})
break;
}
valueLabel.text(valValue).removeClass().addClass("red-ui-editor-type-json-editor-label-value "+valClass);
val.remove();
valueLabel.show();
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
})
$(document).on("keydown.nr-ui-json-editor",function(evt) {
if (evt.keyCode === 27) {
// Escape
val.remove();
valueLabel.show();
if (valType === 'str') {
valValue = '"'+valValue+'"';
}
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
});
valueLabel.hide();
})
item.gutter = $('<span class="red-ui-editor-type-json-editor-item-gutter"></span>');
if (parent) {//red-ui-editor-type-json-editor-item-handle
$('<span class="red-ui-editor-type-json-editor-item-handle"><i class="fa fa-bars"></span>').appendTo(item.gutter);
} else {
$('<span></span>').appendTo(item.gutter);
}
$('<button type="button" class="editor-button editor-button-small"><i class="fa fa-caret-down"></button>').appendTo(item.gutter).on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
showObjectMenu($(this), item);
});
item.element = container;
return item;
}
function convertToObject(item) {
var element;
switch (item.type) {
case 'string': element = item.value; break;
case 'number': element = Number(item.value); break;
case 'boolean': element = item.value; break;
case 'null': element = null; break;
case 'object':
element = {};
item.children.forEach(function(child) {
element[child.key] = convertToObject(child);
})
break;
case 'array':
element = item.children.map(function(child) {
return convertToObject(child);
})
break;
}
return element;
}
var definition = {
show: function(options) {
@@ -41,9 +453,11 @@
return false;
}
}
var rootNode;
var trayOptions = {
title: options.title,
width: "inherit",
width: options.width||700,
buttons: [
{
id: "node-dialog-cancel",
@@ -60,25 +474,60 @@
if (options.requireValid && !checkValid()) {
return;
}
onComplete(expressionEditor.getValue());
var result;
if (activeTab === "json-ui") {
if (rootNode) {
result = JSON.stringify(convertToObject(rootNode),null,4);
} else {
result = expressionEditor.getValue();
}
} else if (activeTab === "json-raw") {
result = expressionEditor.getValue();
}
onComplete && onComplete(result);
RED.tray.close();
}
}
],
resize: function(dimensions) {
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height();
for (var i=0;i<rows.size();i++) {
height -= $(rows[i]).outerHeight(true);
}
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
var height = $(".red-ui-editor-type-json-tab-content").height();
$(".node-text-editor").css("height",(height-45)+"px");
expressionEditor.resize();
},
open: function(tray) {
var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
var container = $("#red-ui-editor-type-json-tab-ui-container").css({"height":"100%"});
var filterDepth = Infinity;
var list = $('<div class="red-ui-debug-msg-payload red-ui-editor-type-json-editor">').appendTo(container).treeList({
rootSortable: false,
sortable: ".red-ui-editor-type-json-editor-item-handle",
}).on("treelistchangeparent", function(event, evt) {
if (evt.old.type === 'array') {
evt.old.element.find(".red-ui-editor-type-json-editor-label-type").text("array["+evt.old.children.length+"]");
}
if (evt.item.parent.type === 'array') {
evt.item.parent.element.find(".red-ui-editor-type-json-editor-label-type").text("array["+evt.item.parent.children.length+"]");
}
}).on("treelistsort", function(event, item) {
item.children.forEach(function(child,i) {
if (item.type === 'array') {
child.key = i;
child.element.find(".red-ui-editor-type-json-editor-label-key")
.text(child.key)
.removeClass('red-ui-debug-msg-type-string')
.addClass('red-ui-debug-msg-type-number');
} else {
child.element.find(".red-ui-editor-type-json-editor-label-key")
.text('"'+child.key+'"')
.removeClass('red-ui-debug-msg-type-number')
.addClass('red-ui-debug-msg-type-string');
}
})
});
expressionEditor = RED.editor.createEditor({
id: 'node-input-json',
value: "",
@@ -103,9 +552,56 @@
expressionEditor.getSession().setValue(v||"",-1);
});
dialogForm.i18n();
var finishedBuild = false;
var tabs = RED.tabs.create({
element: $("#red-ui-editor-type-json-tabs"),
onchange:function(tab) {
activeTab = tab.id;
$(".red-ui-editor-type-json-tab-content").hide();
if (finishedBuild) {
if (tab.id === "json-raw") {
if (rootNode) {
var result = JSON.stringify(convertToObject(rootNode),null,4);
expressionEditor.getSession().setValue(result||"",-1);
}
} else if (tab.id === "json-ui") {
var raw = expressionEditor.getValue().trim() ||"{}";
try {
var parsed = JSON.parse(raw);
rootNode = handleItem(null,parsed,0,null);
rootNode.class = "red-ui-editor-type-json-root-node"
list.treeList('data',[rootNode]);
} catch(err) {
rootNode = null;
list.treeList('data',[{
label: "Invalid JSON: "+err.toString()
}]);
}
}
}
tab.content.show();
trayOptions.resize();
}
})
tabs.addTab({
id: 'json-raw',
label: RED._('jsonEditor.rawMode'),
content: $("#red-ui-editor-type-json-tab-raw")
});
tabs.addTab({
id: 'json-ui',
label: RED._('jsonEditor.uiMode'),
content: $("#red-ui-editor-type-json-tab-ui")
});
finishedBuild = true;
},
close: function() {
expressionEditor.destroy();
// expressionEditor.destroy();
if (options.onclose) {
options.onclose();
}

View File

@@ -19,7 +19,7 @@ RED.keyboard = (function() {
var handlers = {};
var partialState;
RED.h = handlers;
var keyMap = {
"left":37,
"up":38,

View File

@@ -133,7 +133,7 @@ RED.library = (function() {
icon: 'fa fa-folder',
label: d,
path: root+d+"/",
children: function(item,done) {
children: function(done, item) {
loadLibraryFolder(library,type,root+d+"/", function(children) {
item.children = children; // TODO: should this be done by treeList for us
done(children);
@@ -325,7 +325,7 @@ RED.library = (function() {
var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu",
options: [
{id:"red-ui-library-browser-menu-addFolder",label:"New folder", onselect: function() {
{id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
var defaultFolderName = "new-folder";
var defaultFolderNameMatches = {};
@@ -431,11 +431,13 @@ RED.library = (function() {
focus: function() {
dirList.focus();
},
data: function(content) {
data: function(content,selectFirst) {
dirList.treeList('data',content);
// setTimeout(function() {
// dirList.treeList('select',content[0]);
// },100);
if (selectFirst) {
setTimeout(function() {
dirList.treeList('select',content[0]);
},100);
}
}
}
}

View File

@@ -149,13 +149,11 @@ RED.palette = (function() {
RED.utils.createIconElement(icon_url, iconContainer, true);
}
function escapeNodeType(nt) {
return nt.replace(" ","_").replace(".","_").replace(":","_");
function getPaletteNode(type) {
return $(".red-ui-palette-node[data-palette-type='"+type+"']");
}
function addNodeType(nt,def) {
var nodeTypeId = escapeNodeType(nt);
if ($("#red-ui-palette-node_"+nodeTypeId).length) {
if (getPaletteNode(nt).length) {
return;
}
if (exclusion.indexOf(def.category)===-1) {
@@ -164,9 +162,7 @@ RED.palette = (function() {
var category = def.category.replace(/ /g,"_");
var rootCategory = category.split("-")[0];
var d = document.createElement("div");
d.id = "red-ui-palette-node_"+nodeTypeId;
d.type = nt;
var d = $('<div>',{class:"red-ui-palette-node"}).attr("data-palette-type",nt).data('category',rootCategory);
var label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1];
if (typeof def.paletteLabel !== "undefined") {
@@ -182,7 +178,6 @@ RED.palette = (function() {
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
}).appendTo(d);
d.className="red-ui-palette-node";
if (def.icon) {
var icon_url = RED.utils.getNodeIcon(def);
@@ -193,36 +188,35 @@ RED.palette = (function() {
RED.utils.createIconElement(icon_url, iconContainer, true);
}
d.style.backgroundColor = RED.utils.getNodeColor(nt,def);
d.css("backgroundColor", RED.utils.getNodeColor(nt,def));
if (def.outputs > 0) {
var portOut = document.createElement("div");
portOut.className = "red-ui-palette-port red-ui-palette-port-output";
d.appendChild(portOut);
d.append(portOut);
}
if (def.inputs > 0) {
var portIn = document.createElement("div");
portIn.className = "red-ui-palette-port red-ui-palette-port-input";
d.appendChild(portIn);
d.append(portIn);
}
createCategory(def.category,rootCategory,category,(coreCategories.indexOf(rootCategory) !== -1)?"node-red":def.set.id);
$("#red-ui-palette-"+category).append(d);
$(d).data('category',rootCategory);
d.onmousedown = function(e) { e.preventDefault(); };
d.on("mousedown", function(e) { e.preventDefault();});
var popover = RED.popover.create({
target:$(d),
target:d,
trigger: "hover",
width: "300px",
content: "hi",
delay: { show: 750, hide: 50 }
});
$(d).data('popover',popover);
d.data('popover',popover);
// $(d).popover({
// title:d.type,
@@ -232,14 +226,17 @@ RED.palette = (function() {
// html: true,
// container:'body'
// });
$(d).on("click", function() {
d.on("click", function() {
RED.view.focus();
var helpText;
if (nt.indexOf("subflow:") === 0) {
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
} else {
helpText = $("script[data-help-name='"+d.type+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
}
// Don't look too closely. RED.sidebar.info.set will set the 'Description'
// section of the sidebar. Pass in the title of the Help section so it looks
// right.
RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp"));
});
var chart = $("#red-ui-workspace-chart");
@@ -330,13 +327,13 @@ RED.palette = (function() {
var nodeInfo = null;
if (nt.indexOf("subflow:") === 0) {
$(d).on("dblclick", function(e) {
d.on("dblclick", function(e) {
RED.workspaces.show(nt.substring(8));
e.preventDefault();
});
nodeInfo = marked(def.info||"");
}
setLabel(nt,$(d),label,nodeInfo);
setLabel(nt,d,label,nodeInfo);
var categoryNode = $("#red-ui-palette-container-"+rootCategory);
if (categoryNode.find(".red-ui-palette-node").length === 1) {
@@ -347,8 +344,7 @@ RED.palette = (function() {
}
function removeNodeType(nt) {
var nodeTypeId = escapeNodeType(nt);
var paletteNode = $("#red-ui-palette-node_"+nodeTypeId);
var paletteNode = getPaletteNode(nt);
var categoryNode = paletteNode.closest(".red-ui-palette-category");
paletteNode.remove();
if (categoryNode.find(".red-ui-palette-node").length === 0) {
@@ -360,8 +356,7 @@ RED.palette = (function() {
}
function hideNodeType(nt) {
var nodeTypeId = escapeNodeType(nt);
var paletteNode = $("#red-ui-palette-node_"+nodeTypeId);
var paletteNode = getPaletteNode(nt);
paletteNode.hide();
var categoryNode = paletteNode.closest(".red-ui-palette-category");
var cl = categoryNode.find(".red-ui-palette-node");
@@ -373,8 +368,7 @@ RED.palette = (function() {
}
function showNodeType(nt) {
var nodeTypeId = escapeNodeType(nt);
var paletteNode = $("#red-ui-palette-node_"+nodeTypeId);
var paletteNode = getPaletteNode(nt);
var categoryNode = paletteNode.closest(".red-ui-palette-category");
categoryNode.show();
paletteNode.show();
@@ -382,7 +376,7 @@ RED.palette = (function() {
function refreshNodeTypes() {
RED.nodes.eachSubflow(function(sf) {
var paletteNode = $("#red-ui-palette-node_subflow_"+sf.id.replace(".","_"));
var paletteNode = getPaletteNode('subflow:'+sf.id);
var portInput = paletteNode.find(".red-ui-palette-port-input");
var portOutput = paletteNode.find(".red-ui-palette-port-output");
@@ -396,7 +390,6 @@ RED.palette = (function() {
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : "")
);
if (portInput.length === 0 && sf.in.length > 0) {
var portIn = document.createElement("div");
portIn.className = "red-ui-palette-port red-ui-palette-port-input";
@@ -446,7 +439,8 @@ RED.palette = (function() {
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
$("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) {
var currentLabel = $(el).find(".red-ui-palette-label").text();
if (val === "" || re.test(el.id) || re.test(currentLabel)) {
var type = $(el).attr("data-palette-type");
if (val === "" || re.test(type) || re.test(currentLabel)) {
$(this).show();
} else {
$(this).hide();
@@ -459,8 +453,10 @@ RED.palette = (function() {
.find(".red-ui-palette-node")
.filter(function() { return $(this).css('display') !== 'none'}).length === 0) {
categoryContainers[category].close();
categoryContainers[category].container.slideUp();
} else {
categoryContainers[category].open();
categoryContainers[category].container.show();
}
}
}
@@ -539,9 +535,6 @@ RED.palette = (function() {
sidebarControls.hide();
})
var categoryList = coreCategories;
if (RED.settings.paletteCategories) {
categoryList = RED.settings.paletteCategories;

View File

@@ -25,6 +25,7 @@ RED.search = (function() {
var index = {};
var keys = [];
var results = [];
var previousActiveElement;
function indexProperty(node,label,property) {
@@ -216,7 +217,7 @@ RED.search = (function() {
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
var contentDiv = $('<div>',{class:"red-ui-search-result-node-description"}).appendTo(div);
if (node.z) {
var workspace = RED.nodes.workspace(node.z);
if (!workspace) {
@@ -253,6 +254,7 @@ RED.search = (function() {
return;
}
if (!visible) {
previousActiveElement = document.activeElement;
RED.keyboard.add("*","escape",function(){hide()});
$("#red-ui-header-shade").show();
$("#red-ui-editor-shade").show();
@@ -286,6 +288,10 @@ RED.search = (function() {
});
}
RED.events.emit("search:close");
if (previousActiveElement) {
$(previousActiveElement).trigger("focus");
previousActiveElement = null;
}
}
}
@@ -296,6 +302,8 @@ RED.search = (function() {
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });
RED.events.on("actionList:open",function() { disabled = true; });
RED.events.on("actionList:close",function() { disabled = false; });

View File

@@ -145,7 +145,12 @@ RED.sidebar.config = (function() {
var entry = $('<li class="red-ui-palette-node_id_'+node.id.replace(/\./g,"-")+'"></li>').appendTo(list);
var nodeDiv = $('<div class="red-ui-palette-node-config red-ui-palette-node"></div>').appendTo(entry);
entry.data('node',node.id);
$('<div class="red-ui-palette-label"></div>').text(label).appendTo(nodeDiv);
var label = $('<div class="red-ui-palette-label"></div>').text(label).appendTo(nodeDiv);
if (node.d) {
nodeDiv.addClass("red-ui-palette-node-config-disabled");
$('<i class="fa fa-ban"></i>').prependTo(label);
}
if (node._def.hasUsers !== false) {
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container red-ui-palette-icon-container-right"}).appendTo(nodeDiv);
if (node.users.length === 0) {
@@ -257,7 +262,7 @@ RED.sidebar.config = (function() {
RED.actions.add("core:delete-config-selection", function() {
var selectedNodes = [];
$(content).find(".red-ui-palette-node.selected").each(function() {
selectedNodes.push($(this).data('node'));
selectedNodes.push($(this).parent().data('node'));
});
if (selectedNodes.length > 0) {
var historyEvent = {

View File

@@ -14,28 +14,21 @@
* limitations under the License.
**/
RED.sidebar.context = (function() {
var content;
var sections;
var localCache = {};
var flowAutoRefresh;
var nodeSection;
// var subflowSection;
var flowSection;
var globalSection;
var currentNode;
var currentFlow;
function init() {
content = $("<div>").css({"position":"relative","height":"100%"});
content.className = "red-ui-sidebar-context"
var header = $('<div class="red-ui-sidebar-header"></div>').appendTo(content);
var autoUpdate = RED.settings.get("editor.context.refresh",false);
flowAutoRefresh = $('<input type="checkbox">').prop("checked",autoUpdate).appendTo(header).toggleButton({
baseClass: "red-ui-sidebar-header-button",
@@ -47,7 +40,6 @@ RED.sidebar.context = (function() {
});
var footerToolbar = $('<div></div>');
var stackContainer = $("<div>",{class:"red-ui-sidebar-context-stack"}).appendTo(content);
sections = RED.stack.create({
container: stackContainer
@@ -55,10 +47,8 @@ RED.sidebar.context = (function() {
nodeSection = sections.add({
title: RED._("sidebar.context.node"),
collapsible: true,
// onexpand: function() {
// updateNode(currentNode,true);
// }
collapsible: true
// onexpand: function() { updateNode(currentNode,true); }
});
nodeSection.expand();
nodeSection.content.css({height:"100%"});
@@ -73,22 +63,7 @@ RED.sidebar.context = (function() {
evt.preventDefault();
updateNode(currentNode, true);
})
// subflowSection = sections.add({
// title: "Subflow",
// collapsible: true
// });
// subflowSection.expand();
// subflowSection.content.css({height:"100%"});
// bg = $('<div style="float: right"></div>').appendTo(subflowSection.header);
// $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-refresh"></i></button>')
// .appendTo(bg)
// .on("click", function(evt) {
// evt.stopPropagation();
// evt.preventDefault();
// })
//
// subflowSection.container.hide();
RED.popover.tooltip(bg,RED._("sidebar.context.refrsh"));
flowSection = sections.add({
title: RED._("sidebar.context.flow"),
@@ -107,6 +82,7 @@ RED.sidebar.context = (function() {
evt.preventDefault();
updateFlow(currentFlow, true);
})
RED.popover.tooltip(bg,RED._("sidebar.context.refrsh"));
globalSection = sections.add({
title: RED._("sidebar.context.global"),
@@ -126,7 +102,7 @@ RED.sidebar.context = (function() {
evt.preventDefault();
updateEntry(globalSection,"context/global","global");
})
RED.popover.tooltip(bg,RED._("sidebar.context.refrsh"));
RED.actions.add("core:show-context-tab",show);
@@ -163,7 +139,6 @@ RED.sidebar.context = (function() {
// }
// });
RED.events.on("view:selection-changed", function(event) {
var selectedNode = event.nodes && event.nodes.length === 1 && event.nodes[0];
updateNode(selectedNode);
@@ -179,20 +154,31 @@ RED.sidebar.context = (function() {
$('<tr class="red-ui-help-info-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.refresh"></td></tr>').appendTo(globalSection.table).i18n();
globalSection.timestamp.html("&nbsp;");
}
}
function updateNode(node,force) {
currentNode = node;
if (node && /^subflow:/.test(node.type)) {
if (currentNode && currentNode.hasOwnProperty("name") && currentNode.name.length > 0 ) {
$(nodeSection.title).text(RED._("sidebar.context.subflow") + ": " + currentNode.name);
} else {
$(nodeSection.title).text(RED._("sidebar.context.subflow"));
}
} else {
if (currentNode && currentNode.hasOwnProperty("name") && currentNode.name.length > 0 ) {
$(nodeSection.title).text(RED._("sidebar.context.node") + ": " + currentNode.name);
}
else { $(nodeSection.title).text(RED._("sidebar.context.node")); }
}
if (force) {
if (node) {
updateEntry(nodeSection,"context/node/"+node.id,node.id);
// if (/^subflow:/.test(node.type)) {
// subflowSection.container.show();
// updateEntry(subflowSection,"context/flow/"+node.id,node.id);
// } else {
// subflowSection.container.hide();
// }
if (/^subflow:/.test(node.type)) {
//subflowSection.container.show();
updateEntry(nodeSection,"context/flow/"+node.id,node.id);
}
else {
updateEntry(nodeSection,"context/node/"+node.id,node.id);
}
} else {
// subflowSection.container.hide();
updateEntry(nodeSection)
@@ -207,8 +193,10 @@ RED.sidebar.context = (function() {
nodeSection.timestamp.html("&nbsp;");
}
}
function updateFlow(flow, force) {
currentFlow = flow;
$(flowSection.title).text(RED._("sidebar.context.flow") + ": " + currentFlow.label);
if (force || flowAutoRefresh.prop("checked")) {
if (flow) {
updateEntry(flowSection,"context/flow/"+flow.id,flow.id);
@@ -223,7 +211,6 @@ RED.sidebar.context = (function() {
}
function refreshEntry(section,baseUrl,id) {
var contextStores = RED.settings.context.stores;
var container = section.table;
@@ -272,6 +259,7 @@ RED.sidebar.context = (function() {
}
})
});
RED.popover.tooltip(refreshItem,RED._("sidebar.context.refrsh"));
var deleteItem = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-trash"></i></button>').appendTo(tools).on("click", function(e) {
e.preventDefault();
e.stopPropagation();
@@ -322,8 +310,8 @@ RED.sidebar.context = (function() {
}
});
popover.open();
});
RED.popover.tooltip(deleteItem,RED._("sidebar.context.delete"));
var payload = v.msg;
var format = v.format;
RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
@@ -342,6 +330,7 @@ RED.sidebar.context = (function() {
$(section.timestamp).text(new Date().toLocaleString());
});
}
function updateEntry(section,baseUrl,id) {
var container = section.table;
if (id) {
@@ -352,11 +341,10 @@ RED.sidebar.context = (function() {
}
}
function show() {
RED.sidebar.show("context");
}
return {
init: init
}

View File

@@ -128,6 +128,7 @@ RED.sidebar.info = (function() {
$(propertiesSection.content).empty();
$(infoSection.content).empty();
$(helpSection.content).empty();
infoSection.title.text(RED._("sidebar.info.desc"));
var propRow;
@@ -464,7 +465,7 @@ RED.sidebar.info = (function() {
propertiesSection.container.hide();
helpSection.container.hide();
infoSection.container.show();
//helpSection.title.text(title||RED._("sidebar.info.info"));
infoSection.title.text(title||RED._("sidebar.info.desc"));
setInfoText(html,infoSection.content);
$(".red-ui-sidebar-info-stack").scrollTop(0);
}

View File

@@ -25,9 +25,12 @@ RED.tray = (function() {
}
function showTray(options) {
var el = $('<div class="red-ui-tray"></div>');
var header = $('<div class="red-ui-tray-header"></div>').appendTo(el);
// `editor-tray-header` is deprecated - use red-ui-tray-body instead
var header = $('<div class="red-ui-tray-header editor-tray-header"></div>').appendTo(el);
var bodyWrapper = $('<div class="red-ui-tray-body-wrapper"></div>').appendTo(el);
var body = $('<div class="red-ui-tray-body"></div>').appendTo(bodyWrapper);
// `editor-tray-body` is deprecated - use red-ui-tray-body instead
var body = $('<div class="red-ui-tray-body editor-tray-body"></div>').appendTo(bodyWrapper);
// `editor-tray-footer` is deprecated - use red-ui-tray-footer instead
var footer = $('<div class="red-ui-tray-footer"></div>').appendTo(el);
var resizer = $('<div class="red-ui-tray-resize-handle"></div>').appendTo(el);
// var growButton = $('<a class="red-ui-tray-resize-button" style="cursor: w-resize;"><i class="fa fa-angle-left"></i></a>').appendTo(resizer);

View File

@@ -13,6 +13,7 @@ RED.typeSearch = (function() {
var activeFilter = "";
var addCallback;
var cancelCallback;
var moveCallback;
var typesUsed = {};
@@ -44,6 +45,14 @@ RED.typeSearch = (function() {
}
}
function moveDialog(dx,dy) {
var pos = dialog.position();
pos.top = (pos.top + dy)+"px";
pos.left = (pos.left + dx)+"px";
dialog.css(pos);
moveCallback(dx,dy);
}
function createDialog() {
dialog = $("<div>",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#red-ui-main-container");
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
@@ -55,7 +64,19 @@ RED.typeSearch = (function() {
});
searchInput.on('keydown',function(evt) {
var children = searchResults.children(":visible");
if (children.length > 0) {
if (evt.keyCode === 40 && evt.shiftKey) {
evt.preventDefault();
moveDialog(0,10);
} else if (evt.keyCode === 38 && evt.shiftKey) {
evt.preventDefault();
moveDialog(0,-10);
} else if (evt.keyCode === 39 && evt.shiftKey) {
evt.preventDefault();
moveDialog(10,0);
} else if (evt.keyCode === 37 && evt.shiftKey) {
evt.preventDefault();
moveDialog(-10,0);
} else if (children.length > 0) {
if (evt.keyCode === 40) {
// Down
if (selected < children.length-1) {
@@ -68,7 +89,6 @@ RED.typeSearch = (function() {
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 38) {
// Up
if (selected > 0) {
if (selected < children.length) {
$(children[selected]).removeClass('selected');
@@ -79,6 +99,7 @@ RED.typeSearch = (function() {
ensureSelectedIsVisible();
evt.preventDefault();
} else if ((evt.metaKey || evt.ctrlKey) && evt.keyCode === 13 ) {
evt.preventDefault();
// (ctrl or cmd) and enter
var index = Math.max(0,selected);
if (index < children.length) {
@@ -90,8 +111,12 @@ RED.typeSearch = (function() {
addCallback(n.type,true);
}
$("#red-ui-type-search-input").val("").trigger("keyup");
setTimeout(function() {
$("#red-ui-type-search-input").focus();
},100);
}
} else if (evt.keyCode === 13) {
evt.preventDefault();
// Enter
var index = Math.max(0,selected);
if (index < children.length) {
@@ -99,6 +124,12 @@ RED.typeSearch = (function() {
confirm($(children[index]).find(".red-ui-editableList-item-content").data('data'));
}
}
} else {
if (evt.keyCode === 13 ) {
// Stop losing focus if [Cmd]-Enter is pressed on an empty list
evt.stopPropagation();
evt.preventDefault();
}
}
});
@@ -137,7 +168,7 @@ RED.typeSearch = (function() {
if (object.separator) {
container.addClass("red-ui-search-result-separator")
}
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
var div = $('<div>',{class:"red-ui-search-result"}).appendTo(container);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
var colour = RED.utils.getNodeColor(object.type,def);
@@ -219,6 +250,7 @@ RED.typeSearch = (function() {
refreshTypeList(opts);
addCallback = opts.add;
cancelCallback = opts.cancel;
moveCallback = opts.move;
RED.events.emit("type-search:open");
//shade.show();
if ($("#red-ui-main-container").height() - opts.y - 150 < 0) {
@@ -283,7 +315,7 @@ RED.typeSearch = (function() {
function refreshTypeList(opts) {
var i;
searchResults.editableList('empty');
searchInput.searchBox('value','');
searchInput.searchBox('value','').focus();
selected = -1;
var common = [
'inject','debug','function','change','switch'

View File

@@ -101,10 +101,19 @@ RED.userSettings = (function() {
RED.tray.show(trayOptions);
}
function localeToName(lc) {
var name = RED._("languages."+lc);
return {text: (name ? name : lc), val: lc};
}
function compText(a, b) {
return a.text.localeCompare(b.text);
}
var viewSettings = [
{
options: [
{setting:"editor-language",local: true, label:"menu.label.view.language",options:function(done){ done([{val:'',text:RED._('menu.label.view.browserDefault')}].concat(RED.settings.theme("languages"))) }},
{setting:"editor-language",local: true, label:"menu.label.view.language",options:function(done){ done([{val:'',text:RED._('menu.label.view.browserDefault')}].concat(RED.settings.theme("languages").map(localeToName).sort(compText))) }},
]
},{
title: "menu.label.view.grid",

View File

@@ -125,12 +125,14 @@ RED.utils = (function() {
e.stopPropagation();
RED.clipboard.copyText(key,copyPath,"clipboard.copyMessagePath");
})
RED.popover.tooltip(copyPath,RED._("node-red:debug.sidebar.copyPath"));
}
var copyPayload = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-clipboard"></i></button>').appendTo(copyTools).on("click", function(e) {
e.preventDefault();
e.stopPropagation();
RED.clipboard.copyText(msg,copyPayload,"clipboard.copyMessageValue");
})
RED.popover.tooltip(copyPayload,RED._("node-red:debug.sidebar.copyPayload"));
if (strippedKey !== undefined && strippedKey !== '') {
var isPinned = pinnedPaths[sourceId].hasOwnProperty(strippedKey);
@@ -149,6 +151,7 @@ RED.utils = (function() {
}
}).toggleClass("selected",isPinned);
obj.toggleClass("red-ui-debug-msg-row-pinned",isPinned);
RED.popover.tooltip(pinPath,RED._("node-red:debug.sidebar.pinPath"));
}
if (extraTools) {
extraTools.addClass("red-ui-debug-msg-tools-other");

View File

@@ -328,7 +328,7 @@ RED.view = (function() {
accept:".red-ui-palette-node",
drop: function( event, ui ) {
d3.event = event;
var selected_tool = ui.draggable[0].type;
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
var result = addNode(selected_tool);
if (!result) {
return;
@@ -410,6 +410,8 @@ RED.view = (function() {
RED.actions.add("core:zoom-in",zoomIn);
RED.actions.add("core:zoom-out",zoomOut);
RED.actions.add("core:zoom-reset",zoomZero);
RED.actions.add("core:enable-selected-nodes", function() { setSelectedNodeState(false)});
RED.actions.add("core:disable-selected-nodes", function() { setSelectedNodeState(true)});
RED.actions.add("core:toggle-show-grid",function(state) {
if (state === undefined) {
@@ -773,6 +775,15 @@ RED.view = (function() {
x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
filter: filter,
move: function(dx,dy) {
if (ghostNode) {
var pos = d3.transform(ghostNode.attr("transform")).translate;
ghostNode.attr("transform","translate("+(pos[0]+dx)+","+(pos[1]+dy)+")")
point[0] += dx;
point[1] += dy;
rebuildQuickAddLink();
}
},
cancel: function() {
if (quickAddLink) {
if (quickAddLink.el) {
@@ -1367,24 +1378,31 @@ RED.view = (function() {
function zoomIn() {
if (scaleFactor < 2) {
scaleFactor += 0.1;
RED.view.navigator.resize();
redraw();
zoomView(scaleFactor+0.1);
}
}
function zoomOut() {
if (scaleFactor > 0.3) {
scaleFactor -= 0.1;
RED.view.navigator.resize();
redraw();
zoomView(scaleFactor-0.1);
}
}
function zoomZero() {
scaleFactor = 1;
function zoomZero() { zoomView(1); }
function zoomView(factor) {
var screenSize = [chart.width(),chart.height()];
var scrollPos = [chart.scrollLeft(),chart.scrollTop()];
var center = [(scrollPos[0] + screenSize[0]/2)/scaleFactor,(scrollPos[1] + screenSize[1]/2)/scaleFactor];
scaleFactor = factor;
var newCenter = [(scrollPos[0] + screenSize[0]/2)/scaleFactor,(scrollPos[1] + screenSize[1]/2)/scaleFactor];
var delta = [(newCenter[0]-center[0])*scaleFactor,(newCenter[1]-center[1])*scaleFactor]
chart.scrollLeft(scrollPos[0]-delta[0]);
chart.scrollTop(scrollPos[1]-delta[1]);
RED.view.navigator.resize();
redraw();
}
function selectAll() {
if (mouse_mode === RED.state.SELECTING_NODE && selectNodesOptions.single) {
return;
@@ -1396,11 +1414,11 @@ RED.view = (function() {
return;
}
}
}
if (!n.selected) {
n.selected = true;
n.dirty = true;
moving_set.push({n:n});
if (!n.selected) {
n.selected = true;
n.dirty = true;
moving_set.push({n:n});
}
}
});
if (mouse_mode !== RED.state.SELECTING_NODE && activeSubflow) {
@@ -1923,7 +1941,7 @@ RED.view = (function() {
}
var link = {source: src, sourcePort:src_port, target: dst};
if (drag_line.virtualLink) {
if (/^link (in|out)$/.test(src.type) && /^link (in|out)$/.test(dst.type)) {
if (/^link (in|out)$/.test(src.type) && /^link (in|out)$/.test(dst.type) && src.type !== dst.type) {
if (src.links.indexOf(dst.id) === -1 && dst.links.indexOf(src.id) === -1) {
var oldSrcLinks = $.extend(true,{},{v:src.links}).v
var oldDstLinks = $.extend(true,{},{v:dst.links}).v
@@ -2360,7 +2378,7 @@ RED.view = (function() {
function isButtonEnabled(d) {
var buttonEnabled = true;
var ws = RED.nodes.workspace(RED.workspaces.active());
if (ws && !ws.disabled) {
if (ws && !ws.disabled && !d.d) {
if (d._def.button.hasOwnProperty('enabled')) {
if (typeof d._def.button.enabled === "function") {
buttonEnabled = d._def.button.enabled.call(d);
@@ -2381,7 +2399,7 @@ RED.view = (function() {
}
var activeWorkspace = RED.workspaces.active();
var ws = RED.nodes.workspace(activeWorkspace);
if (ws && !ws.disabled) {
if (ws && !ws.disabled && !d.d) {
if (d._def.button.toggle) {
d[d._def.button.toggle] = !d[d._def.button.toggle];
d.dirty = true;
@@ -2913,6 +2931,7 @@ RED.view = (function() {
d.resize = false;
}
var thisNode = d3.select(this);
thisNode.classed("red-ui-flow-node-disabled", function(d) { return d.d === true});
thisNode.classed("red-ui-flow-subflow",function(d) { return activeSubflow != null; })
//thisNode.selectAll(".centerDot").attr({"cx":function(d) { return d.w/2;},"cy":function(d){return d.h/2}});
@@ -3137,7 +3156,7 @@ RED.view = (function() {
} else {
thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(3,"+(d.h+3)+")");
var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill;
thisNode.selectAll(".red-ui-flow-node-status").attr("class","red-ui-flow-node-status "+statusClass);
thisNode.selectAll(".red-ui-flow-node-status").style("display","inline").attr("class","red-ui-flow-node-status "+statusClass);
}
if (d.status.text) {
thisNode.selectAll(".red-ui-flow-node-status-label").text(d.status.text);
@@ -3232,6 +3251,7 @@ RED.view = (function() {
}
return path;
});
link.classed("red-ui-flow-node-disabled", function(d) { return d.source.d || d.target.d; });
}
})
@@ -3562,6 +3582,48 @@ RED.view = (function() {
//TODO: subscribe/unsubscribe here
redraw();
}
function setSelectedNodeState(isDisabled) {
if (mouse_mode === RED.state.SELECTING_NODE) {
return;
}
var workspaceSelection = RED.workspaces.selection();
var changed = false;
if (workspaceSelection.length > 0) {
// TODO: toggle workspace state
} else if (moving_set.length > 0) {
var historyEvents = [];
for (var i=0;i<moving_set.length;i++) {
var node = moving_set[i].n;
if (isDisabled != node.d) {
historyEvents.push({
t: "edit",
node: node,
changed: node.changed,
changes: {
d: node.d
}
});
if (isDisabled) {
node.d = true;
} else {
delete node.d;
}
node.dirty = true;
node.changed = true;
}
}
if (historyEvents.length > 0) {
RED.history.push({
t:"multi",
events: historyEvents,
dirty:RED.nodes.dirty()
})
RED.nodes.dirty(true)
}
}
RED.view.redraw();
}
return {
init: init,
@@ -3632,12 +3694,12 @@ RED.view = (function() {
node.dirty = true;
RED.workspaces.show(node.z);
var screenSize = [chart.width(),chart.height()];
var scrollPos = [chart.scrollLeft(),chart.scrollTop()];
var screenSize = [chart.width()/scaleFactor,chart.height()/scaleFactor];
var scrollPos = [chart.scrollLeft()/scaleFactor,chart.scrollTop()/scaleFactor];
if (node.x < scrollPos[0] || node.y < scrollPos[1] || node.x > screenSize[0]+scrollPos[0] || node.y > screenSize[1]+scrollPos[1]) {
var deltaX = '-='+((scrollPos[0] - node.x) + screenSize[0]/2);
var deltaY = '-='+((scrollPos[1] - node.y) + screenSize[1]/2);
var deltaX = '-='+(((scrollPos[0] - node.x) + screenSize[0]/2)*scaleFactor);
var deltaY = '-='+(((scrollPos[1] - node.y) + screenSize[1]/2)*scaleFactor);
chart.animate({
scrollLeft: deltaX,
scrollTop: deltaY

View File

@@ -60,6 +60,13 @@ RED.workspaces = (function() {
function showEditWorkspaceDialog(id) {
var workspace = RED.nodes.workspace(id);
if (!workspace) {
var subflow = RED.nodes.subflow(id);
if (subflow) {
RED.editor.editSubflow(subflow);
}
return;
}
RED.view.state(RED.state.EDITING);
var tabflowEditor;
var trayOptions = {
@@ -194,8 +201,11 @@ RED.workspaces = (function() {
} else {
workspace.disabled = false;
}
$("#node-input-disabled").toggleButton({invertState: true})
$("#node-input-disabled").toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
@@ -331,6 +341,8 @@ RED.workspaces = (function() {
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace);
RED.actions.add("core:list-flows",function() {
RED.actions.invoke("core:search","type:tab ");
@@ -343,6 +355,48 @@ RED.workspaces = (function() {
showEditWorkspaceDialog(id||activeWorkspace);
}
function enableWorkspace(id) {
setWorkspaceState(id,false);
}
function disableWorkspace(id) {
setWorkspaceState(id,true);
}
function setWorkspaceState(id,disabled) {
var workspace = RED.nodes.workspace(id||activeWorkspace);
if (!workspace) {
return;
}
if (workspace.disabled !== disabled) {
var changes = { disabled: workspace.disabled };
workspace.disabled = disabled;
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
var historyEvent = {
t: "edit",
changes:changes,
node: workspace,
dirty: RED.nodes.dirty()
}
workspace.changed = true;
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
var selection = RED.view.selection();
if (!selection.nodes && !selection.links) {
RED.sidebar.info.refresh(workspace);
}
if (changes.hasOwnProperty('disabled')) {
RED.nodes.eachNode(function(n) {
if (n.z === workspace.id) {
n.dirty = true;
}
});
RED.view.redraw();
}
}
}
function removeWorkspace(ws) {
if (!ws) {
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
@@ -406,6 +460,8 @@ RED.workspaces = (function() {
},
resize: function() {
workspace_tabs.resize();
}
},
enable: enableWorkspace,
disable: disableWorkspace
}
})();

View File

@@ -224,10 +224,10 @@ $node-status-colors: (
$node-selected-color: #ff7f0e;
$port-selected-color: #ff7f0e;
$link-color: #888;
$link-link-color: #ccc;
$link-color: #999;
$link-link-color: #aaa;
$link-disabled-color: #ccc;
$link-link-active-color: #ff7f0e;
$link-subflow-color: #bbb;
$link-unknown-color: #f00;
$clipboard-textarea-background: #F3E7E7;

View File

@@ -218,10 +218,10 @@
.red-ui-debug-msg-row {
display: block;
padding: 4px 2px 2px;
padding: 2px 2px 2px;
position: relative;
&.red-ui-debug-msg-row-pinned {
background: $list-item-border-selected;
background: $secondary-background-selected;
}
}
.red-ui-debug-msg-expandable {

View File

@@ -79,15 +79,20 @@
.red-ui-tray-footer {
@include component-footer;
height: 35px;
font-size: 12px !important;
font-size: 14px !important;
line-height: 35px;
vertical-align: middle;
button {
@include editor-button;
padding: 3px 7px;
font-size: 11px;
button.red-ui-button {
padding: 0px 8px;
height: 26px;
line-height: 26px;
&.toggle:not(.selected) {
color: $workspace-button-color-selected !important;
background: $workspace-button-background-active;
}
}
.red-ui-tray-footer-left {
display:inline-block;
margin-right: 20px;
@@ -461,3 +466,116 @@ button.red-ui-button-small
margin: 2px;
}
}
.red-ui-editor input.red-ui-editor-type-json-editor-key {
width: 150px;
}
.red-ui-editor-type-json-editor {
height: calc(100% - 10px);
.red-ui-treeList-container {
background: $secondary-background;
}
.red-ui-treeList-label {
padding-top: 0;
padding-bottom: 0;
white-space: nowrap;
min-height: 35px;
.red-ui-treeList-icon:before {
content:'';
display: inline-block;
height: 35px;
vertical-align: middle;
}
> span, > span > span {
vertical-align: middle;
}
&:hover, &:hover .red-ui-treeList-sublabel-text {
background: $secondary-background-disabled;
.red-ui-editor-type-json-editor-item-gutter {
> span, > button {
display: inline-block;
}
}
}
&.selected {
.red-ui-editor-type-json-editor-item-gutter {
background: $secondary-background-hover;
}
&:hover {
.red-ui-editor-type-json-editor-item-gutter {
background: $secondary-background-selected;
}
}
}
&.red-ui-editor-type-json-root-node {
.red-ui-editor-type-json-editor-item-gutter {
> span, > button {
display: inline-block;
}
}
}
}
}
.red-ui-editor-type-json-editor-controls {
height: 34px;
line-height: 34px;
display: none;
}
.red-ui-editor-type-json-editor-key {
width: 100px;
}
.red-ui-editor-type-json-editor-label {
display: inline-block;
white-space: pre-wrap;
}
.red-ui-editor-type-json-editor-label-value {
min-width: 200px;
}
.red-ui-editor-type-json-editor-label-value,
.red-ui-editor-type-json-editor-label-key {
display: inline-block;
box-sizing: border-box;
min-height: 34px;
line-height: 30px;
padding: 0 2px;
border: 2px solid rgba(0,0,0,0);
border-radius: 3px;
&:not(.red-ui-editor-type-json-editor-label-array-key):hover {
border-color: $list-item-background-hover;
border-style: dashed;
}
}
.red-ui-editor-type-json-editor-item-gutter {
width: 48px;
padding-left: 4px;
height: 100%;
line-height: 35px;
color: $tertiary-text-color;
background: $secondary-background-disabled;
> span {
display: inline-block;
height: 35px;
line-height: 35px;
width: 20px;
text-align:center;
}
> span, > button {
display: none;
}
}
.red-ui-editor-type-json-editor-item-handle {
cursor: move;
}
.red-ui-editor-type-json-tab-content {
position: relative;
height: calc(100% - 40px);
}
button.red-ui-toggleButton.toggle {
text-align: left;
}

View File

@@ -146,23 +146,42 @@ g.red-ui-flow-node-selected {
border-style: dashed !important;
stroke: $node-selected-color;
stroke-width: 2;
stroke-dasharray: 10, 4;
stroke-dasharray: 8, 3;
}
.red-ui-flow-subflow .red-ui-flow-node {
stroke-dasharray:8, 3;
}
.red-ui-workspace-disabled {
.red-ui-flow-link-line {
stroke-dasharray: 10,5 !important;
stroke-width: 2 !important;
stroke: $link-subflow-color;
}
.red-ui-flow-node {
stroke-dasharray: 10,4;
}
}
.red-ui-workspace-disabled {
.red-ui-flow-node {
stroke-dasharray: 8, 3;
fill-opacity: 0.5;
}
.red-ui-flow-link-line {
stroke-dasharray: 10,8 !important;
stroke-width: 2 !important;
stroke: $link-disabled-color;
}
.red-ui-flow-port {
fill-opacity: 1;
stroke-dasharray: none;
}
}
.red-ui-flow-node-disabled {
&.red-ui-flow-node, .red-ui-flow-node {
stroke-dasharray: 8, 3;
fill-opacity: 0.5;
}
&.red-ui-flow-link-line {
stroke-dasharray: 10,8 !important;
stroke-width: 2 !important;
stroke: $link-disabled-color;
}
.red-ui-flow-port {
fill-opacity: 1;
stroke-dasharray: none;
}
}
@each $current-color in red green yellow blue grey {
.red-ui-flow-node-status-dot-#{$current-color} {
fill: map-get($node-status-colors,$current-color);
@@ -188,7 +207,6 @@ g.red-ui-flow-node-selected {
}
.red-ui-flow-subflow-port {
stroke-dasharray: 5,5;
fill: $node-background-placeholder;
stroke: $node-border;
}
@@ -208,12 +226,14 @@ g.red-ui-flow-node-selected {
}
.red-ui-flow-link-link {
stroke-width: 2;
stroke-dasharray: 10,5;
stroke: $link-link-color;
fill: none;
stroke-dasharray: 15,2;
// pointer-events: none;
stroke-dasharray: 25,4;
}
.red-ui-flow-link-off-flow {
stroke-width: 2;
}
.red-ui-flow-link-port {
fill: $node-link-port-background;
stroke: $link-link-color;
@@ -225,11 +245,6 @@ g.red-ui-flow-node-selected {
.red-ui-flow-link-group:hover {
cursor: pointer;
}
.red-ui-flow-subflow-link {
stroke: $link-subflow-color;
stroke-dasharray: 10,5;
stroke-width: 2;
}
.red-ui-flow-link-outline {
stroke: $view-background;

View File

@@ -26,6 +26,10 @@
box-shadow: none;
}
.ui-widget-header {
color: $header-text-color;
}
/* jQuery Theme overrides */
.ui-tabs .ui-tabs-panel {
padding: 0px;

View File

@@ -192,7 +192,7 @@
right: 0;
height: 25px;
line-height: 25px;
padding: 0 10px;
padding: 0 6px;
user-select: none;
.button-group:not(:last-child) {

View File

@@ -165,7 +165,7 @@
}
}
.red-ui-search-result-description {
.red-ui-search-result-node-description {
margin-left: 40px;
margin-right: 5px;
}
@@ -193,3 +193,14 @@
font-style: italic;
color: $form-placeholder-color;
}
.red-ui-search-result-action {
color: $primary-text-color;
}
.red-ui-search-result-action-key {
position: absolute;
top: 9px;
right: 0;
margin-right: 10px;
color: $tertiary-text-color;
}

View File

@@ -94,12 +94,20 @@ ul.red-ui-sidebar-node-config-list li.red-ui-palette-node-config-type {
text-align:right;
padding-right: 3px;
}
.red-ui-palette-node-config-unused {
.red-ui-palette-node-config-unused,.red-ui-palette-node-config-disabled {
border-color: $primary-border-color;
background: $secondary-background-inactive;
border-style: dashed;
color: $tertiary-text-color;
}
.red-ui-palette-node-config-disabled {
opacity: 0.6;
font-style: italic;
i {
color: $secondary-text-color;
margin-right: 5px;
}
}
.red-ui-sidebar-node-config-filter-info {
position: absolute;
top: 0;

View File

@@ -92,12 +92,12 @@ table.red-ui-info-table tr:not(.blank) td:first-child{
color: $header-text-color;
vertical-align: top;
width: 90px;
padding: 3px 3px 3px 6px;
padding: 6px 3px 3px 6px;
background:$tertiary-background;
border-right: 1px solid $secondary-border-color;
}
table.red-ui-info-table tr:not(.blank) td:last-child{
padding: 3px 3px 3px 6px;
padding: 5px 3px 3px 6px;
color: $primary-text-color;
overflow-y: hidden;
}

View File

@@ -123,7 +123,7 @@
pointer-events: none;
stroke: $secondary-border-color;
strokeWidth: 1;
fill: white;
fill: $view-background;
}
.red-ui-component-footer {

View File

@@ -205,6 +205,7 @@
}
};
RED.events.on("project:change", this.clearMessageList);
RED.actions.add("core:clear-debug-messages", function() { RED.debug.clearMessageList(true) });
$("#red-ui-sidebar-debug-open").on("click", function(e) {
e.preventDefault();
@@ -246,7 +247,8 @@
RED.sidebar.removeTab("debug");
RED.events.off("workspace:change", this.refreshMessageList);
window.removeEventListener("message",this.handleWindowMessage);
RED.actions.remove("core:show-debug");
RED.actions.remove("core:show-debug-tab");
RED.actions.remove("core:clear-debug-messages");
delete RED._debug;
},

View File

@@ -80,6 +80,8 @@
});
this.editor.focus();
RED.popover.tooltip($("#node-function-expand-js"), RED._("node-red:common.label.expand"));
$("#node-function-expand-js").on("click", function(e) {
e.preventDefault();
var value = that.editor.getValue();

View File

@@ -110,6 +110,7 @@
v: Date.now()
});
});
RED.popover.tooltip($("#node-template-expand-editor"), RED._("node-red:common.label.expand"));
$("#node-template-expand-editor").on("click", function(e) {
e.preventDefault();
var value = that.editor.getValue();

View File

@@ -4,7 +4,7 @@
<link rel="stylesheet" href="../../vendor/font-awesome/css/font-awesome.min.css">
<title>Node-RED Debug Tools</title>
</head>
<body class="red-ui-debug-window">
<body class="red-ui-editor red-ui-debug-window">
</body>
<script src="../../vendor/vendor.js"></script>
<script src="../../red/red.min.js"></script>

View File

@@ -203,8 +203,28 @@ module.exports = function(RED) {
var payload = null;
if (method !== 'GET' && method !== 'HEAD' && typeof msg.payload !== "undefined") {
if (opts.headers['content-type'] == 'multipart/form-data' && typeof payload === "object") {
opts.formData = msg.payload;
if (opts.headers['content-type'] == 'multipart/form-data' && typeof msg.payload === "object") {
opts.formData = {};
for (var opt in msg.payload) {
if (msg.payload.hasOwnProperty(opt)) {
var val = msg.payload[opt];
if (val !== undefined && val !== null) {
if (typeof val === 'string' || Buffer.isBuffer(val)) {
opts.formData[opt] = val;
} else if (typeof val === 'object' && val.hasOwnProperty('value')) {
// Treat as file to upload - ensure it has an options object
// as request complains if it doesn't
if (!val.hasOwnProperty('options')) {
val.options = {};
}
opts.formData[opt] = val;
} else {
opts.formData[opt] = JSON.stringify(val);
}
}
}
}
} else {
if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
payload = msg.payload;

View File

@@ -178,6 +178,9 @@ module.exports = function(RED) {
if (this.wholemsg) {
try {
msg = JSON.parse(data);
if (typeof msg !== "object" && !Array.isArray(msg) && (msg !== null)) {
msg = { payload:msg };
}
}
catch(err) {
msg = { payload:data };
@@ -194,20 +197,23 @@ module.exports = function(RED) {
}
WebSocketListenerNode.prototype.broadcast = function(data) {
try {
if (this.isServer) {
for (let client in this._clients) {
if (this._clients.hasOwnProperty(client)) {
if (this.isServer) {
for (let client in this._clients) {
if (this._clients.hasOwnProperty(client)) {
try {
this._clients[client].send(data);
} catch(err) {
this.warn(RED._("websocket.errors.send-error")+" "+client+" "+err.toString())
}
}
}
else {
this.server.send(data);
}
}
catch(e) { // swallow any errors
this.warn("ws:"+i+" : "+e);
else {
try {
this.server.send(data);
} catch(err) {
this.warn(RED._("websocket.errors.send-error")+" "+err.toString())
}
}
}

View File

@@ -128,7 +128,7 @@
var node = this;
var previousValueType = {value:"prev",label:this._("inject.previous"),hasValue:false};
$("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global','jsonata']});
$("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global','jsonata','env']});
var outputCount = $("#node-input-outputs").val("{}");
var andLabel = this._("switch.and");

View File

@@ -627,7 +627,9 @@ module.exports = function(RED) {
var group = inflight[partId];
if (payloadType === 'buffer') {
inflight[partId].bufferLen += property.length;
if (property !== undefined) {
inflight[partId].bufferLen += property.length;
}
}
if (payloadType === 'object') {
group.payload[propertyKey] = property;

View File

@@ -22,7 +22,7 @@
<p>Optionally, the node can be set to stop evaluating rules once it finds one
that matches.</p>
<p>The rules can be evaluated against an individual message property, a flow or global
context property or the result of a JSONata expression.</p>
context property, environment variable or the result of a JSONata expression.</p>
<h4>Rules</h4>
<p>There are four types of rule:</p>
<ol>

View File

@@ -7,7 +7,8 @@
"username": "Username",
"password": "Password",
"property": "Property",
"selectNodes": "Select nodes..."
"selectNodes": "Select nodes...",
"expand": "Expand"
},
"status": {
"connected": "connected",
@@ -137,7 +138,10 @@
"debugNodes": "Debug nodes",
"clearLog": "Clear log",
"filterLog": "Filter log",
"openWindow": "Open in new window"
"openWindow": "Open in new window",
"copyPath": "Copy path",
"copyPayload": "Copy value",
"pinPath": "Pin open"
},
"messageMenu": {
"collapseAll": "Collapse all paths",

View File

@@ -19,7 +19,7 @@
<h3>詳細</h3>
<p>受信したメッセージに対し指定されたルールを順に評価しマッチしたルールに対応する出力ポートにメッセージを送出します</p>
<p>最初にルールがマッチしたところで評価を止めることも可能です</p>
<p>評価ルールにはメッセージプロパティフローコンテキスト/グローバルコンテキストのプロパティJSONata式の評価結果が利用できます</p>
<p>評価ルールにはメッセージプロパティフローコンテキスト/グローバルコンテキストのプロパティ環境変数JSONata式の評価結果が利用できます</p>
<h4>ルール</h4>
<p>振り分けルールは以下の4つに分類されます</p>
<ol>

View File

@@ -6,7 +6,8 @@
"name": "名前",
"username": "ユーザ名",
"password": "パスワード",
"property": "プロパティ"
"property": "プロパティ",
"selectNodes": "ノードを選択..."
},
"status": {
"connected": "接続済",
@@ -90,11 +91,7 @@
"catchUncaught": "catch: 未補足",
"label": {
"source": "エラー取得元",
"node": "ノード",
"type": "型",
"selectAll": "全て選択",
"sortByLabel": "ノード名で並べ替え",
"sortByType": "型で並べ替え",
"uncaught": "Catchードで処理済みのエラーを無視"
},
"scope": {
@@ -107,10 +104,6 @@
"statusNodes": "status: __number__",
"label": {
"source": "状態取得元",
"node": "ノード",
"type": "型",
"selectAll": "全て選択",
"sortByLabel": "ノード名で並べ替え",
"sortByType": "型で並べ替え"
},
"scope": {
@@ -692,7 +685,8 @@
"firstrow": "1行目に列名を含む",
"output": "出力",
"includerow": "1行目を列名とする",
"newline": "改行コード"
"newline": "改行コード",
"usestrings": "数値を変換する"
},
"placeholder": {
"columns": "コンマ区切りで列名を入力"

View File

@@ -23,7 +23,7 @@ function init(_runtime) {
}
function getEntry(type,path) {
var examples = runtime.nodes.getNodeExampleFlows();
var examples = runtime.nodes.getNodeExampleFlows()||{};
var result = [];
if (path === "") {
return Promise.resolve(Object.keys(examples));

View File

@@ -132,29 +132,39 @@ class Flow {
id = configNodes.shift();
node = this.flow.configs[id];
if (!this.activeNodes[id]) {
var readyToCreate = true;
// This node doesn't exist.
// Check it doesn't reference another non-existent config node
for (var prop in node) {
if (node.hasOwnProperty(prop) && prop !== 'id' && prop !== 'wires' && prop !== '_users' && this.flow.configs[node[prop]]) {
if (!this.activeNodes[node[prop]]) {
// References a non-existent config node
// Add it to the back of the list to try again later
configNodes.push(id);
configNodeAttempts[id] = (configNodeAttempts[id]||0)+1;
if (configNodeAttempts[id] === 100) {
throw new Error("Circular config node dependency detected: "+id);
if (node.d !== true) {
var readyToCreate = true;
// This node doesn't exist.
// Check it doesn't reference another non-existent config node
for (var prop in node) {
if (node.hasOwnProperty(prop) &&
prop !== 'id' &&
prop !== 'wires' &&
prop !== '_users' &&
this.flow.configs[node[prop]] &&
this.flow.configs[node[prop]].d !== true
) {
if (!this.activeNodes[node[prop]]) {
// References a non-existent config node
// Add it to the back of the list to try again later
configNodes.push(id);
configNodeAttempts[id] = (configNodeAttempts[id]||0)+1;
if (configNodeAttempts[id] === 100) {
throw new Error("Circular config node dependency detected: "+id);
}
readyToCreate = false;
break;
}
readyToCreate = false;
break;
}
}
}
if (readyToCreate) {
newNode = flowUtil.createNode(this,node);
if (newNode) {
this.activeNodes[id] = newNode;
if (readyToCreate) {
newNode = flowUtil.createNode(this,node);
if (newNode) {
this.activeNodes[id] = newNode;
}
}
} else {
this.debug("not starting disabled config node : "+id);
}
}
}
@@ -171,39 +181,43 @@ class Flow {
for (id in this.flow.nodes) {
if (this.flow.nodes.hasOwnProperty(id)) {
node = this.flow.nodes[id];
if (!node.subflow) {
if (!this.activeNodes[id]) {
newNode = flowUtil.createNode(this,node);
if (newNode) {
this.activeNodes[id] = newNode;
if (node.d !== true) {
if (!node.subflow) {
if (!this.activeNodes[id]) {
newNode = flowUtil.createNode(this,node);
if (newNode) {
this.activeNodes[id] = newNode;
}
}
} else {
if (!this.subflowInstanceNodes[id]) {
try {
var subflowDefinition = this.flow.subflows[node.subflow]||this.global.subflows[node.subflow]
// console.log("NEED TO CREATE A SUBFLOW",id,node.subflow);
this.subflowInstanceNodes[id] = true;
var subflow = Subflow.create(
this,
this.global,
subflowDefinition,
node
);
this.subflowInstanceNodes[id] = subflow;
subflow.start();
this.activeNodes[id] = subflow.node;
// this.subflowInstanceNodes[id] = nodes.map(function(n) { return n.id});
// for (var i=0;i<nodes.length;i++) {
// if (nodes[i]) {
// this.activeNodes[nodes[i].id] = nodes[i];
// }
// }
} catch(err) {
console.log(err.stack)
}
}
}
} else {
if (!this.subflowInstanceNodes[id]) {
try {
var subflowDefinition = this.flow.subflows[node.subflow]||this.global.subflows[node.subflow]
// console.log("NEED TO CREATE A SUBFLOW",id,node.subflow);
this.subflowInstanceNodes[id] = true;
var subflow = Subflow.create(
this,
this.global,
subflowDefinition,
node
);
this.subflowInstanceNodes[id] = subflow;
subflow.start();
this.activeNodes[id] = subflow.node;
// this.subflowInstanceNodes[id] = nodes.map(function(n) { return n.id});
// for (var i=0;i<nodes.length;i++) {
// if (nodes[i]) {
// this.activeNodes[nodes[i].id] = nodes[i];
// }
// }
} catch(err) {
console.log(err.stack)
}
}
this.debug("not starting disabled node : "+id);
}
}
}

View File

@@ -409,7 +409,11 @@ function remapSubflowNodes(nodes,nodeMap) {
for (j=0;j<outputs.length;j++) {
wires = outputs[j];
for (k=0;k<wires.length;k++) {
outputs[j][k] = nodeMap[outputs[j][k]].id
if (nodeMap[outputs[j][k]]) {
outputs[j][k] = nodeMap[outputs[j][k]].id
} else {
outputs[j][k] = null;
}
}
}
}
@@ -421,7 +425,6 @@ function remapSubflowNodes(nodes,nodeMap) {
for (var prop in node) {
if (node.hasOwnProperty(prop) && prop !== '_alias') {
if (nodeMap[node[prop]]) {
//console.log("Mapped",node.type,node.id,prop,nodeMap[node[prop]].id);
node[prop] = nodeMap[node[prop]].id;
}
}

View File

@@ -81,7 +81,7 @@ const result = sass.renderSync({
contents: updatedColors.join("\n")
}
}
return {file:"/Users/nol/code/node-red/node-red/packages/node_modules/@node-red/editor-client/src/sass/"+url+".scss"}
return {file:"../packages/node_modules/@node-red/editor-client/src/sass/"+url+".scss"}
}
});

View File

@@ -77,7 +77,6 @@ module.exports = {
browser.call(function () {
return new Promise(function(resolve, reject) {
cleanup(flowFilename);
app.use("/",express.static("public"));
server = http.createServer(app);
var settings = {
httpAdminRoot: "/",
@@ -102,7 +101,7 @@ module.exports = {
});
});
browser.url(url);
browser.waitForExist('#red-ui-palette-node_inject');
browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']")
} catch (err) {
console.log(err);
throw err;

View File

@@ -16,23 +16,23 @@
var idMap = {
// input
"inject": "#red-ui-palette-node_inject",
"httpin": "#red-ui-palette-node_http_in",
"mqttIn": "#red-ui-palette-node_mqtt_in",
"inject": ".red-ui-palette-node[data-palette-type='inject']",
"httpin": ".red-ui-palette-node[data-palette-type='http in']",
"mqttIn": ".red-ui-palette-node[data-palette-type='mqtt in']",
// output
"debug": "#red-ui-palette-node_debug",
"httpResponse": "#red-ui-palette-node_http_response",
"mqttOut": "#red-ui-palette-node_mqtt_out",
"debug": ".red-ui-palette-node[data-palette-type='debug']",
"httpResponse": ".red-ui-palette-node[data-palette-type='http response']",
"mqttOut": ".red-ui-palette-node[data-palette-type='mqtt out']",
// function
"function": "#red-ui-palette-node_function",
"template": "#red-ui-palette-node_template",
"change": "#red-ui-palette-node_change",
"range": "#red-ui-palette-node_range",
"httpRequest": "#red-ui-palette-node_http_request",
"html": "#red-ui-palette-node_html",
"json": "#red-ui-palette-node_json",
"function": ".red-ui-palette-node[data-palette-type='function']",
"template": ".red-ui-palette-node[data-palette-type='template']",
"change": ".red-ui-palette-node[data-palette-type='change']",
"range": ".red-ui-palette-node[data-palette-type='range']",
"httpRequest": ".red-ui-palette-node[data-palette-type='http request']",
"html": ".red-ui-palette-node[data-palette-type='html']",
"json": ".red-ui-palette-node[data-palette-type='json']",
// storage
"filein": "#red-ui-palette-node_file_in",
"filein": ".red-ui-palette-node[data-palette-type='file in']",
};
function getId(type) {

View File

@@ -49,14 +49,14 @@ function addNode(type, x, y) {
browser.moveToObject("#red-ui-palette-search", previousX + 300, previousY + 100); // adjust to the top-left corner of workspace.
browser.buttonUp();
// Last node is the one that has been created right now.
var nodeElement = browser.elements('//*[@class="red-ui-flow-node red-ui-flow-node-group"][last()]');
var nodeElement = browser.elements('//*[contains(concat(" ", normalize-space(@class), " "), " red-ui-flow-node-group ")][last()]');
var nodeId = nodeElement.getAttribute('id');
var node = nodeFactory.create(type, nodeId);
return node;
}
function deleteAllNodes() {
browser.click('.innerCanvas');
browser.click('.red-ui-workspace-chart-event-layer');
browser.keys(['Control', 'a', 'a', 'Control']); // call twice to release the keys.
browser.keys(['Delete']);
}

View File

@@ -179,6 +179,24 @@ describe('websocket Node', function() {
});
});
it('should receive wholemsg when data not object', function(done) {
var flow = [
{ id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
{ id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
{ id: "n3", type: "helper" }];
helper.load(websocketNode, flow, function() {
createClient("n1").then(function(sock) {
helper.getNode("n3").on("input", function(msg) {
msg.should.have.property("payload", 123);
done();
});
sock.send(123);
}).catch(function(err) {
done(err);
});
});
});
it('should send', function(done) {
var flow = [
{ id: "n1", type: "websocket-listener", path: "/ws" },

View File

@@ -818,6 +818,14 @@ describe('switch Node', function() {
});
});
it('should handle env var expression', function(done) {
var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"VAR",propertyType:"env",rules:[{"t":"eq","v":"VAL"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
process.env.VAR = "VAL";
customFlowSwitchTest(flow, true, "OK", done);
});
it('should take head of message sequence (no repair)', function(done) {
var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"head","v":3}],checkall:false,repair:false,outputs:1,wires:[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];

View File

@@ -319,6 +319,57 @@ describe('Flow', function() {
});
});
it("ignores disabled nodes",function(done) {
var config = flowUtils.parseConfig([
{id:"t1",type:"tab"},
{id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
{id:"2",x:10,y:10,z:"t1",d:true,type:"test",foo:"a",wires:["3"]},
{id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
{id:"4",z:"t1",type:"test",foo:"a"},
{id:"5",z:"t1",type:"test",d:true,foo:"a"}
]);
var flow = Flow.create({},config,config.flows["t1"]);
flow.start();
Object.keys(flow.getActiveNodes()).should.have.length(3);
flow.getNode('1').should.have.a.property('id','1');
should.not.exist(flow.getNode('2'));
flow.getNode('3').should.have.a.property('id','3');
flow.getNode('4').should.have.a.property('id','4');
should.not.exist(flow.getNode('5'));
currentNodes.should.have.a.property("1");
currentNodes.should.not.have.a.property("2");
currentNodes.should.have.a.property("3");
currentNodes.should.have.a.property("4");
currentNodes["1"].should.have.a.property("handled",0);
currentNodes["3"].should.have.a.property("handled",0);
currentNodes["1"].receive({payload:"test"});
currentNodes["1"].should.have.a.property("handled",1);
// Message doesn't reach 3 as 2 is disabled
currentNodes["3"].should.have.a.property("handled",0);
flow.stop().then(function() {
try {
currentNodes.should.not.have.a.property("1");
currentNodes.should.not.have.a.property("2");
currentNodes.should.not.have.a.property("3");
currentNodes.should.not.have.a.property("4");
stoppedNodes.should.have.a.property("1");
stoppedNodes.should.not.have.a.property("2");
stoppedNodes.should.have.a.property("3");
stoppedNodes.should.have.a.property("4");
done();
} catch(err) {
done(err);
}
});
});
});