').appendTo(container);
+ content.css("padding","8px 5px")
+ var min = ui.opts.min;
+ var max = ui.opts.max;
+ var minInput = $('
');
+ minInput.val(min);
+ var maxInput = $('
');
+ maxInput.val(max);
+ $('
').append(minInput).appendTo(content);
+ $('
').append(maxInput).appendTo(content);
+ return {
+ onclose: function() {
+ var min = minInput.val().trim();
+ var max = maxInput.val().trim();
+ if (min !== "") {
+ ui.opts.min = parseInt(min);
+ } else {
+ delete ui.opts.min;
+ }
+ if (max !== "") {
+ ui.opts.max = parseInt(max);
+ } else {
+ delete ui.opts.max;
+ }
+ inputCellInput.typedInput('value',Date.now())
+ }
+ }
+ }
+ }
+ },
+ {
+ value:"none",
+ label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
+ },
+ {
+ value:"hide",
+ label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
+ }
+ ],
+ default: 'none'
+ }).on("typedinputtypechange", function(evt,type) {
+ ui.type = $(this).typedInput("type");
+ ui.opts = typeOptions[ui.type];
+ if (ui.type === 'input') {
+ // In the case of 'input' type, the typedInput uses the multiple-option
+ // mode. Its value needs to be set to a comma-separately list of the
+ // selected options.
+ inputCellInput.typedInput('value',ui.opts.types.join(","))
+ } else {
+ // No other type cares about `value`, but doing this will
+ // force a refresh of the label now that `ui.opts` has
+ // been updated.
+ inputCellInput.typedInput('value',Date.now())
+ }
- switch (ui.type) {
- case 'input':
+ switch (ui.type) {
+ case 'input':
valueField.typedInput('types',ui.opts.types);
break;
case 'select':
- valueField.typedInput('types',['str']);
- break;
- case 'checkbox':
+ valueField.typedInput('types',['str']);
+ break;
+ case 'checkbox':
valueField.typedInput('types',['bool']);
break;
case 'spinner':
- valueField.typedInput('types',['num'])
+ valueField.typedInput('types',['num']);
+ break;
+ case 'cred':
+ valueField.typedInput('types',['cred']);
break;
default:
- valueField.typedInput('types',['str','num','bool','json','bin','env'])
- }
- if (ui.type === 'checkbox') {
- valueField.typedInput('type','bool');
- } else if (ui.type === 'spinner') {
- valueField.typedInput('type','num');
- }
- if (ui.type !== 'checkbox') {
- checkbox = null;
- }
+ valueField.typedInput('types',DEFAULT_ENV_TYPE_LIST)
+ }
+ if (ui.type === 'checkbox') {
+ valueField.typedInput('type','bool');
+ } else if (ui.type === 'spinner') {
+ valueField.typedInput('type','num');
+ }
+ if (ui.type !== 'checkbox') {
+ checkbox = null;
+ }
- }).on("change", function(evt,type) {
- if (ui.type === 'input') {
- ui.opts.types = inputCellInput.typedInput('value').split(",");
- valueField.typedInput('types',ui.opts.types);
- }
- });
- valueField.on("change", function(evt) {
- if (checkbox) {
- checkbox.prop('checked',$(this).typedInput('value')==="true")
- }
- })
- // Set the input to the right type. This will trigger the 'typedinputtypechange'
- // event handler (just above ^^) to update the value if needed
- inputCellInput.typedInput('type',ui.type)
+ }).on("change", function(evt,type) {
+ if (ui.type === 'input') {
+ ui.opts.types = inputCellInput.typedInput('value').split(",");
+ valueField.typedInput('types',ui.opts.types);
+ }
+ });
+ valueField.on("change", function(evt) {
+ if (checkbox) {
+ checkbox.prop('checked',$(this).typedInput('value')==="true")
+ }
+ })
+ // Set the input to the right type. This will trigger the 'typedinputtypechange'
+ // event handler (just above ^^) to update the value if needed
+ inputCellInput.typedInput('type',ui.type)
}
- function buildEnvUIRow(row, tenv, ui) {
+ function buildEnvUIRow(row, tenv, ui, node) {
ui.label = ui.label||{};
- if (!ui.type) {
+ if ((tenv.type === "cred" || (tenv.parent && tenv.parent.type === "cred")) && !ui.type) {
+ ui.type = "cred";
+ ui.opts = {};
+ } else if (!ui.type) {
ui.type = "input";
- ui.opts = {types:['str','num','bool','json','bin','env']}
+ ui.opts = {types:DEFAULT_ENV_TYPE_LIST}
} else {
if (!ui.opts) {
ui.opts = (ui.type === "select") ? {opts:[]} : {};
@@ -1467,6 +1574,24 @@ RED.subflow = (function() {
input.spinner(spinnerOpts).parent().width('70%');
input.val(val.value);
break;
+ case "cred":
+ input = $('
').css('width','70%').appendTo(row);
+ if (node.credentials) {
+ if (node.credentials[tenv.name]) {
+ input.val(node.credentials[tenv.name]);
+ } else if (node.credentials['has_'+tenv.name]) {
+ input.val("__PWRD__")
+ } else {
+ input.val("");
+ }
+ } else {
+ input.val("");
+ }
+ input.typedInput({
+ types: ['cred'],
+ default: 'cred'
+ })
+ break;
}
if (input) {
input.attr('id',getSubflowEnvPropertyName(tenv.name))
@@ -1478,7 +1603,7 @@ RED.subflow = (function() {
* @param uiContainer - container for UI
* @param envList - env var definitions of template
*/
- function buildEnvUI(uiContainer, envList) {
+ function buildEnvUI(uiContainer, envList,node) {
uiContainer.empty();
var elementID = 0;
for (var i = 0; i < envList.length; i++) {
@@ -1487,7 +1612,7 @@ RED.subflow = (function() {
continue;
}
var row = $("
", { class: "form-row" }).appendTo(uiContainer);
- buildEnvUIRow(row,tenv, tenv.ui || {});
+ buildEnvUIRow(row,tenv, tenv.ui || {}, node);
// console.log(ui);
}
@@ -1525,7 +1650,7 @@ RED.subflow = (function() {
// icon: "",
// label: {},
// type: "input",
- // opts: {types:['str','num','bool','json','bin','env']}
+ // opts: {types:DEFAULT_ENV_TYPE_LIST}
// }
if (!ui.icon) {
delete ui.icon;
@@ -1535,13 +1660,19 @@ RED.subflow = (function() {
}
switch (ui.type) {
case "input":
- if (JSON.stringify(ui.opts) === JSON.stringify({types:['str','num','bool','json','bin','env']})) {
+ if (JSON.stringify(ui.opts) === JSON.stringify({types:DEFAULT_ENV_TYPE_LIST})) {
// This is the default input config. Delete it as it will
// be applied automatically
delete ui.type;
delete ui.opts;
}
break;
+ case "cred":
+ if (envItem.type === "cred") {
+ delete ui.type;
+ }
+ delete ui.opts;
+ break;
case "select":
if (ui.opts && $.isEmptyObject(ui.opts.opts)) {
// This is the default select config.
@@ -1585,7 +1716,7 @@ RED.subflow = (function() {
type: env.type,
value: env.value
},
- ui: env.ui
+ ui: $.extend(true,{},env.ui)
}
envList.push(item);
parentEnv[env.name] = item;
@@ -1621,13 +1752,17 @@ RED.subflow = (function() {
var item;
var ui = data.ui || {};
if (!ui.type) {
- ui.type = "input";
- ui.opts = {types:['str','num','bool','json','bin','env']}
+ if (data.parent && data.parent.type === "cred") {
+ ui.type = "cred";
+ } else {
+ ui.type = "input";
+ ui.opts = {types:DEFAULT_ENV_TYPE_LIST}
+ }
} else {
ui.opts = ui.opts || {};
}
var input = $("#"+getSubflowEnvPropertyName(data.name));
- if (input.length) {
+ if (input.length || ui.type === "cred") {
item = { name: data.name };
switch(ui.type) {
case "input":
@@ -1639,6 +1774,10 @@ RED.subflow = (function() {
item.type = 'str';
}
break;
+ case "cred":
+ item.value = input.val();
+ item.type = 'cred';
+ break;
case "spinner":
item.value = input.val();
item.type = 'num';
@@ -1652,7 +1791,7 @@ RED.subflow = (function() {
item.value = ""+input.prop("checked");
break;
}
- if (item.type !== data.parent.type || item.value !== data.parent.value) {
+ if (ui.type === "cred" || item.type !== data.parent.type || item.value !== data.parent.value) {
env.push(item);
}
}
@@ -1702,14 +1841,17 @@ RED.subflow = (function() {
return defaultLabel;
}
- function buildEditForm(container,type,node) {
+ function buildEditForm(type,node) {
if (type === "subflow-template") {
buildPropertiesList($('#node-input-env-container'), node);
} else if (type === "subflow") {
- buildEnvUI($("#subflow-input-ui"), getSubflowInstanceParentEnv(node));
+ // This gets called by the subflow type `oneditprepare` function
+ // registered in nodes.js#addSubflow()
+ buildEnvUI($("#subflow-input-ui"), getSubflowInstanceParentEnv(node), node);
}
}
- function buildPropertiesForm(container, node) {
+ function buildPropertiesForm(node) {
+ var container = $('#editor-subflow-envProperties-content');
var form = $('
').appendTo(container);
var listContainer = $('
').appendTo(form);
var list = $('
').appendTo(listContainer);
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
new file mode 100644
index 000000000..4c469425b
--- /dev/null
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
@@ -0,0 +1,332 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+RED.sidebar.help = (function() {
+
+ var content;
+ var toolbar;
+ var helpSection;
+ var panels;
+ var panelRatio;
+ var helpTopics = [];
+ var treeList;
+ var tocPanel;
+ var helpIndex = {};
+
+
+ function resizeStack() {
+ var h = $(content).parent().height() - toolbar.outerHeight();
+ panels.resize(h)
+ }
+
+ function init() {
+
+ content = document.createElement("div");
+ content.className = "red-ui-sidebar-info"
+
+ toolbar = $("
", {class:"red-ui-sidebar-header red-ui-info-toolbar"}).appendTo(content);
+ $('
').appendTo(toolbar)
+ var showTOCButton = toolbar.find('#red-ui-sidebar-help-show-toc')
+ RED.popover.tooltip(showTOCButton,RED._("sidebar.help.showTopics"));
+ showTOCButton.on("click",function(e) {
+ e.preventDefault();
+ if ($(this).hasClass('selected')) {
+ hideTOC();
+ } else {
+ showTOC();
+ }
+ });
+
+ var stackContainer = $("
",{class:"red-ui-sidebar-help-stack"}).appendTo(content);
+
+ tocPanel = $("
", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer);
+ var helpPanel = $("
").css({
+ "overflow-y": "scroll"
+ }).appendTo(stackContainer);
+
+ panels = RED.panels.create({
+ container: stackContainer
+ })
+ panels.ratio(0.3);
+
+ helpSearch = $('
').appendTo(toolbar).searchBox({
+ delay: 100,
+ change: function() {
+ var val = $(this).val().toLowerCase();
+ if (val) {
+ showTOC();
+ var c = treeList.treeList('filter',function(item) {
+ if (item.depth === 0) {
+ return true;
+ }
+ return (item.nodeType && item.nodeType.indexOf(val) > -1) ||
+ (item.subflowLabel && item.subflowLabel.indexOf(val) > -1)
+ },true)
+ } else {
+ treeList.treeList('filter',null);
+ var selected = treeList.treeList('selected');
+ if (selected.id) {
+ treeList.treeList('show',selected.id);
+ }
+
+ }
+ }
+ })
+
+ helpSection = $("
",{class:"red-ui-help"}).css({
+ "padding":"6px",
+ }).appendTo(helpPanel)
+
+ $('
'+RED._("sidebar.help.noHelp")+'').appendTo(helpSection);
+
+ treeList = $("
").css({width: "100%"}).appendTo(tocPanel).treeList({data: []})
+ treeList.on('treelistselect', function(e,item) {
+ if (item.nodeType) {
+ showHelp(item.nodeType);
+ }
+ })
+
+ RED.sidebar.addTab({
+ id: "help",
+ label: RED._("sidebar.help.label"),
+ name: RED._("sidebar.help.name"),
+ iconClass: "fa fa-book",
+ action:"core:show-help-tab",
+ content: content,
+ pinned: true,
+ enableOnEdit: true,
+ onchange: function() {
+ resizeStack()
+ }
+ });
+
+ $(window).on("resize", resizeStack);
+ $(window).on("focus", resizeStack);
+
+ RED.events.on('registry:node-type-added', queueRefresh);
+ RED.events.on('registry:node-type-removed', queueRefresh);
+ RED.events.on('subflows:change', refreshSubflow);
+
+ RED.actions.add("core:show-help-tab",show);
+
+ }
+
+ var refreshTimer;
+ function queueRefresh() {
+ if (!refreshTimer) {
+ refreshTimer = setTimeout(function() {
+ refreshTimer = null;
+ refreshHelpIndex();
+ },500);
+ }
+ }
+
+ function refreshSubflow(sf) {
+ var item = treeList.treeList('get',"node-type:subflow:"+sf.id);
+ item.subflowLabel = sf._def.label().toLowerCase();
+ item.treeList.replaceElement(getNodeLabel({_def:sf._def,type:sf._def.label()}));
+ }
+
+ function hideTOC() {
+ var tocButton = $('#red-ui-sidebar-help-show-toc')
+ if (tocButton.hasClass('selected')) {
+ tocButton.removeClass('selected');
+ panelRatio = panels.ratio();
+ tocPanel.css({"transition":"height 0.2s"})
+ panels.ratio(0)
+ setTimeout(function() {
+ tocPanel.css({"transition":""})
+ },250);
+ }
+ }
+ function showTOC() {
+ var tocButton = $('#red-ui-sidebar-help-show-toc')
+ if (!tocButton.hasClass('selected')) {
+ tocButton.addClass('selected');
+ tocPanel.css({"transition":"height 0.2s"})
+ panels.ratio(Math.max(0.3,Math.min(panelRatio,0.7)));
+ setTimeout(function() {
+ tocPanel.css({"transition":""})
+ var selected = treeList.treeList('selected');
+ if (selected.id) {
+ treeList.treeList('show',selected);
+ }
+ },250);
+ }
+ }
+
+ function refreshHelpIndex() {
+ helpTopics = [];
+ var modules = RED.nodes.registry.getModuleList();
+ var moduleNames = Object.keys(modules);
+ moduleNames.sort();
+
+ var helpData = [{
+ label: RED._("sidebar.help.nodeHelp"),
+ children: [],
+ expanded: true
+ }]
+
+ var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)});
+ if (subflows.length > 0) {
+ helpData[0].children.push({
+ label: RED._("menu.label.subflows"),
+ children: []
+ })
+ subflows.forEach(function(nodeType) {
+ var sf = RED.nodes.getType(nodeType);
+ helpData[0].children[0].children.push({
+ id:"node-type:"+nodeType,
+ nodeType: nodeType,
+ subflowLabel: sf.label().toLowerCase(),
+ element: getNodeLabel({_def:sf,type:sf.label()})
+ })
+ })
+ }
+
+
+ moduleNames.forEach(function(moduleName) {
+ var module = modules[moduleName];
+ var nodeTypes = [];
+
+ var setNames = Object.keys(module.sets);
+ setNames.forEach(function(setName) {
+ module.sets[setName].types.forEach(function(nodeType) {
+ if ($("script[data-help-name='"+nodeType+"']").length) {
+ nodeTypes.push({
+ id: "node-type:"+nodeType,
+ nodeType: nodeType,
+ element:getNodeLabel({_def:RED.nodes.getType(nodeType),type:nodeType})
+ })
+ }
+ })
+ })
+ if (nodeTypes.length > 0) {
+ nodeTypes.sort(function(A,B) {
+ return A.nodeType.localeCompare(B.nodeType)
+ })
+ helpData[0].children.push({
+ id: moduleName,
+ icon: "fa fa-cube",
+ label: moduleName,
+ children: nodeTypes
+ })
+ }
+ });
+ treeList.treeList("data",helpData);
+ }
+
+ function getNodeLabel(n) {
+ var div = $('
',{class:"red-ui-info-outline-item"});
+ RED.utils.createNodeIcon(n).appendTo(div);
+ var contentDiv = $('
',{class:"red-ui-search-result-description"}).appendTo(div);
+ $('
',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).text(n.name||n.type).appendTo(contentDiv);
+ return div;
+ }
+
+ function showHelp(nodeType) {
+ helpSection.empty();
+ var helpText;
+ var title;
+ var m = /^subflow(:(.+))?$/.exec(nodeType);
+ if (m && m[2]) {
+ var subflowNode = RED.nodes.subflow(m[2]);
+ helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('
'+RED._("sidebar.info.none")+''));
+ title = subflowNode.name || nodeType;
+ } else {
+ helpText = $("script[data-help-name='"+nodeType+"']").html()||('
'+RED._("sidebar.info.none")+'');
+ title = nodeType;
+ }
+ setInfoText(title, helpText, helpSection);
+
+ var ratio = panels.ratio();
+ if (ratio > 0.7) {
+ panels.ratio(0.7)
+ }
+ treeList.treeList("show","node-type:"+nodeType)
+ treeList.treeList("select","node-type:"+nodeType, false);
+
+ }
+
+ function show(type) {
+ RED.sidebar.show("help");
+ if (type) {
+ hideTOC();
+ showHelp(type);
+ }
+ }
+
+ // TODO: DRY - projects.js
+ function addTargetToExternalLinks(el) {
+ $(el).find("a").each(function(el) {
+ var href = $(this).attr('href');
+ if (/^https?:/.test(href)) {
+ $(this).attr('target','_blank');
+ }
+ });
+ return el;
+ }
+
+ function setInfoText(title, infoText,target) {
+ if (title) {
+ $("
",{class:"red-ui-help-title"}).text(title).appendTo(target);
+ }
+ var info = addTargetToExternalLinks($('
'+infoText+'
')).appendTo(target);
+ info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "" );
+ var foldingHeader = "H3";
+ info.find(foldingHeader).wrapInner('')
+ .find("a").prepend('').on("click", function(e) {
+ e.preventDefault();
+ var isExpanded = $(this).hasClass('expanded');
+ var el = $(this).parent().next();
+ while(el.length === 1 && el[0].nodeName !== foldingHeader) {
+ el.toggle(!isExpanded);
+ el = el.next();
+ }
+ $(this).toggleClass('expanded',!isExpanded);
+ })
+ target.parent().scrollTop(0);
+ }
+
+ function set(html,title) {
+ $(helpSection).empty();
+ setInfoText(title,html,helpSection);
+ hideTOC();
+ show();
+ }
+
+ function refreshSelection(selection) {
+ if (selection === undefined) {
+ selection = RED.view.selection();
+ }
+ if (selection.nodes) {
+ if (selection.nodes.length == 1) {
+ var node = selection.nodes[0];
+ if (node.type === "subflow" && node.direction) {
+ // ignore subflow virtual ports
+ } else if (node.type !== 'group'){
+ showHelp(node.type);
+ }
+ }
+ }
+ }
+ RED.events.on("view:selection-changed",refreshSelection);
+
+ return {
+ init: init,
+ show: show,
+ set: set
+ }
+})();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js
new file mode 100644
index 000000000..ccecfd043
--- /dev/null
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js
@@ -0,0 +1,475 @@
+RED.sidebar.info.outliner = (function() {
+
+ var treeList;
+ var searchInput;
+ var projectInfo;
+ var projectInfoLabel;
+ var flowList;
+ var subflowList;
+ var globalConfigNodes;
+
+ var objects = {};
+ var missingParents = {};
+
+ function getFlowData() {
+ var flowData = [
+ {
+ label: RED._("menu.label.flows"),
+ expanded: true,
+ children: []
+ },
+ {
+ label: RED._("menu.label.subflows"),
+ children: []
+ },
+ {
+ id: "__global__",
+ label: RED._("sidebar.info.globalConfig"),
+ children: []
+ }
+ ]
+ flowList = flowData[0];
+ subflowList = flowData[1];
+ globalConfigNodes = flowData[2];
+
+ return flowData;
+ }
+
+ function getProjectLabel(p) {
+ var div = $('',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"});
+ div.css("width", "calc(100% - 40px)");
+ var contentDiv = $('
',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div);
+ contentDiv.text(p.name);
+ var controls = $('
',{class:"red-ui-info-outline-item-controls"}).appendTo(div);
+ var editProjectButton = $('
')
+ .appendTo(controls)
+ .on("click", function(evt) {
+ evt.preventDefault();
+ RED.projects.editProject();
+ });
+ RED.popover.tooltip(editProjectButton,RED._('sidebar.project.showProjectSettings'));
+ return div;
+ }
+
+ var empties = {};
+ function getEmptyItem(id) {
+ var item = {
+ empty: true,
+ element: $('
').text(RED._("sidebar.info.empty")),
+ }
+ empties[id] = item;
+ return item;
+ }
+
+ function getNodeLabelText(n) {
+ var label = n.name || n.type+": "+n.id;
+ if (n._def.label) {
+ try {
+ label = (typeof n._def.label === "function" ? n._def.label.call(n) : n._def.label)||"";
+ } catch(err) {
+ console.log("Definition error: "+type+".label",err);
+ }
+ }
+ var newlineIndex = label.indexOf("\\n");
+ if (newlineIndex > -1) {
+ label = label.substring(0,newlineIndex)+"...";
+ }
+ return label;
+ }
+
+ function getNodeLabel(n) {
+ var div = $('
',{class:"red-ui-info-outline-item"});
+ RED.utils.createNodeIcon(n).appendTo(div);
+ var contentDiv = $('
',{class:"red-ui-search-result-description"}).appendTo(div);
+ var labelText = getNodeLabelText(n);
+ var label = $('
',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).appendTo(contentDiv);
+ if (labelText) {
+ label.text(labelText)
+ } else {
+ label.html(" ")
+ }
+
+ addControls(n, div);
+
+ return div;
+ }
+
+ function getFlowLabel(n) {
+ var div = $('
',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"});
+ var contentDiv = $('
',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div);
+ var label = (typeof n === "string")? n : n.label;
+ var newlineIndex = label.indexOf("\\n");
+ if (newlineIndex > -1) {
+ label = label.substring(0,newlineIndex)+"...";
+ }
+ contentDiv.text(label);
+ addControls(n, div);
+ return div;
+ }
+
+ function getSubflowLabel(n) {
+
+ var div = $('
',{class:"red-ui-info-outline-item"});
+ RED.utils.createNodeIcon(n).appendTo(div);
+ var contentDiv = $('
',{class:"red-ui-search-result-description"}).appendTo(div);
+ var labelText = getNodeLabelText(n);
+ var label = $('
',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).appendTo(contentDiv);
+ if (labelText) {
+ label.text(labelText)
+ } else {
+ label.html(" ")
+ }
+
+ addControls(n, div);
+
+ return div;
+
+
+ // var div = $('
',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"});
+ // var contentDiv = $('
',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div);
+ // contentDiv.text(n.name || n.id);
+ // addControls(n, div);
+ // return div;
+ }
+
+ function addControls(n,div) {
+ var controls = $('
',{class:"red-ui-info-outline-item-controls red-ui-info-outline-item-hover-controls"}).appendTo(div);
+ if (n._def.button) {
+ $('
').appendTo(controls).on("click",function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ RED.view.clickNodeButton(n);
+ })
+ }
+ // $('
').appendTo(controls).on("click",function(evt) {
+ // evt.preventDefault();
+ // evt.stopPropagation();
+ // RED.view.reveal(n.id);
+ // })
+ if (n.type !== 'group' && n.type !== 'subflow') {
+ $('
').appendTo(controls).on("click",function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (n.type === 'tab') {
+ if (n.disabled) {
+ RED.workspaces.enable(n.id)
+ } else {
+ RED.workspaces.disable(n.id)
+ }
+ } else {
+ // TODO: this ought to be a utility function in RED.nodes
+ var historyEvent = {
+ t: "edit",
+ node: n,
+ changed: n.changed,
+ changes: {
+ d: n.d
+ },
+ dirty:RED.nodes.dirty()
+ }
+ if (n.d) {
+ delete n.d;
+ } else {
+ n.d = true;
+ }
+ n.dirty = true;
+ n.changed = true;
+ RED.events.emit("nodes:change",n);
+ RED.nodes.dirty(true)
+ RED.view.redraw();
+ }
+ });
+ } else {
+ $('
').appendTo(controls)
+ }
+ controls.find("button").on("dblclick", function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ })
+ }
+
+ function onProjectLoad(activeProject) {
+ objects = {};
+ var newFlowData = getFlowData();
+ projectInfoLabel.empty();
+ getProjectLabel(activeProject).appendTo(projectInfoLabel);
+ projectInfo.show();
+ treeList.treeList('data',newFlowData);
+ }
+
+ function build() {
+ var container = $("
", {class:"red-ui-info-outline"}).css({'height': '100%'});
+ var toolbar = $("
", {class:"red-ui-sidebar-header red-ui-info-toolbar"}).appendTo(container);
+
+ searchInput = $('').appendTo(toolbar).searchBox({
+ delay: 300,
+ change: function() {
+ var val = $(this).val();
+ var searchResults = RED.search.search(val);
+ if (val) {
+ var resultMap = {};
+ for (var i=0,l=searchResults.length;i
').hide().appendTo(container)
+ projectInfoLabel = $('
').appendTo(projectInfo);
+
+ // ').appendTo(container)
+
+ treeList = $("
").css({width: "100%"}).appendTo(container).treeList({
+ data:getFlowData()
+ })
+ treeList.on('treelistselect', function(e,item) {
+ var node = RED.nodes.node(item.id) || RED.nodes.group(item.id);
+ if (node) {
+ if (node.type === 'group' || node._def.category !== "config") {
+ RED.view.select({nodes:[node]})
+ } else {
+ RED.view.select({nodes:[]})
+ }
+ }
+ })
+ treeList.on('treelistconfirm', function(e,item) {
+ var node = RED.nodes.node(item.id);
+ if (node) {
+ if (node._def.category === "config") {
+ RED.editor.editConfig("", node.type, node.id);
+ } else {
+ RED.editor.edit(node);
+ }
+ }
+ })
+
+ RED.events.on("projects:load", onProjectLoad)
+
+ RED.events.on("flows:add", onFlowAdd)
+ RED.events.on("flows:remove", onObjectRemove)
+ RED.events.on("flows:change", onFlowChange)
+ RED.events.on("flows:reorder", onFlowsReorder)
+
+ RED.events.on("subflows:add", onSubflowAdd)
+ RED.events.on("subflows:remove", onObjectRemove)
+ RED.events.on("subflows:change", onSubflowChange)
+
+ RED.events.on("nodes:add",onNodeAdd);
+ RED.events.on("nodes:remove",onObjectRemove);
+ RED.events.on("nodes:change",onNodeChange);
+
+ RED.events.on("groups:add",onNodeAdd);
+ RED.events.on("groups:remove",onObjectRemove);
+ RED.events.on("groups:change",onNodeChange);
+
+ RED.events.on("view:selection-changed", onSelectionChanged);
+
+ RED.events.on("workspace:clear", onWorkspaceClear)
+
+ return container;
+ }
+ function onWorkspaceClear() {
+ treeList.treeList('data',getFlowData());
+ }
+ function onFlowAdd(ws) {
+ objects[ws.id] = {
+ id: ws.id,
+ element: getFlowLabel(ws),
+ children:[],
+ deferBuild: true,
+ icon: "red-ui-icons red-ui-icons-flow",
+ gutter: getGutter(ws)
+ }
+ if (missingParents[ws.id]) {
+ objects[ws.id].children = missingParents[ws.id];
+ delete missingParents[ws.id]
+ } else {
+ objects[ws.id].children.push(getEmptyItem(ws.id));
+ }
+ flowList.treeList.addChild(objects[ws.id])
+ objects[ws.id].element.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
+ objects[ws.id].treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
+
+
+ }
+ function onFlowChange(n) {
+ var existingObject = objects[n.id];
+
+ var label = n.label || n.id;
+ var newlineIndex = label.indexOf("\\n");
+ if (newlineIndex > -1) {
+ label = label.substring(0,newlineIndex)+"...";
+ }
+ existingObject.element.find(".red-ui-info-outline-item-label").text(label);
+ existingObject.element.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled)
+ existingObject.treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled)
+ }
+ function onFlowsReorder(order) {
+ var indexMap = {};
+ order.forEach(function(id,index) {
+ indexMap[id] = index;
+ })
+
+ flowList.treeList.sortChildren(function(A,B) {
+ if (A.id === "__global__") { return -1 }
+ if (B.id === "__global__") { return 1 }
+ return indexMap[A.id] - indexMap[B.id]
+ })
+ }
+ function onSubflowAdd(sf) {
+ objects[sf.id] = {
+ id: sf.id,
+ element: getNodeLabel(sf),
+ children:[],
+ deferBuild: true,
+ gutter: getGutter(sf)
+ }
+ if (missingParents[sf.id]) {
+ objects[sf.id].children = missingParents[sf.id];
+ delete missingParents[sf.id]
+ } else {
+ objects[sf.id].children.push(getEmptyItem(sf.id));
+ }
+ subflowList.treeList.addChild(objects[sf.id])
+ }
+ function onSubflowChange(sf) {
+ var existingObject = objects[sf.id];
+ existingObject.treeList.replaceElement(getNodeLabel(sf));
+ // existingObject.element.find(".red-ui-info-outline-item-label").text(n.name || n.id);
+ RED.nodes.eachNode(function(n) {
+ if (n.type == "subflow:"+sf.id) {
+ var sfInstance = objects[n.id];
+ sfInstance.treeList.replaceElement(getNodeLabel(n));
+ }
+ });
+ }
+
+ function onNodeChange(n) {
+ var existingObject = objects[n.id];
+ var parent = n.g||n.z;
+
+ var nodeLabelText = getNodeLabelText(n);
+ if (nodeLabelText) {
+ existingObject.element.find(".red-ui-info-outline-item-label").text(nodeLabelText);
+ } else {
+ existingObject.element.find(".red-ui-info-outline-item-label").html(" ");
+ }
+
+ if (parent !== existingObject.parent.id) {
+ existingObject.treeList.remove();
+ if (!parent) {
+ globalConfigNodes.treeList.addChild(existingObject);
+ } else {
+ if (empties[parent]) {
+ empties[parent].treeList.remove();
+ delete empties[parent];
+ }
+ objects[parent].treeList.addChild(existingObject)
+ }
+ }
+ existingObject.element.toggleClass("red-ui-info-outline-item-disabled", !!n.d)
+ }
+ function onObjectRemove(n) {
+ var existingObject = objects[n.id];
+ existingObject.treeList.remove();
+ delete objects[n.id]
+ var parent = existingObject.parent;
+ if (parent.children.length === 0) {
+ parent.treeList.addChild(getEmptyItem(parent.id));
+ }
+ if (existingObject.children && (existingObject.children.length > 0)) {
+ existingObject.children.forEach(function (nc) {
+ if (!nc.empty) {
+ var childObject = objects[nc.id];
+ nc.parent = parent;
+ objects[parent.id].treeList.addChild(childObject);
+ }
+ });
+ }
+ }
+ function getGutter(n) {
+ var span = $("
",{class:"red-ui-info-outline-gutter"});
+ $('').appendTo(span).on("click",function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ RED.view.reveal(n.id);
+ })
+ return span;
+ }
+ function onNodeAdd(n) {
+ objects[n.id] = {
+ id: n.id,
+ element: getNodeLabel(n),
+ gutter: getGutter(n)
+ }
+ if (n.type === "group") {
+ objects[n.id].children = [];
+ objects[n.id].deferBuild = true;
+ if (missingParents[n.id]) {
+ objects[n.id].children = missingParents[n.id];
+ delete missingParents[n.id]
+ }
+ }
+ var parent = n.g||n.z;
+ if (parent) {
+ if (objects[parent]) {
+ if (empties[parent]) {
+ empties[parent].treeList.remove();
+ delete empties[parent];
+ }
+ if (objects[parent].treeList) {
+ objects[parent].treeList.addChild(objects[n.id]);
+ } else {
+ objects[parent].children.push(objects[n.id])
+ }
+ } else {
+ missingParents[parent] = missingParents[parent]||[];
+ missingParents[parent].push(objects[n.id])
+ }
+ } else {
+ // No parent - add to Global flow list
+ globalConfigNodes.treeList.addChild(objects[n.id])
+ }
+ objects[n.id].element.toggleClass("red-ui-info-outline-item-disabled", !!n.d)
+ }
+
+ function onSelectionChanged(selection) {
+ // treeList.treeList('clearSelection');
+ }
+
+ return {
+ build: build,
+ search: function(val) {
+ searchInput.searchBox('value',val)
+ },
+ select: function(node) {
+ if (node) {
+ if (Array.isArray(node)) {
+ treeList.treeList('select', node.map(function(n) { return objects[n.id] }), false)
+ } else {
+ treeList.treeList('select', objects[node.id], false)
+
+ }
+ } else {
+ treeList.treeList('clearSelection')
+ }
+ },
+ reveal: function(node) {
+ treeList.treeList('show', objects[node.id])
+ }
+ }
+})();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js
index bfa4e4b23..418939a72 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js
@@ -16,16 +16,32 @@
RED.sidebar.info = (function() {
var content;
- var sections;
- var propertiesSection;
+ var panels;
var infoSection;
- var helpSection;
+
+ var propertiesPanelContent;
+ var propertiesPanelHeader;
+ var propertiesPanelHeaderIcon;
+ var propertiesPanelHeaderLabel;
+ var propertiesPanelHeaderReveal;
+ var propertiesPanelHeaderHelp;
+
+ var selectedObject;
+
+ var tipContainer;
var tipBox;
+ // TODO: remove this
var expandedSections = {
"property": false
};
+ function resizeStack() {
+ if (panels) {
+ var h = $(content).parent().height() - tipContainer.outerHeight();
+ panels.resize(h)
+ }
+ }
function init() {
content = document.createElement("div");
@@ -35,31 +51,79 @@ RED.sidebar.info = (function() {
var stackContainer = $("",{class:"red-ui-sidebar-info-stack"}).appendTo(content);
- sections = RED.stack.create({
- container: stackContainer
- }).hide();
+ var outlinerPanel = $("
").css({
+ "overflow": "hidden",
+ "height": "calc(70%)"
+ }).appendTo(stackContainer);
+ var propertiesPanel = $("
").css({
+ "overflow":"hidden",
+ "height":"100%",
+ "display": "flex",
+ "flex-direction": "column"
+ }).appendTo(stackContainer);
+ propertiesPanelHeader = $("
", {class:"red-ui-palette-header red-ui-info-header"}).css({
+ "flex":"0 0 auto"
+ }).appendTo(propertiesPanel);
- propertiesSection = sections.add({
- title: RED._("sidebar.info.info"),
- collapsible: true
+ propertiesPanelHeaderIcon = $("
").appendTo(propertiesPanelHeader);
+ propertiesPanelHeaderLabel = $("").appendTo(propertiesPanelHeader);
+ propertiesPanelHeaderHelp = $('').css({
+ position: 'absolute',
+ top: '12px',
+ right: '32px'
+ }).on("click", function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (selectedObject) {
+ RED.sidebar.help.show(selectedObject.type);
+ }
+ }).appendTo(propertiesPanelHeader);
+ RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp"));
+
+
+ propertiesPanelHeaderReveal = $('').css({
+ position: 'absolute',
+ top: '12px',
+ right: '8px'
+ }).on("click", function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (selectedObject) {
+ RED.sidebar.info.outliner.reveal(selectedObject);
+ RED.view.reveal(selectedObject.id);
+ }
+ }).appendTo(propertiesPanelHeader);
+ RED.popover.tooltip(propertiesPanelHeaderReveal,RED._("sidebar.help.showInOutline"));
+
+
+ propertiesPanelContent = $("").css({
+ "flex":"1 1 auto",
+ "overflow-y":"scroll",
+ }).appendTo(propertiesPanel);
+
+
+ panels = RED.panels.create({container: stackContainer})
+ panels.ratio(0.6);
+ RED.sidebar.info.outliner.build().appendTo(outlinerPanel);
+
+
+ RED.sidebar.addTab({
+ id: "info",
+ label: RED._("sidebar.info.label"),
+ name: RED._("sidebar.info.name"),
+ iconClass: "fa fa-info",
+ action:"core:show-info-tab",
+ content: content,
+ pinned: true,
+ enableOnEdit: true
});
- propertiesSection.expand();
- infoSection = sections.add({
- title: RED._("sidebar.info.desc"),
- collapsible: true
- });
- infoSection.expand();
- infoSection.content.css("padding","6px");
+ $(window).on("resize", resizeStack);
+ $(window).on("focus", resizeStack);
- helpSection = sections.add({
- title: RED._("sidebar.info.nodeHelp"),
- collapsible: true
- });
- helpSection.expand();
- helpSection.content.css("padding","6px");
- var tipContainer = $('
').appendTo(content);
+ // Tip Box
+ tipContainer = $('
').appendTo(content);
tipBox = $('
').appendTo(tipContainer);
var tipButtons = $('
').appendTo(tipContainer);
@@ -75,17 +139,6 @@ RED.sidebar.info = (function() {
RED.actions.invoke("core:toggle-show-tips");
RED.notify(RED._("sidebar.info.showTips"));
});
-
- RED.sidebar.addTab({
- id: "info",
- label: RED._("sidebar.info.label"),
- name: RED._("sidebar.info.name"),
- iconClass: "fa fa-info",
- action:"core:show-info-tab",
- content: content,
- pinned: true,
- enableOnEdit: true
- });
if (tips.enabled()) {
tips.start();
} else {
@@ -113,46 +166,36 @@ RED.sidebar.info = (function() {
refreshSelection();
return;
}
- sections.show();
- $(propertiesSection.content).empty();
- $(infoSection.content).empty();
- $(helpSection.content).empty();
- infoSection.title.text(RED._("sidebar.info.desc"));
+ $(propertiesPanelContent).empty();
var propRow;
- var table = $('
').appendTo(propertiesSection.content);
+ var table = $('
').appendTo(propertiesPanelContent);
var tableBody = $('
').appendTo(table);
var subflowNode;
var subflowUserCount;
- var activeProject = RED.projects.getActiveProject();
- if (activeProject) {
- propRow = $(''+ RED._("sidebar.project.name") + ' | |
').appendTo(tableBody);
- $(propRow.children()[1]).text(activeProject.name||"");
- $(' |
').appendTo(tableBody);
- var editProjectButton = $('')
- .appendTo(propRow.children()[1])
- .on("click", function(evt) {
- evt.preventDefault();
- RED.projects.editProject();
- });
- RED.popover.tooltip(editProjectButton,RED._('sidebar.project.showProjectSettings'));
- }
- propertiesSection.container.show();
- infoSection.container.show();
- helpSection.container.show();
if (node === null) {
+ RED.sidebar.info.outliner.select(null);
return;
} else if (Array.isArray(node)) {
// Multiple things selected
// - hide help and info sections
+ RED.sidebar.info.outliner.select(node);
+
+ propertiesPanelHeaderIcon.empty();
+ RED.utils.createNodeIcon({type:"_selection_"}).appendTo(propertiesPanelHeaderIcon);
+ propertiesPanelHeaderLabel.text("Selection");
+ propertiesPanelHeaderReveal.hide();
+ propertiesPanelHeaderHelp.hide();
+ selectedObject = null;
var types = {
nodes:0,
flows:0,
- subflows:0
+ subflows:0,
+ groups: 0
}
node.forEach(function(n) {
if (n.type === 'tab') {
@@ -160,12 +203,13 @@ RED.sidebar.info = (function() {
types.nodes += RED.nodes.filterNodes({z:n.id}).length;
} else if (n.type === 'subflow') {
types.subflows++;
+ } else if (n.type === 'group') {
+ types.groups++;
} else {
types.nodes++;
}
});
- helpSection.container.hide();
- infoSection.container.hide();
+ // infoSection.container.hide();
// - show the count of selected nodes
propRow = $(''+RED._("sidebar.info.selection")+" | |
").appendTo(tableBody);
@@ -179,14 +223,19 @@ RED.sidebar.info = (function() {
if (types.nodes > 0) {
$('').text(RED._("clipboard.node",{count:types.nodes})).appendTo(counts);
}
+ if (types.groups > 0) {
+ $('
').text(RED._("clipboard.group",{count:types.groups})).appendTo(counts);
+ }
} else {
// A single 'thing' selected.
+ RED.sidebar.info.outliner.select(node);
+
// Check to see if this is a subflow or subflow instance
- var m = /^subflow(:(.+))?$/.exec(node.type);
- if (m) {
- if (m[2]) {
- subflowNode = RED.nodes.subflow(m[2]);
+ var subflowRegex = /^subflow(:(.+))?$/.exec(node.type);
+ if (subflowRegex) {
+ if (subflowRegex[2]) {
+ subflowNode = RED.nodes.subflow(subflowRegex[2]);
} else {
subflowNode = node;
}
@@ -199,33 +248,76 @@ RED.sidebar.info = (function() {
}
});
}
+
+ propertiesPanelHeaderIcon.empty();
+ RED.utils.createNodeIcon(node).appendTo(propertiesPanelHeaderIcon);
+ var objectLabel = RED.utils.getNodeLabel(node, node.type+": "+node.id)
+ var newlineIndex = objectLabel.indexOf("\\n");
+ if (newlineIndex > -1) {
+ objectLabel = objectLabel.substring(0,newlineIndex)+"...";
+ }
+ propertiesPanelHeaderLabel.text(objectLabel);
+ propertiesPanelHeaderReveal.show();
+ selectedObject = node;
+
+ propRow = $('
| |
').appendTo(tableBody);
+ var objectType = "node";
+ if (node.type === "subflow" || subflowRegex) {
+ objectType = "subflow";
+ } else if (node.type === "tab") {
+ objectType = "flow";
+ }else if (node.type === "group") {
+ objectType = "group";
+ }
+ $(propRow.children()[0]).text(RED._("sidebar.info."+objectType))
+ RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
+
if (node.type === "tab" || node.type === "subflow") {
// If nothing is selected, but we're on a flow or subflow tab.
- propRow = $('
'+RED._("sidebar.info."+(node.type==='tab'?'flow':'subflow'))+' | |
').appendTo(tableBody);
- RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
- propRow = $('
'+RED._("sidebar.info.tabName")+" | |
").appendTo(tableBody);
- $(propRow.children()[1]).text(node.label||node.name||"");
- if (node.type === "tab") {
- propRow = $('
'+RED._("sidebar.info.status")+' | |
').appendTo(tableBody);
- $(propRow.children()[1]).text((!!!node.disabled)?RED._("sidebar.info.enabled"):RED._("sidebar.info.disabled"))
+ propertiesPanelHeaderHelp.hide();
+
+ } else if (node.type === "group") {
+ propertiesPanelHeaderHelp.hide();
+
+ propRow = $('
| |
').appendTo(tableBody);
+
+ var typeCounts = {
+ nodes:0,
+ groups: 0
}
+ var allNodes = RED.group.getNodes(node,true);
+ allNodes.forEach(function(n) {
+ if (n.type === "group") {
+ typeCounts.groups++;
+ } else {
+ typeCounts.nodes++
+ }
+ });
+ var counts = $('
').appendTo($(propRow.children()[1]));
+ if (typeCounts.nodes > 0) {
+ $('
').text(RED._("clipboard.node",{count:typeCounts.nodes})).appendTo(counts);
+ }
+ if (typeCounts.groups > 0) {
+ $('
').text(RED._("clipboard.group",{count:typeCounts.groups})).appendTo(counts);
+ }
+
+
} else {
- // An actual node is selected in the editor - build up its properties table
- propRow = $('
'+RED._("sidebar.info.node")+" | |
").appendTo(tableBody);
- RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
- if (node.type !== "subflow" && node.type !== "unknown" && node.name) {
- propRow = $('
'+RED._("common.label.name")+' | |
').appendTo(tableBody);
- $('
').text(node.name).appendTo(propRow.children()[1]);
- }
- if (!m) {
- propRow = $('
'+RED._("sidebar.info.type")+" | |
").appendTo(tableBody);
+ propertiesPanelHeaderHelp.show();
+
+ if (!subflowRegex) {
+ propRow = $('
'+RED._("sidebar.info.type")+' | |
').appendTo(tableBody);
$(propRow.children()[1]).text((node.type === "unknown")?node._orig.type:node.type);
if (node.type === "unknown") {
$('
').prependTo($(propRow.children()[1]))
}
}
+
var count = 0;
- if (!m && node.type != "subflow") {
+ if (!subflowRegex && node.type != "subflow" && node.type != "group") {
+
+ var blankRow = $('
|
').appendTo(tableBody);
+
var defaults;
if (node.type === 'unknown') {
defaults = {};
@@ -240,7 +332,6 @@ RED.sidebar.info = (function() {
$(propRow.children()[1]).text(RED.nodes.getType(node.type).set.module);
count++;
}
- $('
|
').appendTo(tableBody);
if (defaults) {
for (var n in defaults) {
@@ -248,7 +339,8 @@ RED.sidebar.info = (function() {
var val = node[n];
var type = typeof val;
count++;
- propRow = $('
'+n+" | |
").appendTo(tableBody);
+ propRow = $('
| |
').appendTo(tableBody);
+ $(propRow.children()[0]).text(n);
if (defaults[n].type) {
var configNode = RED.nodes.node(val);
if (!configNode) {
@@ -278,37 +370,35 @@ RED.sidebar.info = (function() {
}
}
if (count > 0) {
- $('
'+RED._("sidebar.info.showMore")+''+RED._("sidebar.info.showLess")+' |
').appendTo(tableBody);
+ $('
'+RED._("sidebar.info.showMore")+''+RED._("sidebar.info.showLess")+' ').appendTo(blankRow.children()[0]);
}
}
if (node.type !== 'tab') {
- if (m) {
+ if (subflowRegex) {
$('
'+RED._("sidebar.info.subflow")+' |
---|
').appendTo(tableBody);
$('
'+RED._("common.label.name")+' | '+RED.utils.sanitize(subflowNode.name)+' |
').appendTo(tableBody);
}
}
}
- if (m) {
+ if (subflowRegex) {
propRow = $('
'+RED._("subflow.category")+' | |
').appendTo(tableBody);
var category = subflowNode.category||"subflows";
$(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category}))
$('
'+RED._("sidebar.info.instances")+" | "+subflowUserCount+' |
').appendTo(tableBody);
}
- var helpText = "";
- if (node.type === "tab" || node.type === "subflow") {
- $(helpSection.container).hide();
- } else {
- $(helpSection.container).show();
- if (subflowNode && node.type !== "subflow") {
- // Selected a subflow instance node.
- // - The subflow template info goes into help
- helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('
'+RED._("sidebar.info.none")+''));
- } else {
- helpText = $("script[data-help-name='"+node.type+"']").html()||('
'+RED._("sidebar.info.none")+'');
- }
- setInfoText(helpText, helpSection.content);
- }
+ // var helpText = "";
+ // if (node.type === "tab" || node.type === "subflow") {
+ // } else {
+ // if (subflowNode && node.type !== "subflow") {
+ // // Selected a subflow instance node.
+ // // - The subflow template info goes into help
+ // helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('
'+RED._("sidebar.info.none")+''));
+ // } else {
+ // helpText = $("script[data-help-name='"+node.type+"']").html()||('
'+RED._("sidebar.info.none")+'');
+ // }
+ // setInfoText(helpText, helpSection.content);
+ // }
var infoText = "";
@@ -320,7 +410,26 @@ RED.sidebar.info = (function() {
if (node.info) {
infoText = infoText + RED.utils.renderMarkdown(node.info || "")
}
- setInfoText(infoText, infoSection.content);
+ var infoSectionContainer = $("
").css("padding","0 6px 6px").appendTo(propertiesPanelContent)
+
+ // var editInfo = $('
').appendTo(infoSectionContainer).on("click", function(evt) {
+ // //.text(RED._("sidebar.info.editDescription"))
+ // evt.preventDefault();
+ // evt.stopPropagation();
+ // if (node.type === 'tab') {
+ //
+ // } else if (node.type === 'subflow') {
+ //
+ // } else if (node.type === 'group') {
+ //
+ // } else if (node._def.category !== 'config') {
+ // RED.editor.edit(node,"editor-tab-description");
+ // } else {
+ //
+ // }
+ // })
+
+ setInfoText(infoText, infoSectionContainer);
$(".red-ui-sidebar-info-stack").scrollTop(0);
$(".node-info-property-header").on("click", function(e) {
@@ -336,7 +445,7 @@ RED.sidebar.info = (function() {
// propRow = $('
Actions | |
').appendTo(tableBody);
// var actionBar = $(propRow.children()[1]);
//
- // // var actionBar = $('
',{style:"background: #fefefe; padding: 3px;"}).appendTo(propertiesSection.content);
+ // // var actionBar = $('
',{style:"background: #fefefe; padding: 3px;"}).appendTo(propertiesPanel);
// $('
').appendTo(actionBar);
// $('
').appendTo(actionBar);
// $('
').appendTo(actionBar);
@@ -411,6 +520,7 @@ RED.sidebar.info = (function() {
}
function startTips() {
$(".red-ui-sidebar-info").addClass('show-tips');
+ resizeStack();
if (enabled) {
if (!startTimeout && !refreshTimeout) {
if (tipCount === -1) {
@@ -424,6 +534,7 @@ RED.sidebar.info = (function() {
}
function stopTips() {
$(".red-ui-sidebar-info").removeClass('show-tips');
+ resizeStack();
clearInterval(refreshTimeout);
clearTimeout(startTimeout);
refreshTimeout = null;
@@ -448,15 +559,8 @@ RED.sidebar.info = (function() {
}
function set(html,title) {
- // tips.stop();
- // sections.show();
- refresh(null);
- propertiesSection.container.hide();
- helpSection.container.hide();
- infoSection.container.show();
- infoSection.title.text(title||RED._("sidebar.info.desc"));
- setInfoText(html,infoSection.content);
- $(".red-ui-sidebar-info-stack").scrollTop(0);
+ console.warn("Deprecated use of RED.sidebar.info.set - use RED.sidebar.help.set instead")
+ RED.sidebar.help.set(html,title);
}
function refreshSelection(selection) {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index a9c1c9500..e8306bd0f 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -806,9 +806,9 @@ RED.utils = (function() {
function separateIconPath(icon) {
var result = {module: "", file: ""};
if (icon) {
- var index = icon.indexOf('icons/');
- if (index !== -1) {
- icon = icon.substring(index+6);
+ var index = icon.indexOf(RED.settings.apiRootUrl+'icons/');
+ if (index === 0) {
+ icon = icon.substring((RED.settings.apiRootUrl+'icons/').length);
}
index = icon.indexOf('/');
if (index !== -1) {
@@ -859,10 +859,15 @@ RED.utils = (function() {
}
function getNodeIcon(def,node) {
- if (def.category === 'config') {
+ if (node && node.type === '_selection_') {
+ return "font-awesome/fa-object-ungroup";
+ } else if (node && node.type === 'group') {
+ return "font-awesome/fa-object-group"
+ } else if (def.category === 'config') {
return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
} else if (node && node.type === 'tab') {
- return RED.settings.apiRootUrl+"icons/node-red/subflow.svg"
+ return "red-ui-icons/red-ui-icons-flow"
+ // return RED.settings.apiRootUrl+"images/subflow_tab.svg"
} else if (node && node.type === 'unknown') {
return RED.settings.apiRootUrl+"icons/node-red/alert.svg"
} else if (node && node.icon) {
@@ -921,6 +926,8 @@ RED.utils = (function() {
var l;
if (node.type === 'tab') {
l = node.label || defaultLabel
+ } else if (node.type === 'group') {
+ l = node.name || defaultLabel
} else {
l = node._def.label;
try {
@@ -1054,11 +1061,63 @@ RED.utils = (function() {
}
// If the specified name is not defined in font-awesome, show arrow-in icon.
iconUrl = RED.settings.apiRootUrl+"icons/node-red/arrow-in.svg"
+ } else if (iconPath.module === "red-ui-icons") {
+ var redIconElement = $('
').appendTo(iconContainer);
+ redIconElement.addClass("red-ui-palette-icon red-ui-icons " + iconPath.file);
+ return;
}
var imageIconElement = $('
',{class:"red-ui-palette-icon"}).appendTo(iconContainer);
imageIconElement.css("backgroundImage", "url("+iconUrl+")");
}
+ function createNodeIcon(node) {
+ var def = node._def;
+ var nodeDiv = $('
',{class:"red-ui-search-result-node"})
+ if (node.type === "_selection_") {
+ nodeDiv.addClass("red-ui-palette-icon-selection");
+ } else if (node.type === "group") {
+ nodeDiv.addClass("red-ui-palette-icon-group");
+ } else if (node.type === 'tab') {
+ nodeDiv.addClass("red-ui-palette-icon-flow");
+ } else {
+ var colour = RED.utils.getNodeColor(node.type,def);
+ // if (node.type === 'tab') {
+ // colour = "#C0DEED";
+ // }
+ nodeDiv.css('backgroundColor',colour);
+ var borderColor = getDarkerColor(colour);
+ if (borderColor !== colour) {
+ nodeDiv.css('border-color',borderColor)
+ }
+ }
+
+ var icon_url = RED.utils.getNodeIcon(def,node);
+ var iconContainer = $('
',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
+ RED.utils.createIconElement(icon_url, iconContainer, true);
+ return nodeDiv;
+ }
+
+ function getDarkerColor(c) {
+ var r,g,b;
+ if (/^#[a-f0-9]{6}$/i.test(c)) {
+ r = parseInt(c.substring(1, 3), 16);
+ g = parseInt(c.substring(3, 5), 16);
+ b = parseInt(c.substring(5, 7), 16);
+ } else if (/^#[a-f0-9]{3}$/i.test(c)) {
+ r = parseInt(c.substring(1, 2)+c.substring(1, 2), 16);
+ g = parseInt(c.substring(2, 3)+c.substring(2, 3), 16);
+ b = parseInt(c.substring(3, 4)+c.substring(3, 4), 16);
+ } else {
+ return c;
+ }
+ var l = 0.3 * r/255 + 0.59 * g/255 + 0.11 * b/255 ;
+ r = Math.max(0,r-50);
+ g = Math.max(0,g-50);
+ b = Math.max(0,b-50);
+ var s = ((r<<16) + (g<<8) + b).toString(16);
+ return '#'+'000000'.slice(0, 6-s.length)+s;
+ }
+
return {
createObjectElement: buildMessageElement,
getMessageProperty: getMessageProperty,
@@ -1076,6 +1135,8 @@ RED.utils = (function() {
parseContextKey: parseContextKey,
createIconElement: createIconElement,
sanitize: sanitize,
- renderMarkdown: renderMarkdown
+ renderMarkdown: renderMarkdown,
+ createNodeIcon: createNodeIcon,
+ getDarkerColor: getDarkerColor
}
})();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
index 0814892be..631e7ec1e 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
@@ -67,9 +67,16 @@ RED.view.tools = (function() {
function moveSelection(dx,dy) {
if (moving_set === null) {
+ moving_set = [];
var selection = RED.view.selection();
if (selection.nodes) {
- moving_set = selection.nodes.map(function(n) { return {n:n}});
+ while (selection.nodes.length > 0) {
+ var n = selection.nodes.shift();
+ moving_set.push({n:n});
+ if (n.type === "group") {
+ selection.nodes = selection.nodes.concat(n.nodes);
+ }
+ }
}
}
if (moving_set && moving_set.length > 0) {
@@ -93,6 +100,9 @@ RED.view.tools = (function() {
node.n.x += dx;
node.n.y += dy;
node.n.dirty = true;
+ if (node.n.type === "group") {
+ RED.group.markDirty(node.n);
+ }
minX = Math.min(node.n.x-node.n.w/2-5,minX);
minY = Math.min(node.n.y-node.n.h/2-5,minY);
}
@@ -105,13 +115,86 @@ RED.view.tools = (function() {
}
}
RED.view.redraw();
+ } else {
+ RED.view.scroll(dx*10,dy*10);
}
}
+ function setSelectedNodeLabelState(labelShown) {
+ var selection = RED.view.selection();
+ var historyEvents = [];
+ var nodes = [];
+ if (selection.nodes) {
+ selection.nodes.forEach(function(n) {
+ if (n.type !== 'subflow' && n.type !== 'group') {
+ nodes.push(n);
+ } else if (n.type === 'group') {
+ nodes = nodes.concat( RED.group.getNodes(n,true));
+ }
+ });
+ }
+ nodes.forEach(function(n) {
+ var modified = false;
+ var oldValue = n.l === undefined?true:n.l;
+ var isLink = /^link (in|out)$/.test(n._def.type);
+
+ if (labelShown) {
+ if (n.l === false || (isLink && !n.hasOwnProperty('l'))) {
+ n.l = true;
+ modified = true;
+ }
+ } else {
+ if ((!isLink && (!n.hasOwnProperty('l') || n.l === true)) || (isLink && n.l === true) ) {
+ n.l = false;
+ modified = true;
+ }
+ }
+ if (modified) {
+ historyEvents.push({
+ t: "edit",
+ node: n,
+ changed: n.changed,
+ changes: {
+ l: oldValue
+ }
+ })
+ n.changed = true;
+ n.dirty = true;
+ n.resize = 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: function() {
+ RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
+ RED.actions.add("core:hide-selected-node-labels", function() { setSelectedNodeLabelState(false); })
+
RED.actions.add("core:align-selection-to-grid", alignToGrid);
+ RED.actions.add("core:scroll-view-up", function() { RED.view.scroll(0,-RED.view.gridSize());});
+ RED.actions.add("core:scroll-view-right", function() { RED.view.scroll(RED.view.gridSize(),0);});
+ RED.actions.add("core:scroll-view-down", function() { RED.view.scroll(0,RED.view.gridSize());});
+ RED.actions.add("core:scroll-view-left", function() { RED.view.scroll(-RED.view.gridSize(),0);});
+
+ RED.actions.add("core:step-view-up", function() { RED.view.scroll(0,-5*RED.view.gridSize());});
+ RED.actions.add("core:step-view-right", function() { RED.view.scroll(5*RED.view.gridSize(),0);});
+ RED.actions.add("core:step-view-down", function() { RED.view.scroll(0,5*RED.view.gridSize());});
+ RED.actions.add("core:step-view-left", function() { RED.view.scroll(-5*RED.view.gridSize(),0);});
+
RED.actions.add("core:move-selection-up", function() { moveSelection(0,-1);});
RED.actions.add("core:move-selection-right", function() { moveSelection(1,0);});
RED.actions.add("core:move-selection-down", function() { moveSelection(0,1);});
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
index 80a9432f7..7f541204e 100755
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
@@ -21,12 +21,15 @@
* \-
.red-ui-workspace-chart-event-layer "eventLayer"
* |- .red-ui-workspace-chart-background
* |- .red-ui-workspace-chart-grid "gridLayer"
+ * |- "groupLayer"
+ * |- "groupSelectLayer"
* |- "linkLayer"
* |- "dragGroupLayer"
- * \- "nodeLayer"
+ * |- "nodeLayer"
*/
RED.view = (function() {
+ var DEBUG_EVENTS = false;
var space_width = 5000,
space_height = 5000,
lineCurveScale = 0.75,
@@ -48,34 +51,42 @@ RED.view = (function() {
var activeSpliceLink;
var spliceActive = false;
var spliceTimer;
+ var groupHoverTimer;
var activeSubflow = null;
var activeNodes = [];
var activeLinks = [];
var activeFlowLinks = [];
var activeLinkNodes = {};
+ var activeGroup = null;
+ var activeHoverGroup = null;
+ var activeGroups = [];
+ var dirtyGroups = {};
- var selected_link = null,
- mousedown_link = null,
- mousedown_node = null,
- mousedown_port_type = null,
- mousedown_port_index = 0,
- mouseup_node = null,
- mouse_offset = [0,0],
- mouse_position = null,
- mouse_mode = 0,
- moving_set = [],
- lasso = null,
- ghostNode = null,
- showStatus = false,
- lastClickNode = null,
- dblClickPrimed = null,
- clickTime = 0,
- clickElapsed = 0,
- scroll_position = [],
- quickAddActive = false,
- quickAddLink = null,
- showAllLinkPorts = -1;
+ var selected_link = null;
+ var mousedown_link = null;
+ var mousedown_node = null;
+ var mousedown_group = null;
+ var mousedown_port_type = null;
+ var mousedown_port_index = 0;
+ var mouseup_node = null;
+ var mouse_offset = [0,0];
+ var mouse_position = null;
+ var mouse_mode = 0;
+ var mousedown_group_handle = null;
+ var moving_set = [];
+ var lasso = null;
+ var ghostNode = null;
+ var showStatus = false;
+ var lastClickNode = null;
+ var dblClickPrimed = null;
+ var clickTime = 0;
+ var clickElapsed = 0;
+ var scroll_position = [];
+ var quickAddActive = false;
+ var quickAddLink = null;
+ var showAllLinkPorts = -1;
+ var groupNodeSelectPrimed = false;
var selectNodesOptions;
@@ -100,7 +111,9 @@ RED.view = (function() {
var gridLayer;
var linkLayer;
var dragGroupLayer;
+ var groupSelectLayer;
var nodeLayer;
+ var groupLayer;
var drag_lines;
function init() {
@@ -253,9 +266,12 @@ RED.view = (function() {
gridLayer = eventLayer.append("g").attr("class","red-ui-workspace-chart-grid");
updateGrid();
+ groupLayer = eventLayer.append("g");
+ groupSelectLayer = eventLayer.append("g");
linkLayer = eventLayer.append("g");
dragGroupLayer = eventLayer.append("g");
nodeLayer = eventLayer.append("g");
+
drag_lines = [];
RED.events.on("workspace:change",function(event) {
@@ -377,14 +393,36 @@ RED.view = (function() {
historyEvent.removedLinks = [spliceLink];
}
- RED.history.push(historyEvent);
RED.nodes.add(nn);
+
+ var group = $(ui.helper).data("group");
+ if (group) {
+ RED.group.addToGroup(group, nn);
+ historyEvent = {
+ t: 'multi',
+ events: [historyEvent],
+
+ }
+ historyEvent.events.push({
+ t: "addToGroup",
+ group: group,
+ nodes: nn
+ })
+ }
+
+ RED.history.push(historyEvent);
RED.editor.validateNode(nn);
RED.nodes.dirty(true);
// auto select dropped node - so info shows (if visible)
+ exitActiveGroup();
clearSelection();
nn.selected = true;
moving_set.push({n:nn});
+ if (group) {
+ selectGroup(group,false);
+ enterActiveGroup(group);
+ activeGroup = group;
+ }
updateActiveNodes();
updateSelection();
redraw();
@@ -517,6 +555,53 @@ RED.view = (function() {
source:{z:activeWorkspace},
target:{z:activeWorkspace}
});
+
+ activeGroups = RED.nodes.groups(activeWorkspace)||[];
+ activeGroups.forEach(function(g) {
+ if (g.g) {
+ g._root = g.g;
+ g._depth = 1;
+ } else {
+ g._root = g.id;
+ g._depth = 0;
+ }
+ });
+ var changed = false;
+ do {
+ changed = false;
+ activeGroups.forEach(function(g) {
+ if (g.g) {
+ var parentGroup = RED.nodes.group(g.g);
+ if (parentGroup) {
+ var parentDepth = parentGroup._depth;
+ if (g._depth !== parentDepth + 1) {
+ g._depth = parentDepth + 1;
+ changed = true;
+ }
+ if (g._root !== parentGroup._root) {
+ g._root = parentGroup._root;
+ changed = true;
+ }
+ }
+ }
+ });
+ } while (changed)
+ activeGroups.sort(function(a,b) {
+ if (a._root === b._root) {
+ return a._depth - b._depth;
+ } else {
+ return a._root.localeCompare(b._root);
+ }
+ });
+
+ var group = groupLayer.selectAll(".red-ui-flow-group").data(activeGroups,function(d) { return d.id });
+ group.sort(function(a,b) {
+ if (a._root === b._root) {
+ return a._depth - b._depth;
+ } else {
+ return a._root.localeCompare(b._root);
+ }
+ })
}
function generateLinkPath(origX,origY, destX, destY, sc) {
@@ -671,6 +756,7 @@ RED.view = (function() {
}
function canvasMouseDown() {
+if (DEBUG_EVENTS) { console.warn("canvasMouseDown", mouse_mode); }
var point;
if (mouse_mode === RED.state.SELECTING_NODE) {
d3.event.stopPropagation();
@@ -684,7 +770,7 @@ RED.view = (function() {
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
return;
}
- if (!mousedown_node && !mousedown_link) {
+ if (!mousedown_node && !mousedown_link && !mousedown_group) {
selected_link = null;
updateSelection();
}
@@ -697,7 +783,13 @@ RED.view = (function() {
if (mouse_mode === 0 || mouse_mode === RED.state.QUICK_JOINING) {
if (d3.event.metaKey || d3.event.ctrlKey) {
d3.event.stopPropagation();
- showQuickAddDialog(d3.mouse(this));
+ clearSelection();
+ point = d3.mouse(this);
+ var clickedGroup = getGroupAt(point[0],point[1]);
+ if (drag_lines.length > 0) {
+ clickedGroup = clickedGroup || RED.nodes.group(drag_lines[0].node.g)
+ }
+ showQuickAddDialog(point, null, clickedGroup);
}
}
if (mouse_mode === 0 && !(d3.event.metaKey || d3.event.ctrlKey)) {
@@ -718,7 +810,13 @@ RED.view = (function() {
}
}
- function showQuickAddDialog(point,spliceLink) {
+ function showQuickAddDialog(point, spliceLink, targetGroup) {
+ if (targetGroup && !targetGroup.active) {
+ selectGroup(targetGroup,false);
+ enterActiveGroup(targetGroup);
+ RED.view.redraw();
+ }
+
var ox = point[0];
var oy = point[1];
@@ -946,6 +1044,22 @@ RED.view = (function() {
}
}
}
+ if (targetGroup) {
+ RED.group.addToGroup(targetGroup, nn);
+ if (historyEvent.t !== "multi") {
+ historyEvent = {
+ t:'multi',
+ events: [historyEvent]
+ }
+ }
+ historyEvent.events.push({
+ t: "addToGroup",
+ group: targetGroup,
+ nodes: nn
+ })
+
+ }
+
if (spliceLink) {
resetMouseVars();
// TODO: DRY - droppable/nodeMouseDown/canvasMouseUp/showQuickAddDialog
@@ -972,6 +1086,10 @@ RED.view = (function() {
// auto select dropped node - so info shows (if visible)
clearSelection();
nn.selected = true;
+ if (targetGroup) {
+ selectGroup(targetGroup,false);
+ enterActiveGroup(targetGroup);
+ }
moving_set.push({n:nn});
updateActiveNodes();
updateSelection();
@@ -1076,11 +1194,23 @@ RED.view = (function() {
return;
}
- if (mouse_mode != RED.state.QUICK_JOINING && mouse_mode != RED.state.IMPORT_DRAGGING && !mousedown_node && selected_link == null) {
+ if (mouse_mode != RED.state.QUICK_JOINING && mouse_mode != RED.state.IMPORT_DRAGGING && !mousedown_node && !mousedown_group && selected_link == null) {
return;
}
var mousePos;
+ // if (mouse_mode === RED.state.GROUP_RESIZE) {
+ // mousePos = mouse_position;
+ // var nx = mousePos[0] + mousedown_group.dx;
+ // var ny = mousePos[1] + mousedown_group.dy;
+ // switch(mousedown_group.activeHandle) {
+ // case 0: mousedown_group.pos.x0 = nx; mousedown_group.pos.y0 = ny; break;
+ // case 1: mousedown_group.pos.x1 = nx; mousedown_group.pos.y0 = ny; break;
+ // case 2: mousedown_group.pos.x1 = nx; mousedown_group.pos.y1 = ny; break;
+ // case 3: mousedown_group.pos.x0 = nx; mousedown_group.pos.y1 = ny; break;
+ // }
+ // mousedown_group.dirty = true;
+ // }
if (mouse_mode == RED.state.JOINING || mouse_mode === RED.state.QUICK_JOINING) {
// update drag line
if (drag_lines.length === 0 && mousedown_port_type !== null) {
@@ -1182,10 +1312,18 @@ RED.view = (function() {
node.n.x = mousePos[0]+node.dx;
node.n.y = mousePos[1]+node.dy;
node.n.dirty = true;
- minX = Math.min(node.n.x-node.n.w/2-5,minX);
- minY = Math.min(node.n.y-node.n.h/2-5,minY);
- maxX = Math.max(node.n.x+node.n.w/2+5,maxX);
- maxY = Math.max(node.n.y+node.n.h/2+5,maxY);
+ if (node.n.type === "group") {
+ RED.group.markDirty(node.n);
+ minX = Math.min(node.n.x-5,minX);
+ minY = Math.min(node.n.y-5,minY);
+ maxX = Math.max(node.n.x+node.n.w+5,maxX);
+ maxY = Math.max(node.n.y+node.n.h+5,maxY);
+ } else {
+ minX = Math.min(node.n.x-node.n.w/2-5,minX);
+ minY = Math.min(node.n.y-node.n.h/2-5,minY);
+ maxX = Math.max(node.n.x+node.n.w/2+5,maxX);
+ maxY = Math.max(node.n.y+node.n.h/2+5,maxY);
+ }
}
if (minX !== 0 || minY !== 0) {
for (i = 0; i 0) {
- var gridOffset = [0,0];
- node = moving_set[0];
- gridOffset[0] = node.n.x-(gridSize*Math.floor((node.n.x-node.n.w/2)/gridSize)+node.n.w/2);
- gridOffset[1] = node.n.y-(gridSize*Math.floor(node.n.y/gridSize));
+ var i = 0;
+
+ // Prefer to snap nodes to the grid if there is one in the selection
+ do {
+ node = moving_set[i++];
+ } while(i x && n.x < x2 && n.y > y && n.y < y2);
- if (n.selected) {
- n.dirty = true;
- moving_set.push({n:n});
+ activeGroups.forEach(function(g) {
+ if (!g.selected) {
+ if (g.x > x && g.x+g.w < x2 && g.y > y && g.y+g.h < y2) {
+ while (g.g) {
+ g = RED.nodes.group(g.g);
+ }
+ if (!g.selected) {
+ selectGroup(g,true);
+ }
+ }
+ }
+ })
+
+ activeNodes.forEach(function(n) {
+ if (!n.selected) {
+ if (n.x > x && n.x < x2 && n.y > y && n.y < y2) {
+ if (n.g) {
+ var group = RED.nodes.group(n.g);
+ while (group.g) {
+ group = RED.nodes.group(group.g);
+ }
+ if (!group.selected) {
+ selectGroup(group,true);
+ }
+ } else {
+ n.selected = true;
+ n.dirty = true;
+ moving_set.push({n:n});
+ }
}
}
});
+
+
+
+ // var selectionChanged = false;
+ // do {
+ // selectionChanged = false;
+ // selectedGroups.forEach(function(g) {
+ // if (g.g && g.selected && RED.nodes.group(g.g).selected) {
+ // g.selected = false;
+ // selectionChanged = true;
+ // }
+ // })
+ // } while(selectionChanged);
+
if (activeSubflow) {
activeSubflow.in.forEach(function(n) {
n.selected = (n.x > x && n.x < x2 && n.y > y && n.y < y2);
@@ -1355,6 +1568,21 @@ RED.view = (function() {
}
if (mouse_mode == RED.state.MOVING_ACTIVE) {
if (moving_set.length > 0) {
+ var addedToGroup = null;
+ if (activeHoverGroup) {
+ for (var j=0;j 0) {
historyEvent = {t:"move",nodes:ns,dirty:RED.nodes.dirty()};
if (activeSpliceLink) {
@@ -1386,12 +1615,31 @@ RED.view = (function() {
historyEvent.removedLinks = [spliceLink];
updateActiveNodes();
}
+ if (addedToGroup) {
+ historyEvent.addToGroup = addedToGroup;
+ }
RED.nodes.dirty(true);
RED.history.push(historyEvent);
}
}
}
+ // if (mouse_mode === RED.state.MOVING && mousedown_node && mousedown_node.g) {
+ // if (mousedown_node.gSelected) {
+ // delete mousedown_node.gSelected
+ // } else {
+ // if (!d3.event.ctrlKey && !d3.event.metaKey) {
+ // clearSelection();
+ // }
+ // RED.nodes.group(mousedown_node.g).selected = true;
+ // mousedown_node.selected = true;
+ // mousedown_node.dirty = true;
+ // moving_set.push({n:mousedown_node});
+ // }
+ // }
if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE) {
+ // if (mousedown_node) {
+ // delete mousedown_node.gSelected;
+ // }
for (i=0;i 0) {
- selection.nodes = moving_set.map(function(n) { return n.n;});
- }
- if (selected_link != null) {
- selection.link = selected_link;
- }
+ selection = getSelection();
activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace},
target:{z:activeWorkspace}
@@ -1606,6 +1872,8 @@ RED.view = (function() {
var node = moving_set[0].n;
if (node.type === "subflow") {
RED.editor.editSubflow(activeSubflow);
+ } else if (node.type === "group") {
+ RED.editor.editGroup(node);
} else {
RED.editor.edit(node);
}
@@ -1632,6 +1900,7 @@ RED.view = (function() {
dirty: RED.nodes.dirty(),
nodes: [],
links: [],
+ groups: [],
workspaces: [],
subflows: []
}
@@ -1651,6 +1920,7 @@ RED.view = (function() {
}
historyEvent.nodes = historyEvent.nodes.concat(subEvent.nodes);
historyEvent.links = historyEvent.links.concat(subEvent.links);
+ historyEvent.groups = historyEvent.groups.concat(subEvent.groups);
}
RED.history.push(historyEvent);
RED.nodes.dirty(true);
@@ -1661,6 +1931,7 @@ RED.view = (function() {
var result;
var removedNodes = [];
var removedLinks = [];
+ var removedGroups = [];
var removedSubflowOutputs = [];
var removedSubflowInputs = [];
var removedSubflowStatus;
@@ -1668,11 +1939,14 @@ RED.view = (function() {
var startDirty = RED.nodes.dirty();
var startChanged = false;
+ var selectedGroups = [];
if (moving_set.length > 0) {
for (var i=0;i 0) {
+ var g = selectedGroups.shift();
+ if (removedGroups.indexOf(g) === -1) {
+ removedGroups.push(g);
+ g.nodes.forEach(function(n) {
+ if (n.type === "group") {
+ selectedGroups.push(n);
+ }
+ })
+ RED.nodes.removeGroup(g);
+ }
+ }
if (removedSubflowOutputs.length > 0) {
result = RED.subflow.removeOutput(removedSubflowOutputs);
if (result) {
@@ -1716,7 +2009,7 @@ RED.view = (function() {
subflowInstances = instances.instances;
}
moving_set = [];
- if (removedNodes.length > 0 || removedSubflowOutputs.length > 0 || removedSubflowInputs.length > 0 || removedSubflowStatus) {
+ if (removedNodes.length > 0 || removedSubflowOutputs.length > 0 || removedSubflowInputs.length > 0 || removedSubflowStatus || removedGroups.length > 0) {
RED.nodes.dirty(true);
}
}
@@ -1769,6 +2062,7 @@ RED.view = (function() {
t:"delete",
nodes:removedNodes,
links:removedLinks,
+ groups: removedGroups,
subflowOutputs:removedSubflowOutputs,
subflowInputs:removedSubflowInputs,
subflow: {
@@ -1801,20 +2095,36 @@ RED.view = (function() {
selection.forEach(function(n) {
if (n.type === 'tab') {
nodes.push(n);
+ nodes = nodes.concat(RED.nodes.groups(n.id));
nodes = nodes.concat(RED.nodes.filterNodes({z:n.id}));
}
});
- } else if (moving_set.length > 0) {
- nodes = moving_set.map(function(n) { return n.n });
+ } else {
+ selection = RED.view.selection();
+ if (selection.nodes) {
+ selection.nodes.forEach(function(n) {
+ nodes.push(n);
+ if (n.type === 'group') {
+ nodes = nodes.concat(RED.group.getNodes(n,true));
+ }
+ })
+ }
}
if (nodes.length > 0) {
var nns = [];
+ var nodeCount = 0;
+ var groupCount = 0;
for (var n=0;n 0) {
+ RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"});
+ } else if (groupCount > 0) {
+ RED.notify(RED._("clipboard.groupCopied",{count:groupCount}),{id:"clipboard"});
+ }
}
}
function calculateTextWidth(str, className, offset) {
- return calculateTextDimensions(str,className,offset,0)[0];
+ var result=convertLineBreakCharacter(str);
+ var width = 0;
+ for (var i=0;i 0 ? 1: 0) : (d.direction == "in" ? 0: 1)
var wasJoining = false;
if (mouse_mode === RED.state.JOINING || mouse_mode === RED.state.QUICK_JOINING) {
@@ -2276,7 +2666,24 @@ RED.view = (function() {
}
}
+ function prepareDrag(mouse) {
+ mouse_mode = RED.state.MOVING;
+ // Called when moving_set should be prepared to be dragged
+ for (i=0;i 0 && clickElapsed < 750) {
+ mouse_mode = RED.state.DEFAULT;
+ RED.editor.editGroup(g);
+ d3.event.stopPropagation();
+ return;
+ }
+
+ }
+
+ function groupMouseDown(g) {
+ var mouse = d3.touches(this.parentNode)[0]||d3.mouse(this.parentNode);
+ // if (! (mouse[0] < g.x+10 || mouse[0] > g.x+g.w-10 || mouse[1] < g.y+10 || mouse[1] > g.y+g.h-10) ) {
+ // return
+ // }
+
+ focusView();
+ if (d3.event.button === 1) {
+ return;
+ }
+ if (mouse_mode == RED.state.IMPORT_DRAGGING) {
+ RED.keyboard.remove("escape");
+ } else if (mouse_mode == RED.state.QUICK_JOINING) {
+ d3.event.stopPropagation();
+ return;
+ } else if (mouse_mode === RED.state.SELECTING_NODE) {
+ d3.event.stopPropagation();
+ return;
+ }
+
+ mousedown_group = g;
+
+ var now = Date.now();
+ clickElapsed = now-clickTime;
+ clickTime = now;
+
+ dblClickPrimed = (
+ lastClickNode == g &&
+ d3.event.button === 0 &&
+ !d3.event.shiftKey && !d3.event.metaKey && !d3.event.altKey && !d3.event.ctrlKey
+ );
+ lastClickNode = g;
+
+ if (g.selected && (d3.event.ctrlKey||d3.event.metaKey)) {
+ if (g === activeGroup) {
+ exitActiveGroup();
+ }
+ deselectGroup(g);
+ d3.event.stopPropagation();
+ } else {
+ if (!g.selected) {
+ if (!d3.event.ctrlKey && !d3.event.metaKey) {
+ clearSelection();
+ }
+ if (activeGroup) {
+ if (!RED.group.contains(activeGroup,g)) {
+ // Clicked on a group that is outside the activeGroup
+ exitActiveGroup();
+ } else {
+ }
+ }
+ selectGroup(g,true);//!wasSelected);
+ } else {
+ exitActiveGroup();
+ }
+
+
+ if (d3.event.button != 2) {
+ var d = g.nodes[0];
+ prepareDrag(mouse);
+ mousedown_group.dx = mousedown_group.x - mouse[0];
+ mousedown_group.dy = mousedown_group.y - mouse[1];
+ }
+ }
+
+ updateSelection();
+ redraw();
+ d3.event.stopPropagation();
+ }
+
+ function selectGroup(g, includeNodes) {
+ if (!g.selected) {
+ g.selected = true;
+ g.dirty = true;
+ }
+ moving_set.push({n:g});
+ if (includeNodes) {
+ var currentSet = new Set(moving_set.map(function(n) { return n.n }));
+ var allNodes = RED.group.getNodes(g,true);
+ allNodes.forEach(function(n) {
+ if (!currentSet.has(n)) {
+ moving_set.push({n:n})
+ // n.selected = true;
+ }
+ n.dirty = true;
+ })
+ }
+ }
+ function enterActiveGroup(group) {
+ if (activeGroup) {
+ exitActiveGroup();
+ }
+ group.active = true;
+ group.dirty = true;
+ activeGroup = group;
+ for (var i = moving_set.length-1; i >= 0; i -= 1) {
+ if (moving_set[i].n === group) {
+ moving_set.splice(i,1);
+ break;
+ }
+ }
+ }
+ function exitActiveGroup() {
+ if (activeGroup) {
+ activeGroup.active = false;
+ activeGroup.dirty = true;
+ deselectGroup(activeGroup);
+ selectGroup(activeGroup,true);
+ activeGroup = null;
+ }
+ }
+ function deselectGroup(g) {
+ if (g.selected) {
+ g.selected = false;
+ g.dirty = true;
+ }
+ var nodeSet = new Set(g.nodes);
+ nodeSet.add(g);
+ for (var i = moving_set.length-1; i >= 0; i -= 1) {
+ if (nodeSet.has(moving_set[i].n) || moving_set[i].n === g) {
+ moving_set[i].n.selected = false;
+ moving_set[i].n.dirty = true;
+ moving_set.splice(i,1);
+ }
+ }
+ }
+ function getGroupAt(x,y) {
+ var candidateGroups = {};
+ for (var i=0;i= g.x && x <= g.x + g.w && y >= g.y && y <= g.y + g.h) {
+ candidateGroups[g.id] = g;
+ }
+ }
+ var ids = Object.keys(candidateGroups);
+ if (ids.length > 1) {
+ ids.forEach(function(id) {
+ if (candidateGroups[id] && candidateGroups[id].g) {
+ delete candidateGroups[candidateGroups[id].g]
+ }
+ })
+ ids = Object.keys(candidateGroups);
+ }
+ if (ids.length === 0) {
+ return null;
+ } else {
+ return candidateGroups[ids[ids.length-1]]
+ }
+ }
+
function isButtonEnabled(d) {
var buttonEnabled = true;
var ws = RED.nodes.workspace(RED.workspaces.active());
@@ -2424,7 +3066,9 @@ RED.view = (function() {
function nodeButtonClicked(d) {
if (mouse_mode === RED.state.SELECTING_NODE) {
- d3.event.stopPropagation();
+ if (d3.event) {
+ d3.event.stopPropagation();
+ }
return;
}
var activeWorkspace = RED.workspaces.active();
@@ -2451,7 +3095,9 @@ RED.view = (function() {
RED.notify(RED._("notification.warning", {message:RED._("notification.warnings.nodeActionDisabled")}),"warning");
}
}
- d3.event.preventDefault();
+ if (d3.event) {
+ d3.event.preventDefault();
+ }
}
function showTouchMenu(obj,pos) {
@@ -2523,6 +3169,10 @@ RED.view = (function() {
}
function redraw() {
+ requestAnimationFrame(_redraw);
+ }
+
+ function _redraw() {
eventLayer.attr("transform","scale("+scaleFactor+")");
outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor);
@@ -2702,23 +3352,26 @@ RED.view = (function() {
var nodeEnter = node.enter().insert("svg:g")
.attr("class", "red-ui-flow-node red-ui-flow-node-group")
- .classed("red-ui-flow-subflow",function(d) { return activeSubflow != null; });
+ .classed("red-ui-flow-subflow", activeSubflow != null);
nodeEnter.each(function(d,i) {
var node = d3.select(this);
var isLink = (d.type === "link in" || d.type === "link out")
var hideLabel = d.hasOwnProperty('l')?!d.l : isLink;
node.attr("id",d.id);
- var l = RED.utils.getNodeLabel(d);
+ var labelWidth = calculateTextWidth(RED.utils.getNodeLabel(d), "red-ui-flow-node-label", 50);
if (d.resize || d.w === undefined) {
if (hideLabel) {
d.w = node_height;
} else {
- d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) );
+ d.w = Math.max(node_width,20*(Math.ceil((labelWidth+(d._def.inputs>0?7:0))/20)) );
}
}
- d.h = Math.max(node_height,(d.outputs||0) * 15);
-
+ if (hideLabel) {
+ d.h = Math.max(node_height,(d.outputs || 0) * 15);
+ } else {
+ d.h = Math.max(6+24*separateTextByLineBreak.length, (d.outputs || 0) * 15, 30);
+ }
// if (d._def.badge) {
// var badge = node.append("svg:g").attr("class","node_badge_group");
// var badgeRect = badge.append("rect").attr("class","node_badge").attr("rx",5).attr("ry",5).attr("width",40).attr("height",15);
@@ -2765,10 +3418,10 @@ RED.view = (function() {
var mainRect = node.append("rect")
.attr("class", "red-ui-flow-node")
- .classed("red-ui-flow-node-unknown",function(d) { return d.type == "unknown"; })
+ .classed("red-ui-flow-node-unknown", d.type == "unknown")
.attr("rx", 5)
.attr("ry", 5)
- .attr("fill",function(d) { return RED.utils.getNodeColor(d.type,d._def); /*d._def.color;*/})
+ .attr("fill", RED.utils.getNodeColor(d.type,d._def))
.on("mouseup",nodeMouseUp)
.on("mousedown",nodeMouseDown)
.on("touchstart",function(d) {
@@ -2876,17 +3529,17 @@ RED.view = (function() {
.attr("x",0).attr("y",0)
.attr("class","red-ui-flow-node-icon-shade")
.attr("width","30")
- .attr("height",function(d){return Math.min(50,d.h-4);});
+ .attr("height", Math.min(50,d.h-4));
createIconAttributes(icon_url, icon_group, d);
var icon_shade_border = icon_group.append("path")
- .attr("d",function(d) { return "M 30 1 l 0 "+(d.h-2)})
+ .attr("d","M 30 1 l 0 "+(d.h-2))
.attr("class","red-ui-flow-node-icon-shade-border");
if ("right" == d._def.align) {
icon_group.attr("class","red-ui-flow-node-icon-group red-ui-flow-node-icon-group-"+d._def.align);
- icon_shade_border.attr("d",function(d) { return "M 0 1 l 0 "+(d.h-2)})
+ icon_shade_border.attr("d", "M 0 1 l 0 "+(d.h-2))
//icon.attr("class","red-ui-flow-node-icon red-ui-flow-node-icon-"+d._def.align);
//icon.attr("class","red-ui-flow-node-icon-shade red-ui-flow-node-icon-shade-"+d._def.align);
//icon.attr("class","red-ui-flow-node-icon-shade-border red-ui-flow-node-icon-shade-border-"+d._def.align);
@@ -2904,17 +3557,22 @@ RED.view = (function() {
//icon.style("pointer-events","none");
icon_group.style("pointer-events","none");
}
- var text = node.append("svg:text")
+ var labelLineNumber = (separateTextByLineBreak.length == 0)? 1:separateTextByLineBreak.length;
+ var labelId = d.id.replace(".","-");
+ for(var i=0;i0?7:0))/20)) );
+ d.w = Math.max(node_width,20*(Math.ceil((labelWidth+(d._def.inputs>0?7:0))/20)) );
}
// d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) );
- d.h = Math.max(node_height,(d.outputs||0) * 15);
d.x += (d.w-ow)/2;
d.resize = false;
}
+ if (hideLabel) {
+ d.h = Math.max(node_height,(d.outputs || 0) * 15);
+ } else {
+ d.h = Math.max(6+24*separateTextByLineBreak.length,(d.outputs || 0) * 15, 30);
+ }
+
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.classed("red-ui-flow-node-disabled", d.d === true);
+ thisNode.classed("red-ui-flow-subflow", activeSubflow != null)
//thisNode.selectAll(".centerDot").attr({"cx":function(d) { return d.w/2;},"cy":function(d){return d.h/2}});
- thisNode.attr("transform", function(d) { return "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")"; });
+ thisNode.attr("transform", "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")");
if (mouse_mode != RED.state.MOVING_ACTIVE) {
- thisNode.classed("red-ui-flow-node-selected",function(d) { return d.selected })
+ thisNode.classed("red-ui-flow-node-selected", d.selected )
thisNode.selectAll(".red-ui-flow-node")
- .attr("width",function(d){return d.w})
- .attr("height",function(d){return d.h})
- .classed("red-ui-flow-node-highlighted",function(d) { return d.highlighted; })
+ .attr("width", d.w)
+ .attr("height", d.h)
+ .classed("red-ui-flow-node-highlighted",d.highlighted )
;
+ var l = "";
+ if (d._def.label) {
+ l = d._def.label;
+ try {
+ l = (typeof l === "function" ? l.call(d) : l)||"";
+ l = RED.text.bidi.enforceTextDirectionWithUCC(l);
+ } catch(err) {
+ console.log("Definition error: "+d.type+".label",err);
+ l = d.type;
+ }
+ }
+ var sa = convertLineBreakCharacter(l);
+ var sn = sa.length;
+ var st = "";
+ var yp = d.h / 2 - (sn / 2) * 24 + 16
+ var labelId = d.id.replace(".","-");
+ if(labelLineNumber0?5:0);});
//thisNode.selectAll(".red-ui-flow-node-icon-shade-right").attr("x",function(d){return d.w-30;});
//thisNode.selectAll(".red-ui-flow-node-icon-shade-border-right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)});
@@ -3067,35 +3790,6 @@ RED.view = (function() {
port.attr("transform", function(d) { return "translate("+x+","+((y+13*i)-5)+")";});
});
}
- thisNode.selectAll("text.red-ui-flow-node-label").text(function(d,i){
- var l = "";
- if (d._def.label) {
- l = d._def.label;
- try {
- l = (typeof l === "function" ? l.call(d) : l)||"";
- l = RED.text.bidi.enforceTextDirectionWithUCC(l);
- } catch(err) {
- console.log("Definition error: "+d.type+".label",err);
- l = d.type;
- }
- }
- return l;
- })
- .attr("y", function(d){return (d.h/2)-1;})
- .attr("class",function(d){
- var s = "";
- if (d._def.labelStyle) {
- s = d._def.labelStyle;
- try {
- s = (typeof s === "function" ? s.call(d) : s)||"";
- } catch(err) {
- console.log("Definition error: "+d.type+".labelStyle",err);
- s = "";
- }
- s = " "+s;
- }
- return "red-ui-flow-node-label"+(d._def.align?" red-ui-flow-node-label-"+d._def.align:"")+s;
- }).classed("hide",hideLabel);
if (d._def.icon) {
var icon = thisNode.select(".red-ui-flow-node-icon");
var faIcon = thisNode.select(".fa-lg");
@@ -3118,12 +3812,12 @@ RED.view = (function() {
}
thisNode.selectAll(".red-ui-flow-node-changed")
- .attr("transform",function(d){return "translate("+(d.w-10)+", -2)"})
- .classed("hide",function(d) { return !(d.changed||d.moved); });
+ .attr("transform", "translate("+(d.w-10)+", -2)")
+ .classed("hide", !(d.changed||d.moved));
thisNode.selectAll(".red-ui-flow-node-error")
- .attr("transform",function(d){ return "translate("+(d.w-10-((d.changed||d.moved)?14:0))+", -2)"})
- .classed("hide",function(d) { return d.valid; });
+ .attr("transform", "translate("+(d.w-10-((d.changed||d.moved)?14:0))+", -2)")
+ .classed("hide", d.valid);
thisNode.selectAll(".red-ui-flow-port-input").each(function(d,i) {
var port = d3.select(this);
@@ -3131,18 +3825,14 @@ RED.view = (function() {
});
thisNode.selectAll(".red-ui-flow-node-icon").attr("y",function(d){return (d.h-d3.select(this).attr("height"))/2;});
- thisNode.selectAll(".red-ui-flow-node-icon-shade").attr("height",function(d){return d.h;});
- thisNode.selectAll(".red-ui-flow-node-icon-shade-border").attr("d", function (d) {
- return "M " + (((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) ? 0 : 30) + " 1 l 0 " + (d.h - 2);
- });
- thisNode.selectAll(".fa-lg").attr("y",function(d){return (d.h+13)/2;});
+ thisNode.selectAll(".red-ui-flow-node-icon-shade").attr("height", d.h );
+ thisNode.selectAll(".red-ui-flow-node-icon-shade-border").attr("d",
+ "M " + (((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) ? 0 : 30) + " 1 l 0 " + (d.h - 2)
+ );
+ thisNode.selectAll(".fa-lg").attr("y",(d.h+13)/2);
- thisNode.selectAll(".red-ui-flow-node-button").attr("opacity",function(d) {
- return (!isButtonEnabled(d))?0.4:1
- });
- thisNode.selectAll(".red-ui-flow-node-button-button").attr("cursor",function(d) {
- return (!isButtonEnabled(d))?"":"pointer";
- });
+ thisNode.selectAll(".red-ui-flow-node-button").attr("opacity", function(d2) { return !isButtonEnabled(d2)?0.4:1 });
+ thisNode.selectAll(".red-ui-flow-node-button-button").attr("cursor",function(d2) { return isButtonEnabled(d2)?"":"pointer"});
thisNode.selectAll(".red-ui-flow-node-button").attr("transform",function(d){
var x = d._def.align == "right"?d.w-6:-25;
if (d._def.button.toggle && !d[d._def.button.toggle]) {
@@ -3208,6 +3898,15 @@ RED.view = (function() {
}
d.dirty = false;
+ if (d.g) {
+ if (!dirtyGroups[d.g]) {
+ var gg = d.g;
+ while (gg && !dirtyGroups[gg]) {
+ dirtyGroups[gg] = RED.nodes.group(gg);
+ gg = dirtyGroups[gg].g;
+ }
+ }
+ }
}
});
@@ -3238,7 +3937,9 @@ RED.view = (function() {
d3.event.stopPropagation();
if (d3.event.metaKey || d3.event.ctrlKey) {
l.classed("red-ui-flow-link-splice",true);
- showQuickAddDialog(d3.mouse(this), selected_link);
+ var point = d3.mouse(this);
+ var clickedGroup = getGroupAt(point[0],point[1]);
+ showQuickAddDialog(point, selected_link, clickedGroup);
}
})
.on("touchstart",function(d) {
@@ -3423,6 +4124,194 @@ RED.view = (function() {
})
+
+ var group = groupLayer.selectAll(".red-ui-flow-group").data(activeGroups,function(d) { return d.id });
+ group.exit().each(function(d,i) {
+ document.getElementById("group_select_"+d.id).remove()
+ }).remove();
+ var groupEnter = group.enter().insert("svg:g").attr("class", "red-ui-flow-group")
+
+ var addedGroups = false;
+ groupEnter.each(function(d,i) {
+ addedGroups = true;
+ var g = d3.select(this);
+ g.attr("id",d.id);
+
+ var groupBorderRadius = 4;
+
+ var selectGroup = groupSelectLayer.append('g').attr("class", "red-ui-flow-group").attr("id","group_select_"+d.id);
+ selectGroup.append('rect').classed("red-ui-flow-group-outline-select",true)
+ .attr('rx',groupBorderRadius).attr('ry',groupBorderRadius)
+ .attr("x",-4)
+ .attr("y",-4)
+ .style("stroke","rgba(255,255,255,0.8)")
+ .style("stroke-width",6)
+
+ selectGroup.append('rect').classed("red-ui-flow-group-outline-select",true)
+ .attr('rx',groupBorderRadius).attr('ry',groupBorderRadius)
+ .attr("x",-4)
+ .attr("y",-4)
+ selectGroup.on("mousedown", function() {groupMouseDown.call(g[0][0],d)});
+ selectGroup.on("mouseup", function() {groupMouseUp.call(g[0][0],d)});
+
+ g.append('rect').classed("red-ui-flow-group-outline",true).attr('rx',0.5).attr('ry',0.5);
+
+ g.append('rect').classed("red-ui-flow-group-body",true)
+ .attr('rx',groupBorderRadius).attr('ry',groupBorderRadius).style({
+ "fill":d.fill||"none",
+ "stroke": d.stroke||"none",
+ })
+ g.on("mousedown",groupMouseDown).on("mouseup",groupMouseUp)
+ g.append('svg:text').attr("class","red-ui-flow-group-label");
+ d.dirty = true;
+ });
+ if (addedGroups) {
+ group.sort(function(a,b) {
+ if (a._root === b._root) {
+ return a._depth - b._depth;
+ } else {
+ return a._root.localeCompare(b._root);
+ }
+ })
+ }
+ group[0].reverse();
+
+ group.each(function(d,i) {
+ if (d.resize) {
+ d.minWidth = 0;
+ delete d.resize;
+ }
+ if (d.dirty || dirtyGroups[d.id]) {
+ var g = d3.select(this);
+ if (d.nodes.length > 0) {
+ var minX = Number.POSITIVE_INFINITY;
+ var minY = Number.POSITIVE_INFINITY;
+ var maxX = 0;
+ var maxY = 0;
+ d.nodes.forEach(function(n) {
+ if (n.type !== "group") {
+ minX = Math.min(minX,n.x-n.w/2-25-((n._def.button && n._def.align!=="right")?20:0));
+ minY = Math.min(minY,n.y-n.h/2-25);
+ maxX = Math.max(maxX,n.x+n.w/2+25+((n._def.button && n._def.align=="right")?20:0));
+ maxY = Math.max(maxY,n.y+n.h/2+25);
+ } else {
+ minX = Math.min(minX,n.x-25)
+ minY = Math.min(minY,n.y-25)
+ maxX = Math.max(maxX,n.x+n.w+25)
+ maxY = Math.max(maxY,n.y+n.h+25)
+ }
+ });
+
+ d.x = minX;
+ d.y = minY;
+ d.w = maxX - minX;
+ d.h = maxY - minY;
+ } else {
+ d.w = 40;
+ d.h = 40;
+ }
+ if (!d.minWidth) {
+ if (d.style.label && d.name) {
+ d.minWidth = calculateTextWidth(d.name||"","red-ui-flow-group-label",8);
+ d.labels = separateTextByLineBreak;
+ } else {
+ d.minWidth = 40;
+ }
+ }
+ d.w = Math.max(d.minWidth,d.w);
+ if (d.style.label && d.labels) {
+ var h = (d.labels.length -1) * 16;
+ var labelPos = d.style["label-position"] || "nw";
+ d.h += h;
+ if (labelPos[0] === "n") {
+ d.y -= h;
+ }
+ }
+
+ g.attr("transform","translate("+d.x+","+d.y+")")
+ g.selectAll(".red-ui-flow-group-outline")
+ .attr("width",d.w)
+ .attr("height",d.h)
+
+
+ var selectGroup = document.getElementById("group_select_"+d.id);
+ selectGroup.setAttribute("transform","translate("+d.x+","+d.y+")");
+ if (d.hovered) {
+ selectGroup.classList.add("red-ui-flow-group-hovered")
+ } else {
+ selectGroup.classList.remove("red-ui-flow-group-hovered")
+ }
+ var selectGroupRect = selectGroup.children[0];
+ selectGroupRect.setAttribute("width",d.w+8)
+ selectGroupRect.setAttribute("height",d.h+8)
+ selectGroupRect.style.strokeOpacity = (d.selected || d.highlighted)?0.8:0;
+ selectGroupRect.style.strokeDasharray = (d.active)?"10 4":"";
+ selectGroupRect = selectGroup.children[1];
+ selectGroupRect.setAttribute("width",d.w+8)
+ selectGroupRect.setAttribute("height",d.h+8)
+ selectGroupRect.style.strokeOpacity = (d.selected || d.highlighted)?0.8:0;
+ selectGroupRect.style.strokeDasharray = (d.active)?"10 4":"";
+
+ if (d.highlighted) {
+ selectGroup.classList.add("red-ui-flow-node-highlighted");
+ } else {
+ selectGroup.classList.remove("red-ui-flow-node-highlighted");
+ }
+
+
+ g.selectAll(".red-ui-flow-group-body")
+ .attr("width",d.w)
+ .attr("height",d.h)
+ .style("stroke", d.style.stroke || "")
+ .style("stroke-opacity", d.style.hasOwnProperty('stroke-opacity') ? d.style['stroke-opacity'] : "")
+ .style("fill", d.style.fill || "")
+ .style("fill-opacity", d.style.hasOwnProperty('fill-opacity') ? d.style['fill-opacity'] : "")
+
+ var label = g.selectAll(".red-ui-flow-group-label");
+ label.classed("hide",!!!d.style.label)
+ if (d.style.label) {
+ var labelPos = d.style["label-position"] || "nw";
+ var labelX = 0;
+ var labelY = 0;
+
+ if (labelPos[0] === 'n') {
+ labelY = 0+15; // Allow for font-height
+ } else {
+ labelY = d.h - 5 -(d.labels.length -1) * 16;
+ }
+ if (labelPos[1] === 'w') {
+ labelX = 5;
+ labelAnchor = "start"
+ } else if (labelPos[1] === 'e') {
+ labelX = d.w-5;
+ labelAnchor = "end"
+ } else {
+ labelX = d.w/2;
+ labelAnchor = "middle"
+ }
+ label
+ .style("fill", d.style.hasOwnProperty('color')?d.style.color:"#999")
+ .attr("transform","translate("+labelX+","+labelY+")")
+ .attr("text-anchor",labelAnchor);
+ if (d.labels) {
+ var ypos = 0;
+ g.selectAll(".red-ui-flow-group-label-text").remove();
+ d.labels.forEach(function (name) {
+ label.append("tspan")
+ .classed("red-ui-flow-group-label-text", true)
+ .text(name)
+ .attr("x", 0)
+ .attr("y", ypos);
+ ypos += 16;
+ });
+ }
+ }
+
+ delete dirtyGroups[d.id];
+ delete d.dirty;
+ }
+ })
+
} else {
// JOINING - unselect any selected links
linkLayer.selectAll(".red-ui-flow-link-selected").data(
@@ -3436,7 +4325,6 @@ RED.view = (function() {
if (d3.event) {
d3.event.preventDefault();
}
-
}
function focusView() {
@@ -3474,29 +4362,36 @@ RED.view = (function() {
if (result) {
var new_nodes = result[0];
var new_links = result[1];
- var new_workspaces = result[2];
- var new_subflows = result[3];
- var new_default_workspace = result[4];
+ var new_groups = result[2];
+ var new_workspaces = result[3];
+ var new_subflows = result[4];
+ var new_default_workspace = result[5];
if (addNewFlow && new_default_workspace) {
RED.workspaces.show(new_default_workspace.id);
}
var new_ms = new_nodes.filter(function(n) { return n.hasOwnProperty("x") && n.hasOwnProperty("y") && n.z == RED.workspaces.active() }).map(function(n) { return {n:n};});
+ new_ms = new_ms.concat(new_groups.filter(function(g) { return g.z === RED.workspaces.active()}).map(function(g) { return {n:g}}))
var new_node_ids = new_nodes.map(function(n){ n.changed = true; return n.id; });
-
// TODO: pick a more sensible root node
if (new_ms.length > 0) {
- var root_node = new_ms[0].n;
- var dx = root_node.x;
- var dy = root_node.y;
+
if (mouse_position == null) {
mouse_position = [0,0];
}
+ var dx = mouse_position[0];
+ var dy = mouse_position[1];
+ if (new_ms.length > 0) {
+ var root_node = new_ms[0].n;
+ dx = root_node.x;
+ dy = root_node.y;
+ }
+
var minX = 0;
var minY = 0;
var i;
- var node;
+ var node,group;
for (i=0;i 0) {
counts.push(RED._("clipboard.flow",{count:new_workspaces.length}));
}
if (newNodeCount > 0) {
counts.push(RED._("clipboard.node",{count:newNodeCount}));
}
+ if (newGroupCount > 0) {
+ counts.push(RED._("clipboard.group",{count:newGroupCount}));
+ }
if (newConfigNodeCount > 0) {
counts.push(RED._("clipboard.configNode",{count:newNodeCount}));
}
@@ -3640,22 +4548,25 @@ RED.view = (function() {
var historyEvents = [];
for (var i=0;i 0) {
@@ -3670,7 +4581,40 @@ RED.view = (function() {
RED.view.redraw();
}
+ function getSelection() {
+ var selection = {};
+ var allNodes = new Set();
+
+ if (moving_set.length > 0) {
+ moving_set.forEach(function(n) {
+ if (n.n.type !== 'group') {
+ allNodes.add(n.n);
+ }
+ });
+ }
+ var selectedGroups = activeGroups.filter(function(g) { return g.selected && !g.active });
+ if (selectedGroups.length > 0) {
+ if (selectedGroups.length === 1 && selectedGroups[0].active) {
+ // Let nodes be nodes
+ } else {
+ selectedGroups.forEach(function(g) {
+ var groupNodes = RED.group.getNodes(g,true);
+ groupNodes.forEach(function(n) {
+ allNodes.delete(n);
+ });
+ allNodes.add(g);
+ });
+ }
+ }
+ if (allNodes.size > 0) {
+ selection.nodes = Array.from(allNodes);
+ }
+ if (selected_link != null) {
+ selection.link = selected_link;
+ }
+ return selection;
+ }
return {
init: init,
state:function(state) {
@@ -3681,12 +4625,17 @@ RED.view = (function() {
}
},
- redraw: function(updateActive) {
+ updateActive: updateActiveNodes,
+ redraw: function(updateActive, syncRedraw) {
if (updateActive) {
updateActiveNodes();
updateSelection();
}
- redraw();
+ if (syncRedraw) {
+ _redraw();
+ } else {
+ redraw();
+ }
},
focus: focusView,
importNodes: importNodes,
@@ -3701,21 +4650,31 @@ RED.view = (function() {
selectedNode.dirty = true;
moving_set = [{n:selectedNode}];
}
+ } else if (selection) {
+ if (selection.nodes) {
+ updateActiveNodes();
+ moving_set = [];
+ // TODO: this selection group span groups
+ // - if all in one group -> activate the group
+ // - if in multiple groups (or group/no-group)
+ // -> select the first 'set' of things in the same group/no-group
+ selection.nodes.forEach(function(n) {
+ if (n.type !== "group") {
+ n.selected = true;
+ n.dirty = true;
+ moving_set.push({n:n});
+ } else {
+ selectGroup(n,true);
+ }
+ })
+ }
}
}
updateSelection();
- redraw();
- },
- selection: function() {
- var selection = {};
- if (moving_set.length > 0) {
- selection.nodes = moving_set.map(function(n) { return n.n;});
- }
- if (selected_link != null) {
- selection.link = selected_link;
- }
- return selection;
+ redraw(true);
},
+ selection: getSelection,
+
scale: function() {
return scaleFactor;
},
@@ -3730,47 +4689,57 @@ RED.view = (function() {
}
return result;
},
- reveal: function(id) {
+ getGroupAtPoint: getGroupAt,
+ getActiveGroup: function() { return activeGroup },
+ reveal: function(id,triggerHighlight) {
if (RED.nodes.workspace(id) || RED.nodes.subflow(id)) {
RED.workspaces.show(id);
} else {
- var node = RED.nodes.node(id);
- if (node._def.category !== 'config' && node.z) {
- node.highlighted = true;
- node.dirty = true;
- RED.workspaces.show(node.z);
+ var node = RED.nodes.node(id) || RED.nodes.group(id);
+ if (node) {
+ if (node.z && (node.type === "group" || node._def.category !== 'config')) {
+ node.dirty = true;
+ RED.workspaces.show(node.z);
- 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)*scaleFactor);
- var deltaY = '-='+(((scrollPos[1] - node.y) + screenSize[1]/2)*scaleFactor);
- chart.animate({
- scrollLeft: deltaX,
- scrollTop: deltaY
- },200);
- }
-
- if (!node._flashing) {
- node._flashing = true;
- var flash = 22;
- var flashFunc = function() {
- flash--;
- node.dirty = true;
- if (flash >= 0) {
- node.highlighted = !node.highlighted;
- setTimeout(flashFunc,100);
- } else {
- node.highlighted = false;
- delete node._flashing;
- }
- RED.view.redraw();
+ var screenSize = [chart.width()/scaleFactor,chart.height()/scaleFactor];
+ var scrollPos = [chart.scrollLeft()/scaleFactor,chart.scrollTop()/scaleFactor];
+ var cx = node.x;
+ var cy = node.y;
+ if (node.type === "group") {
+ cx += node.w/2;
+ cy += node.h/2;
}
- flashFunc();
+ if (cx < scrollPos[0] || cy < scrollPos[1] || cx > screenSize[0]+scrollPos[0] || cy > screenSize[1]+scrollPos[1]) {
+ var deltaX = '-='+(((scrollPos[0] - cx) + screenSize[0]/2)*scaleFactor);
+ var deltaY = '-='+(((scrollPos[1] - cy) + screenSize[1]/2)*scaleFactor);
+ chart.animate({
+ scrollLeft: deltaX,
+ scrollTop: deltaY
+ },200);
+ }
+ if (triggerHighlight !== false) {
+ node.highlighted = true;
+ if (!node._flashing) {
+ node._flashing = true;
+ var flash = 22;
+ var flashFunc = function() {
+ flash--;
+ node.dirty = true;
+ if (flash >= 0) {
+ node.highlighted = !node.highlighted;
+ setTimeout(flashFunc,100);
+ } else {
+ node.highlighted = false;
+ delete node._flashing;
+ }
+ RED.view.redraw();
+ }
+ flashFunc();
+ }
+ }
+ } else if (node._def.category === 'config') {
+ RED.sidebar.config.show(id);
}
- } else if (node._def.category === 'config') {
- RED.sidebar.config.show(id);
}
}
},
@@ -3795,7 +4764,6 @@ RED.view = (function() {
mouse_mode = RED.state.SELECTING_NODE;
clearSelection();
if (options.selected) {
- console.log(options.selected);
options.selected.forEach(function(id) {
var n = RED.nodes.node(id);
if (n) {
@@ -3848,6 +4816,15 @@ RED.view = (function() {
type: "compact",
buttons: buttons
})
+ },
+ scroll: function(x,y) {
+ chart.scrollLeft(chart.scrollLeft()+x);
+ chart.scrollTop(chart.scrollTop()+y)
+ },
+ clickNodeButton: function(n) {
+ if (n._def.button) {
+ nodeButtonClicked(n);
+ }
}
};
})();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js
index 1f361d0f7..290083ea6 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js
@@ -128,10 +128,6 @@ RED.workspaces = (function() {
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) {
@@ -140,6 +136,7 @@ RED.workspaces = (function() {
});
RED.view.redraw();
}
+ RED.events.emit("flows:change",workspace);
}
RED.tray.close();
}
@@ -219,7 +216,10 @@ RED.workspaces = (function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
RED.view.state(RED.state.DEFAULT);
}
- RED.sidebar.info.refresh(workspace);
+ var selection = RED.view.selection();
+ if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
+ RED.sidebar.info.refresh(workspace);
+ }
tabflowEditor.destroy();
}
}
@@ -371,7 +371,9 @@ RED.workspaces = (function() {
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);
+ if (id === activeWorkspace) {
+ $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
+ }
var historyEvent = {
t: "edit",
changes:changes,
@@ -380,10 +382,11 @@ RED.workspaces = (function() {
}
workspace.changed = true;
RED.history.push(historyEvent);
+ RED.events.emit("flows:change",workspace);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
var selection = RED.view.selection();
- if (!selection.nodes && !selection.links) {
+ if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
RED.sidebar.info.refresh(workspace);
}
if (changes.hasOwnProperty('disabled')) {
@@ -412,9 +415,14 @@ RED.workspaces = (function() {
}
function setWorkspaceOrder(order) {
- RED.nodes.setWorkspaceOrder(order.filter(function(id) {
+ var newOrder = order.filter(function(id) {
return RED.nodes.workspace(id) !== undefined;
- }));
+ })
+ var currentOrder = RED.nodes.getWorkspaceOrder();
+ if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) {
+ RED.nodes.setWorkspaceOrder(newOrder);
+ RED.events.emit("flows:reorder",newOrder);
+ }
workspace_tabs.order(order);
}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/ace.scss b/packages/node_modules/@node-red/editor-client/src/sass/ace.scss
index f9c00faac..cd3739800 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/ace.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/ace.scss
@@ -9,19 +9,15 @@
color: transparent !important;
}
}
-
-
.ace_gutter {
+ background: $text-editor-gutter-background;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.ace_scroller {
+ background: $text-editor-background;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
- }
-
- .ace_scroller {
- background: $text-editor-background;
color: $text-editor-color;
}
.ace_marker-layer .ace_active-line {
@@ -37,9 +33,6 @@
.ace_gutter-active-line {
background: $text-editor-gutter-active-line-background;
}
- .ace_gutter {
- background: $text-editor-gutter-background;
- }
.ace_tooltip {
font-family: $primary-font;
line-height: 1.4em;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss
index 8411343c5..96be7b5ab 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss
@@ -23,7 +23,7 @@ $primary-background: #f3f3f3;//#0ff;
$secondary-background: #fff;//#ff0;
$secondary-background-selected: #efefef;//#e9e900;
$secondary-background-inactive: #f0f0f0;//#f0f000;
-$secondary-background-hover: #ddd;//#dd0;
+$secondary-background-hover: #e6e6e6;//#dd0;
$secondary-background-disabled: #f9f9f9;//#fafa0;
$tertiary-background: #f7f7f7;//#f0f;
@@ -94,7 +94,7 @@ $list-item-secondary-color: $secondary-text-color;
$list-item-background: $secondary-background;
$list-item-background-disabled: $secondary-background-inactive;
$list-item-background-hover: $secondary-background-hover;
-$list-item-background-selected: $secondary-background-selected;
+$list-item-background-selected: #ffebc7; // #fff1e5;
$list-item-border-selected: $secondary-text-color-selected;
$tab-text-color-active: $header-text-color;
@@ -284,3 +284,8 @@ $debug-message-border: #eee;
$debug-message-border-hover: #999;
$debug-message-border-warning: #ffdf9d;
$debug-message-border-error: #f99;
+
+$group-default-fill: none;
+$group-default-fill-opacity: 1;
+$group-default-stroke: #999;
+$group-default-stroke-opacity: 1;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss
index c95fecad6..d8ef3e89c 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss
@@ -304,9 +304,6 @@ button.red-ui-button-small
&:first-child {
padding: 20px 20px 0;
}
- &:last-child {
- padding-bottom: 20px;
- }
}
}
.red-ui-editor-type-expression-tab-content {
@@ -411,6 +408,133 @@ button.red-ui-button.red-ui-editor-node-appearance-button {
}
}
+.red-ui-group-layout-picker {
+ padding: 5px;
+ background: $primary-background;
+}
+.red-ui-group-layout-picker-cell-text {
+ position: absolute;
+ width: 14px;
+ height: 2px;
+ border-top: 2px solid $secondary-text-color;
+ border-bottom: 2px solid $secondary-text-color;
+ margin: 2px;
+
+ &.red-ui-group-layout-text-pos-nw { top: 0; left: 0; }
+ &.red-ui-group-layout-text-pos-n { top: 0; left: calc(50% - 9px); }
+ &.red-ui-group-layout-text-pos-ne { top: 0; right: 0; }
+ &.red-ui-group-layout-text-pos-sw { bottom: 0; left: 0; }
+ &.red-ui-group-layout-text-pos-s { bottom: 0; left: calc(50% - 9px); }
+ &.red-ui-group-layout-text-pos-se { bottom: 0; right: 0; }
+ &.red-ui-group-layout-text-pos- {
+ width: 100%;
+ height: 100%;
+ border-radius: 5px;
+ margin: 0;
+ background-color: #FFF;
+ background-size: 100% 100%;
+ background-position: 0 0, 50% 50%;
+ background-image: linear-gradient(45deg, transparent 45%, $secondary-border-color 45%, $secondary-border-color 55%, transparent 55%, transparent),linear-gradient(-45deg, transparent 45%, $secondary-border-color 45%, $secondary-border-color 55%, transparent 55%, transparent);
+ border: none;
+ }
+}
+
+.red-ui-group-layout-picker button.red-ui-search-result-node {
+ float: none;
+ position: relative;
+ padding: 0;
+ margin: 5px;
+ width: 32px;
+ height: 27px;
+}
+
+button.red-ui-group-layout-picker-none {
+ width: 100%;
+}
+
+.red-ui-color-picker {
+ input[type="text"] {
+ border-radius:0;
+ width: 100%;
+ margin-bottom: 0;
+ border: none;
+ border-bottom: 1px solid $form-input-border-color;
+ }
+ small {
+ color: $secondary-text-color;
+ margin-left: 5px;
+ margin-right: 4px;
+ display: inline-block;
+ min-width: 35px;
+ text-align: right;
+ }
+ background: $primary-background;
+}
+.red-ui-editor-node-appearance-button {
+ .red-ui-search-result-node {
+ overflow: hidden
+ }
+}
+.red-ui-color-picker-cell {
+ padding: 0;
+ border-style: solid;
+ border-width: 1px;
+ border-color: $secondary-border-color;
+}
+.red-ui-color-picker-swatch {
+ position: absolute;
+ top:-1px;right:-1px;left:-1px;bottom:-1px;
+ border-radius: 4px;
+}
+
+.red-ui-color-picker-cell-none {
+ height: 100%;
+ background-color: #FFF;
+ background-size: 100% 100%;
+ background-position: 0 0, 50% 50%;
+ background-image: linear-gradient(45deg, transparent 45%, $secondary-border-color 45%, $secondary-border-color 55%, transparent 55%, transparent),linear-gradient(-45deg, transparent 45%, $secondary-border-color 45%, $secondary-border-color 55%, transparent 55%, transparent)
+}
+.red-ui-search-result-node .red-ui-color-picker-cell-none {
+ border-radius: 4px;
+ background-size: 50% 50%;
+ background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee), linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
+}
+
+.red-ui-color-picker-opacity-slider {
+ position:relative;
+ vertical-align: middle;
+ display: inline-block;
+ width: calc(100% - 50px);
+ height: 14px;
+ margin: 6px 3px 8px;
+ box-sizing: border-box;
+ background-color: white;
+ background-image:
+ linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 25%),
+ linear-gradient(-45deg, #eee 25%, transparent 25%, transparent 75%, #eee 25%);
+ background-size: 6px 6px;
+}
+.red-ui-color-picker-opacity-slider-overlay {
+ position: absolute;
+ top:0;right:0;left:0;bottom:0;
+ background-image:linear-gradient(90deg, transparent 0%, #f00 100%);
+ background-size: 100% 100%;
+ border: 1px solid $primary-border-color;
+}
+
+div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle {
+ z-Index: 10;
+ top: -4px;
+ cursor: pointer;
+ min-width: 0;
+ width: 10px;
+ height: 22px;
+ padding: 0;
+ border: 1px solid $primary-border-color;
+ border-radius: 1px;
+ background: $secondary-background;
+ box-sizing: border-box;
+}
.red-ui-icon-picker {
select {
box-sizing: border-box;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss
index d92d1e964..60de209cc 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss
@@ -71,6 +71,48 @@
}
}
+.red-ui-flow-group {
+ &.red-ui-flow-group-hovered {
+ .red-ui-flow-group-outline-select {
+ stroke-opacity: 0.8 !important;
+ stroke-dasharray: 10 4 !important;
+ }
+ }
+ &.red-ui-flow-group-active-hovered:not(.red-ui-flow-group-hovered) {
+ .red-ui-flow-group-outline-select {
+ stroke: $link-link-color;
+ }
+ }
+}
+
+.red-ui-flow-group-outline {
+ fill: none;
+ stroke: $node-selected-color;
+ stroke-opacity: 0;
+ stroke-width: 12;
+ pointer-events: stroke;
+}
+.red-ui-flow-group-outline-select {
+ fill: none;
+ stroke: $node-selected-color;
+ pointer-events: stroke;
+ stroke-opacity: 0;
+ stroke-width: 3;
+}
+.red-ui-flow-group-body {
+ pointer-events: none;
+ fill: $group-default-fill;
+ fill-opacity: $group-default-fill-opacity;
+ stroke-width: 2;
+ stroke: $group-default-stroke;
+ stroke-opacity: $group-default-stroke-opacity;
+}
+.red-ui-flow-group-label {
+ @include disable-selection;
+}
+
+
+
.red-ui-flow-node-unknown {
stroke-dasharray:10,4;
stroke: $node-border-unknown;
@@ -166,6 +208,9 @@ g.red-ui-flow-node-selected {
fill-opacity: 1;
stroke-dasharray: none;
}
+ .red-ui-flow-group, .red-ui-flow-group-body {
+ stroke-dasharray: 8, 3;
+ }
}
.red-ui-flow-node-disabled {
&.red-ui-flow-node, .red-ui-flow-node {
@@ -248,6 +293,7 @@ g.red-ui-flow-node-selected {
.red-ui-flow-link-outline {
stroke: $view-background;
+ stroke-opacity: 0.4;
stroke-width: 5;
cursor: crosshair;
fill: none;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/library.scss b/packages/node_modules/@node-red/editor-client/src/sass/library.scss
index 60014b2e6..5cff53f44 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/library.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/library.scss
@@ -37,7 +37,7 @@
border-radius: 4px;
font-family: $monospace-font !important;
font-size: 13px !important;
- height: 300px;
+ height: 100%;
line-height: 1.3em;
padding: 6px 10px;
background: $clipboard-textarea-background;
@@ -62,6 +62,7 @@
background: $form-input-background;
&>div {
height: 100%;
+ box-sizing: border-box;
}
}
.red-ui-clipboard-dialog-box {
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/palette.scss b/packages/node_modules/@node-red/editor-client/src/sass/palette.scss
index ea4b06c52..922a31e33 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/palette.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/palette.scss
@@ -186,6 +186,21 @@
background-size: contain;
background-repeat: no-repeat;
}
+.red-ui-search-result-node {
+ &.red-ui-palette-icon-flow,
+ &.red-ui-palette-icon-group,
+ &.red-ui-palette-icon-selection {
+ background: none;
+ border-color: transparent;
+ .red-ui-palette-icon-container {
+ background: none;
+ }
+ .red-ui-palette-icon-fa {
+ color: $secondary-text-color;
+ font-size: 18px;
+ }
+ }
+}
.red-ui-palette-icon-fa {
color: white;
position: absolute;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/panels.scss b/packages/node_modules/@node-red/editor-client/src/sass/panels.scss
index 9f99db5d4..455aab891 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/panels.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/panels.scss
@@ -22,9 +22,19 @@
// border: 1px solid red;
box-sizing: border-box;
}
+ display: flex;
+ flex-direction: column;
+
+ >.red-ui-panel:first-child {
+ flex: 0 0 auto;
+ }
+ >.red-ui-panel:last-child {
+ flex: 1 1 auto;
+ }
}
.red-ui-panels-separator {
+ flex: 0 0 auto;
border-top: 1px solid $secondary-border-color;
border-bottom: 1px solid $secondary-border-color;
height: 7px;
@@ -37,10 +47,13 @@
.red-ui-panel {
overflow: auto;
height: calc(50% - 4px);
+ position: relative;
}
.red-ui-panels.red-ui-panels-horizontal {
height: 100%;
+ flex-direction: row;
+
&>.red-ui-panel {
vertical-align: top;
display: inline-block;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/popover.scss b/packages/node_modules/@node-red/editor-client/src/sass/popover.scss
index 95097a30e..872f32024 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/popover.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/popover.scss
@@ -150,6 +150,16 @@
.red-ui-popover a.red-ui-button,
.red-ui-popover button.red-ui-button {
+ &:not(.primary) {
+ border-color: $popover-button-border-color;
+ background: $popover-background;
+ color: $popover-color !important;
+ }
+ &:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
+ border-color: $popover-button-border-color-hover;
+ }
+
+
&.primary {
border-color: $popover-button-border-color;
}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/projects.scss b/packages/node_modules/@node-red/editor-client/src/sass/projects.scss
index 9b1005f22..e08551297 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/projects.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/projects.scss
@@ -18,7 +18,12 @@
.red-ui-editableList-container {
padding: 0px;
}
-
+ padding: 0;
+ .red-ui-projects-dialog-box {
+ box-sizing: border-box;
+ overflow-y: auto;
+ padding: 25px 25px 10px 25px;
+ }
}
#red-ui-project-settings-tab-settings {
overflow-y: scroll;
@@ -99,6 +104,7 @@
.red-ui-projects-dialog-screen-create {
min-height: 500px;
button.red-ui-projects-dialog-screen-create-type {
+ position: relative;
height: auto;
padding: 10px;
}
@@ -169,9 +175,14 @@
.red-ui-projects-dialog-project-list-container {
border: 1px solid $secondary-border-color;
border-radius: 2px;
+ display: flex;
+ flex-direction: column;
+ .red-ui-search-container {
+ flex-grow: 0;
+ }
}
.red-ui-projects-dialog-project-list-inner-container {
- height: 300px;
+ flex-grow: 1 ;
overflow-y: scroll;
position:relative;
.red-ui-editableList-border {
@@ -254,6 +265,9 @@
}
}
}
+.red-ui-projects-dialog-screen-create-type {
+ position: relative;
+}
.red-ui-projects-dialog-screen-create-type.red-ui-button.toggle.selected:not(.disabled):not(:disabled) {
color: $secondary-text-color-active !important;
}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/search.scss b/packages/node_modules/@node-red/editor-client/src/sass/search.scss
index 0ec8b6525..27ebb1a04 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/search.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/search.scss
@@ -24,6 +24,13 @@
top: 0px;
border: 1px solid $primary-border-color;
box-shadow: 0 0 10px $shadow;
+ background: $secondary-background;
+
+ .red-ui-searchBox-container {
+ display: inline-block;
+ margin-right: 6px;
+ width: calc(100% - 30px);
+ }
}
.red-ui-type-search {
@@ -87,6 +94,8 @@
}
.red-ui-palette-icon {
width: 15px;
+ position:relative;
+ left: -1px;
}
.red-ui-search-result-description {
margin-left:28px;
@@ -153,7 +162,7 @@
width: 30px;
float:left;
height: 25px;
- border-radius: 5px;
+ border-radius: 3px;
border: 1px solid $node-border;
background-position: 5% 50%;
background-repeat: no-repeat;
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/style.scss b/packages/node_modules/@node-red/editor-client/src/sass/style.scss
index 088e5c1b8..ca572ea46 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/style.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/style.scss
@@ -42,6 +42,7 @@
@import "tab-config";
@import "tab-context";
@import "tab-info";
+@import "tab-help";
@import "popover";
@import "flow";
@import "palette-editor";
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/tab-help.scss b/packages/node_modules/@node-red/editor-client/src/sass/tab-help.scss
new file mode 100644
index 000000000..fe4f9fb84
--- /dev/null
+++ b/packages/node_modules/@node-red/editor-client/src/sass/tab-help.scss
@@ -0,0 +1,27 @@
+.red-ui-sidebar-help-stack {
+ // height: calc(100% - 39px);
+}
+.red-ui-help-search {
+ border-bottom: 1px solid $secondary-border-color;
+}
+
+.red-ui-sidebar-help-toc {
+ .red-ui-treeList-label {
+ font-size: 13px;
+ padding: 2px 0;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+
+}
+#red-ui-sidebar-help-show-toc {
+ i.fa-angle-right {
+ transition: all 0.2s ease-in-out;
+ }
+ &.selected {
+ i.fa-angle-right {
+ transform: rotate(90deg);
+ }
+ }
+
+}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss b/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss
index bc72f7532..c98bdb6ad 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss
@@ -14,9 +14,25 @@
* limitations under the License.
**/
+.red-ui-sidebar-info {
+ height: 100%;
+}
.red-ui-sidebar-info hr {
margin: 10px 0;
}
+.red-ui-info-header {
+ padding-left: 9px;
+ line-height: 21px;
+ cursor: default;
+ > * {
+ vertical-align: middle
+ }
+ > span {
+ display: inline-block;
+ margin-left: 5px;
+ }
+ border-bottom: 1px solid $secondary-border-color;
+}
table.red-ui-info-table {
font-size: 14px;
margin: 0 0 10px;
@@ -125,6 +141,9 @@ div.red-ui-info-table {
font-size: 1.296em;
line-height: 1.3em;
margin: 8px auto;
+ &.red-ui-help-title {
+ border-bottom: 1px solid $tertiary-border-color;
+ }
}
h2 {
font-weight: 500;
@@ -214,12 +233,13 @@ div.red-ui-info-table {
}
.red-ui-sidebar-info-stack {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- overflow-y: scroll;
+ height: 100%;
+ // position: absolute;
+ // top: 0;
+ // bottom: 0;
+ // left: 0;
+ // right: 0;
+ // overflow-y: scroll;
}
.red-ui-help-tips {
display: none;
@@ -227,20 +247,23 @@ div.red-ui-info-table {
left:0;
right:0;
bottom: 0;
- height: 150px;
+ height: 0;
+ transition: height 0.2s, padding 0.2s;
box-sizing: border-box;
border-top: 1px solid $secondary-border-color;
background-color: $secondary-background;
- padding: 20px;
+ padding: 0;
box-shadow: 0 5px 20px 0px $shadow;
overflow-y: auto;
}
.red-ui-sidebar-info.show-tips {
.red-ui-sidebar-info-stack {
- bottom: 150px;
+ height: calc(100% - 150px);
}
.red-ui-help-tips {
display: block;
+ height: 150px;
+ padding: 20px;
}
}
@@ -279,3 +302,220 @@ div.red-ui-info-table {
border-radius: 4px;
padding: 2px 4px 2px;
}
+
+.red-ui-info-outline,.red-ui-sidebar-help-toc {
+ display: flex;
+ flex-direction: column;
+
+ .red-ui-treeList {
+ flex-grow: 1;
+ position: relative;
+ }
+ .red-ui-treeList-container {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ }
+
+ .red-ui-treeList-container,.red-ui-editableList-border {
+ border: none;
+ border-radius: 0;
+ }
+ .red-ui-treeList-label {
+ font-size: 13px;
+ padding: 2px 0;
+ overflow: hidden;
+ }
+ .red-ui-info-outline-project {
+ border-bottom: 1px solid $secondary-border-color;
+ }
+
+ .red-ui-info-outline-item {
+ display: inline-block;
+ padding: 0;
+ font-size: 13px;
+ border: none;
+ .red-ui-palette-icon-fa {
+ position: relative;
+ top: 1px;
+ left: 0px;
+ }
+ &:hover {
+ background: inherit
+ }
+
+ &.red-ui-info-outline-item-flow {
+ .red-ui-search-result-description {
+ margin-left: 4px;
+ }
+ }
+ &.red-ui-info-outline-item-group .red-ui-search-result-node {
+ background: none;
+ border-color: transparent;
+ .red-ui-palette-icon-container {
+ background: none;
+ }
+ .red-ui-palette-icon-fa {
+ color: $secondary-text-color;
+ font-size: 18px;
+ }
+ }
+ &.red-ui-info-outline-item-empty {
+ font-style: italic;
+ color: $form-placeholder-color;
+ }
+ }
+
+ .red-ui-search-result-node {
+ width: 24px;
+ height: 20px;
+ margin-top: 1px;
+ }
+
+ .red-ui-palette-icon-container {
+ width: 24px;
+ }
+ .red-ui-palette-icon {
+ width: 20px;
+ }
+ .red-ui-search-result-description {
+ margin-left: 32px;
+ line-height: 22px;
+ white-space: nowrap;
+ }
+ .red-ui-search-result-node-label {
+ color: $secondary-text-color;
+ }
+}
+.red-ui-info-outline-item-control-spacer {
+ display: inline-block;
+ width: 23px;
+}
+.red-ui-info-outline-gutter {
+ display:none;
+ button {
+ position: absolute;
+ top: 1px;
+ left: 2px;
+ }
+ .red-ui-treeList-label:hover & {
+ display: inline;
+ }
+}
+.red-ui-info-outline-item-controls {
+ position: absolute;
+ top:0;
+ bottom: 0;
+ right: 0px;
+ padding: 2px 3px 0 1px;
+ text-align: right;
+ background: $list-item-background;
+
+ .red-ui-treeList-label:hover & {
+ background: $list-item-background-hover;
+ }
+ .red-ui-treeList-label.selected & {
+ background: $list-item-background-selected;
+ }
+
+
+ &.red-ui-info-outline-item-hover-controls button {
+ min-width: 23px;
+ }
+
+ .red-ui-treeList-label:not(:hover) &.red-ui-info-outline-item-hover-controls {
+ button {
+ border: none;
+ background: none;
+ }
+ }
+ .red-ui-info-outline-item-control-reveal,
+ .red-ui-info-outline-item-control-action {
+ display: none;
+ }
+ .red-ui-treeList-label:hover & {
+ .red-ui-info-outline-item-control-reveal,
+ .red-ui-info-outline-item-control-action {
+ display: inline-block;
+ }
+ }
+
+ .fa-ban {
+ display: none;
+ }
+ .red-ui-info-outline-item.red-ui-info-outline-item-disabled & {
+ .fa-ban {
+ display: inline-block;
+ }
+ .fa-circle-thin {
+ display: none;
+ }
+ }
+ button {
+ margin-right: 3px
+ }
+}
+.red-ui-info-outline-item-disabled {
+ .red-ui-search-result-node {
+ opacity: 0.4;
+ }
+ .red-ui-info-outline-item-label {
+ font-style: italic;
+ color: $secondary-text-color-disabled;
+ }
+ .red-ui-icons-flow {
+ opacity: 0.4;
+ }
+}
+
+
+
+.red-ui-icons {
+ display: inline-block;
+ width: 18px;
+ &:before {
+ white-space: pre;
+ content: ' '
+ }
+
+}
+
+.red-ui-icons-flow {
+ background-image: url('images/subflow_tab.svg');
+ background-repeat: no-repeat;
+ background-size: contain;
+ filter: brightness(2.5);
+}
+
+.red-ui-info-toolbar {
+ min-height: 39px;
+ height: 39px;
+ box-sizing: border-box;
+ text-align: left;
+ // padding-left: 9px;
+ // box-sizing: border-box;
+ // background: $palette-header-background;
+ // border-bottom: 1px solid $secondary-border-color;
+
+ .red-ui-searchBox-container {
+ position: absolute;
+ top: 6px;
+ right: 8px;
+ width: calc(100% - 150px);
+ max-width: 250px;
+ background: $palette-header-background;
+ input.red-ui-searchBox-input {
+ border: 1px solid $secondary-border-color;
+ border-radius: 3px;
+ font-size: 12px;
+ height: 26px;
+ }
+ input:focus.red-ui-searchBox-input {
+ border: 1px solid $secondary-border-color;
+ }
+ i.fa-search, i.fa-times {
+ top: 7px;
+ }
+ }
+
+}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss b/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss
index 704ca10d6..ec865b116 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss
@@ -51,7 +51,10 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
-
+ .red-ui-typedInput-value-label-inactive {
+ background: $secondary-background-disabled;
+ color: $secondary-text-color-disabled;
+ }
}
}
.red-ui-typedInput-options {
@@ -117,7 +120,7 @@ button.red-ui-typedInput-option-trigger
}
&.disabled {
cursor: default;
- i.red-ui-typedInput-icon {
+ > i.red-ui-typedInput-icon {
color: $secondary-text-color-disabled;
}
}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss b/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss
index f6255eacf..2adfb89ba 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss
@@ -112,7 +112,7 @@
position: absolute;
bottom: 0;
right:0;
- zIndex: 101;
+ z-index: 101;
border-left: 1px solid $primary-border-color;
border-top: 1px solid $primary-border-color;
background: $view-navigator-background;
@@ -122,7 +122,7 @@
stroke-dasharray: 5,5;
pointer-events: none;
stroke: $secondary-border-color;
- strokeWidth: 1;
+ stroke-width: 1;
fill: $view-background;
}
@@ -172,3 +172,44 @@ button.red-ui-footer-button-toggle {
margin-right: 0;
}
}
+
+
+#red-ui-loading-progress {
+ position: absolute;
+ background: $primary-background;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ z-index: 200;
+ & > div {
+ position: absolute;
+ top: 30%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 300px;
+ height:80px;
+ text-align: center;
+ color: $secondary-text-color;
+
+ }
+}
+.red-ui-loading-bar {
+ box-sizing: border-box;
+ width: 300px;
+ height: 30px;
+ border: 2px solid $primary-border-color;
+ border-radius: 4px;
+
+ > span {
+ display: block;
+ height: 100%;
+ background: $secondary-border-color;
+ transition: width 0.2s;
+ width: 10%;
+ }
+}
+.red-ui-loading-bar-label {
+ font-size: 13px;
+ margin-bottom: 2px;
+}
diff --git a/packages/node_modules/@node-red/nodes/core/common/20-inject.html b/packages/node_modules/@node-red/nodes/core/common/20-inject.html
index 87ec3f86b..8aa3dc7b2 100644
--- a/packages/node_modules/@node-red/nodes/core/common/20-inject.html
+++ b/packages/node_modules/@node-red/nodes/core/common/20-inject.html
@@ -14,16 +14,14 @@
limitations under the License.
-->
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/20-inject.js b/packages/node_modules/@node-red/nodes/core/common/20-inject.js
index c0d9e0c2f..54715e131 100644
--- a/packages/node_modules/@node-red/nodes/core/common/20-inject.js
+++ b/packages/node_modules/@node-red/nodes/core/common/20-inject.js
@@ -20,9 +20,32 @@ module.exports = function(RED) {
function InjectNode(n) {
RED.nodes.createNode(this,n);
- this.topic = n.topic;
- this.payload = n.payload;
- this.payloadType = n.payloadType;
+
+ /* Handle legacy */
+ if(!Array.isArray(n.props)){
+ n.props = [];
+ n.props.push({
+ p:'payload',
+ v:n.payload,
+ vt:n.payloadType
+ });
+ n.props.push({
+ p:'topic',
+ v:n.topic,
+ vt:'str'
+ });
+ } else {
+ for (var i=0,l=n.props.length; i 2147483) {
node.error(RED._("inject.errors.toolong", this));
delete node.repeat;
}
node.repeaterSetup = function () {
- if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
- this.repeat = this.repeat * 1000;
- if (RED.settings.verbose) {
- this.log(RED._("inject.repeat", this));
+ if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
+ this.repeat = this.repeat * 1000;
+ if (RED.settings.verbose) {
+ this.log(RED._("inject.repeat", this));
+ }
+ this.interval_id = setInterval(function() {
+ node.emit("input", {});
+ }, this.repeat);
+ } else if (this.crontab) {
+ if (RED.settings.verbose) {
+ this.log(RED._("inject.crontab", this));
+ }
+ this.cronjob = new cron.CronJob(this.crontab, function() { node.emit("input", {}); }, null, true);
}
- this.interval_id = setInterval(function() {
- node.emit("input", {});
- }, this.repeat);
- } else if (this.crontab) {
- if (RED.settings.verbose) {
- this.log(RED._("inject.crontab", this));
- }
- this.cronjob = new cron.CronJob(this.crontab, function() { node.emit("input", {}); }, null, true);
- }
};
if (this.once) {
this.onceTimeout = setTimeout( function() {
- node.emit("input",{});
- node.repeaterSetup();
+ node.emit("input",{});
+ node.repeaterSetup();
}, this.onceDelay);
} else {
- node.repeaterSetup();
+ node.repeaterSetup();
}
- this.on("input",function(msg) {
- msg.topic = this.topic;
- if (this.payloadType !== 'flow' && this.payloadType !== 'global') {
- try {
- if ( (this.payloadType == null && this.payload === "") || this.payloadType === "date") {
- msg.payload = Date.now();
- } else if (this.payloadType == null) {
- msg.payload = this.payload;
- } else if (this.payloadType === 'none') {
- msg.payload = "";
- } else {
- msg.payload = RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg);
- }
- this.send(msg);
- msg = null;
- } catch(err) {
- this.error(err,msg);
- }
- } else {
- RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg, function(err,res) {
- if (err) {
- node.error(err,msg);
- } else {
- msg.payload = res;
- node.send(msg);
- }
+ this.on("input", function(msg) {
+ var errors = [];
- });
+ this.props.forEach(p => {
+ var property = p.p;
+ var value = p.v ? p.v : '';
+ var valueType = p.vt ? p.vt : 'str';
+
+ if (!property) return;
+
+ if (valueType === "jsonata") {
+ if (p.exp) {
+ try {
+ var val = RED.util.evaluateJSONataExpression(p.exp, msg);
+ RED.util.setMessageProperty(msg, property, val, true);
+ }
+ catch (err) {
+ errors.push(err.message);
+ }
+ }
+ return;
+ }
+ try {
+ RED.util.setMessageProperty(msg,property,RED.util.evaluateNodeProperty(value, valueType, this, msg),true);
+ } catch (err) {
+ errors.push(err.toString());
+ }
+ });
+
+ if (errors.length) {
+ node.error(errors.join('; '), msg);
+ } else {
+ node.send(msg);
}
});
}
diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.html b/packages/node_modules/@node-red/nodes/core/common/21-debug.html
index 5e2f3ba49..d12279c74 100644
--- a/packages/node_modules/@node-red/nodes/core/common/21-debug.html
+++ b/packages/node_modules/@node-red/nodes/core/common/21-debug.html
@@ -1,30 +1,35 @@
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.html b/packages/node_modules/@node-red/nodes/core/function/10-function.html
index 9202d96ba..78e7f2d63 100644
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.html
+++ b/packages/node_modules/@node-red/nodes/core/function/10-function.html
@@ -1,22 +1,57 @@
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.js b/packages/node_modules/@node-red/nodes/core/function/10-function.js
index 65a1b4a61..a6573a787 100644
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.js
+++ b/packages/node_modules/@node-red/nodes/core/function/10-function.js
@@ -57,22 +57,55 @@ module.exports = function(RED) {
}
}
+ function createVMOpt(node, kind) {
+ var opt = {
+ filename: 'Function node'+kind+':'+node.id+(node.name?' ['+node.name+']':''), // filename for stack traces
+ displayErrors: true
+ // Using the following options causes node 4/6 to not include the line number
+ // in the stack output. So don't use them.
+ // lineOffset: -11, // line number offset to be used for stack traces
+ // columnOffset: 0, // column number offset to be used for stack traces
+ };
+ return opt;
+ }
+
+ function updateErrorInfo(err) {
+ if (err.stack) {
+ var stack = err.stack.toString();
+ var m = /^([^:]+):([^:]+):(\d+).*/.exec(stack);
+ if (m) {
+ var line = parseInt(m[3]) -1;
+ var kind = "body:";
+ if (/setup/.exec(m[1])) {
+ kind = "setup:";
+ }
+ if (/cleanup/.exec(m[1])) {
+ kind = "cleanup:";
+ }
+ err.message += " ("+kind+"line "+line+")";
+ }
+ }
+ }
+
function FunctionNode(n) {
RED.nodes.createNode(this,n);
var node = this;
- this.name = n.name;
- this.func = n.func;
+ node.name = n.name;
+ node.func = n.func;
+ node.ini = n.initialize ? n.initialize : "";
+ node.fin = n.finalize ? n.finalize : "";
var handleNodeDoneCall = true;
+
// Check to see if the Function appears to call `node.done()`. If so,
// we will assume it is well written and does actually call node.done().
// Otherwise, we will call node.done() after the function returns regardless.
- if (/node\.done\s*\(\s*\)/.test(this.func)) {
+ if (/node\.done\s*\(\s*\)/.test(node.func)) {
handleNodeDoneCall = false;
}
var functionText = "var results = null;"+
- "results = (function(msg,__send__,__done__){ "+
+ "results = (async function(msg,__send__,__done__){ "+
"var __msgid__ = msg._msgid;"+
"var node = {"+
"id:__node__.id,"+
@@ -87,11 +120,13 @@ module.exports = function(RED) {
"send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
"done:__done__"+
"};\n"+
- this.func+"\n"+
+ node.func+"\n"+
"})(msg,send,done);";
- this.topic = n.topic;
- this.outstandingTimers = [];
- this.outstandingIntervals = [];
+ var finScript = null;
+ var finOpt = null;
+ node.topic = n.topic;
+ node.outstandingTimers = [];
+ node.outstandingIntervals = [];
var sandbox = {
console:console,
util:util,
@@ -182,12 +217,12 @@ module.exports = function(RED) {
arguments[0] = function() {
sandbox.clearTimeout(timerId);
try {
- func.apply(this,arguments);
+ func.apply(node,arguments);
} catch(err) {
node.error(err,{});
}
};
- timerId = setTimeout.apply(this,arguments);
+ timerId = setTimeout.apply(node,arguments);
node.outstandingTimers.push(timerId);
return timerId;
},
@@ -203,12 +238,12 @@ module.exports = function(RED) {
var timerId;
arguments[0] = function() {
try {
- func.apply(this,arguments);
+ func.apply(node,arguments);
} catch(err) {
node.error(err,{});
}
};
- timerId = setInterval.apply(this,arguments);
+ timerId = setInterval.apply(node,arguments);
node.outstandingIntervals.push(timerId);
return timerId;
},
@@ -226,37 +261,48 @@ module.exports = function(RED) {
sandbox.setTimeout(function(){ resolve(value); }, after);
});
};
+ sandbox.promisify = util.promisify;
}
var context = vm.createContext(sandbox);
try {
- this.script = vm.createScript(functionText, {
- filename: 'Function node:'+this.id+(this.name?' ['+this.name+']':''), // filename for stack traces
- displayErrors: true
- // Using the following options causes node 4/6 to not include the line number
- // in the stack output. So don't use them.
- // lineOffset: -11, // line number offset to be used for stack traces
- // columnOffset: 0, // column number offset to be used for stack traces
- });
- this.on("input", function(msg,send,done) {
- try {
- var start = process.hrtime();
- context.msg = msg;
- context.send = send;
- context.done = done;
+ var iniScript = null;
+ var iniOpt = null;
+ if (node.ini && (node.ini !== "")) {
+ var iniText = "(async function () {\n"+node.ini +"\n})();";
+ iniOpt = createVMOpt(node, " setup");
+ iniScript = new vm.Script(iniText, iniOpt);
+ }
+ node.script = vm.createScript(functionText, createVMOpt(node, ""));
+ if (node.fin && (node.fin !== "")) {
+ var finText = "(function () {\n"+node.fin +"\n})();";
+ finOpt = createVMOpt(node, " cleanup");
+ finScript = new vm.Script(finText, finOpt);
+ }
+ var promise = Promise.resolve();
+ if (iniScript) {
+ promise = iniScript.runInContext(context, iniOpt);
+ }
- this.script.runInContext(context);
- sendResults(this,send,msg._msgid,context.results,false);
+ function processMessage(msg, send, done) {
+ var start = process.hrtime();
+ context.msg = msg;
+ context.send = send;
+ context.done = done;
+
+ node.script.runInContext(context);
+ context.results.then(function(results) {
+ sendResults(node,send,msg._msgid,results,false);
if (handleNodeDoneCall) {
done();
}
var duration = process.hrtime(start);
var converted = Math.floor((duration[0] * 1e9 + duration[1])/10000)/100;
- this.metric("duration", msg, converted);
+ node.metric("duration", msg, converted);
if (process.env.NODE_RED_FUNCTION_TIME) {
- this.status({fill:"yellow",shape:"dot",text:""+converted});
+ node.status({fill:"yellow",shape:"dot",text:""+converted});
}
- } catch(err) {
+ }).catch(err => {
if ((typeof err === "object") && err.hasOwnProperty("stack")) {
//remove unwanted part
var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
@@ -294,23 +340,67 @@ module.exports = function(RED) {
else {
done(JSON.stringify(err));
}
+ });
+ }
+
+ const RESOLVING = 0;
+ const RESOLVED = 1;
+ const ERROR = 2;
+ var state = RESOLVING;
+ var messages = [];
+
+ node.on("input", function(msg,send,done) {
+ if(state === RESOLVING) {
+ messages.push({msg:msg, send:send, done:done});
+ }
+ else if(state === RESOLVED) {
+ processMessage(msg, send, done);
}
});
- this.on("close", function() {
+ node.on("close", function() {
+ if (finScript) {
+ try {
+ finScript.runInContext(context, finOpt);
+ }
+ catch (err) {
+ node.error(err);
+ }
+ }
while (node.outstandingTimers.length > 0) {
clearTimeout(node.outstandingTimers.pop());
}
while (node.outstandingIntervals.length > 0) {
clearInterval(node.outstandingIntervals.pop());
}
- this.status({});
+ node.status({});
});
- } catch(err) {
+
+ promise.then(function (v) {
+ var msgs = messages;
+ messages = [];
+ while (msgs.length > 0) {
+ msgs.forEach(function (s) {
+ processMessage(s.msg, s.send, s.done);
+ });
+ msgs = messages;
+ messages = [];
+ }
+ state = RESOLVED;
+ }).catch((error) => {
+ messages = [];
+ state = ERROR;
+ node.error(error);
+ });
+
+ }
+ catch(err) {
// eg SyntaxError - which v8 doesn't include line number information
// so we can't do better than this
- this.error(err);
+ updateErrorInfo(err);
+ node.error(err);
}
}
RED.nodes.registerType("function",FunctionNode);
RED.library.register("functions");
};
+
diff --git a/packages/node_modules/@node-red/nodes/core/function/16-range.html b/packages/node_modules/@node-red/nodes/core/function/16-range.html
index 77d123d56..f108a99ce 100644
--- a/packages/node_modules/@node-red/nodes/core/function/16-range.html
+++ b/packages/node_modules/@node-red/nodes/core/function/16-range.html
@@ -1,5 +1,5 @@
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js
index 4debeacde..cda1afadf 100644
--- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js
+++ b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js
@@ -24,6 +24,8 @@ module.exports = function(RED) {
this.op2 = n.op2 || "0";
this.op1type = n.op1type || "str";
this.op2type = n.op2type || "str";
+ this.second = (n.outputs == 2) ? true : false;
+ this.topic = n.topic || "topic";
if (this.op1type === 'val') {
if (this.op1 === 'true' || this.op1 === 'false') {
@@ -111,8 +113,15 @@ module.exports = function(RED) {
processMessageQueue(msg);
});
+ var stat = function() {
+ var l = Object.keys(node.topics).length;
+ if (l === 0) { return {} }
+ else if (l === 1) { return {fill:"blue",shape:"dot"} }
+ else return {fill:"blue",shape:"dot",text:l};
+ }
+
var processMessage = function(msg) {
- var topic = msg.topic || "_none";
+ var topic = RED.util.getMessageProperty(msg,node.topic) || "_none";
var promise;
if (node.bytopic === "all") { topic = "_none"; }
node.topics[topic] = node.topics[topic] || {};
@@ -120,7 +129,7 @@ module.exports = function(RED) {
if (node.loop === true) { clearInterval(node.topics[topic].tout); }
else { clearTimeout(node.topics[topic].tout); }
delete node.topics[topic];
- node.status({});
+ node.status(stat());
}
else {
if (node.op2type === "payl") { npay[topic] = RED.util.cloneMessage(msg); }
@@ -189,27 +198,29 @@ module.exports = function(RED) {
}
promise.then(() => {
if (node.op2type === "payl") {
- node.send(npay[topic]);
+ if (node.second === true) { node.send([null,npay[topic]]); }
+ else { node.send(npay[topic]); }
delete npay[topic];
}
- else {
+ else {
msg2.payload = node.topics[topic].m2;
- node.send(msg2);
+ if (node.second === true) { node.send([null,msg2]); }
+ else { node.send(msg2); }
}
delete node.topics[topic];
- node.status({});
+ node.status(stat());
}).catch(err => {
node.error(err);
});
} else {
delete node.topics[topic];
- node.status({});
+ node.status(stat());
}
}, node.duration);
}
}
- node.status({fill:"blue",shape:"dot",text:" "});
+ node.status(stat());
if (node.op1type !== "nul") { node.send(RED.util.cloneMessage(msg)); }
});
});
@@ -245,13 +256,17 @@ module.exports = function(RED) {
}
}
delete node.topics[topic];
- node.status({});
- node.send(msg2);
+ node.status(stat());
+ if (node.second === true) { node.send([null,msg2]); }
+ else { node.send(msg2); }
}).catch(err => {
node.error(err);
});
}, node.duration);
}
+ // else {
+ // if (node.op2type === "payl") {node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
+ // }
}
return Promise.resolve();
}
@@ -264,7 +279,7 @@ module.exports = function(RED) {
delete node.topics[t];
}
}
- node.status({});
+ node.status(stat());
});
}
RED.nodes.registerType("trigger",TriggerNode);
diff --git a/packages/node_modules/@node-red/nodes/core/function/90-exec.html b/packages/node_modules/@node-red/nodes/core/function/90-exec.html
index c6102d397..4a4e8942c 100644
--- a/packages/node_modules/@node-red/nodes/core/function/90-exec.html
+++ b/packages/node_modules/@node-red/nodes/core/function/90-exec.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/de/network/06-httpproxy.html b/packages/node_modules/@node-red/nodes/locales/de/network/06-httpproxy.html
index 228da487b..1ece7efe0 100755
--- a/packages/node_modules/@node-red/nodes/locales/de/network/06-httpproxy.html
+++ b/packages/node_modules/@node-red/nodes/locales/de/network/06-httpproxy.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/de/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/locales/de/network/31-tcpin.html
index 2b22418dc..51ec15c6f 100755
--- a/packages/node_modules/@node-red/nodes/locales/de/network/31-tcpin.html
+++ b/packages/node_modules/@node-red/nodes/locales/de/network/31-tcpin.html
@@ -14,13 +14,13 @@
limitations under the License.
-->
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/function/90-exec.html b/packages/node_modules/@node-red/nodes/locales/en-US/function/90-exec.html
index 69447bc60..ff515e781 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/function/90-exec.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/function/90-exec.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/network/06-httpproxy.html b/packages/node_modules/@node-red/nodes/locales/en-US/network/06-httpproxy.html
index b17012e72..12bb3684c 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/network/06-httpproxy.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/network/06-httpproxy.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/network/32-udp.html b/packages/node_modules/@node-red/nodes/locales/en-US/network/32-udp.html
index 09e6aef34..666889be6 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/network/32-udp.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/network/32-udp.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-HTML.html b/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-HTML.html
index b9231663d..7b081976c 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-HTML.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-HTML.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/storage/23-watch.html b/packages/node_modules/@node-red/nodes/locales/en-US/storage/23-watch.html
index 4a28cfcab..bc6e4ad31 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/storage/23-watch.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/storage/23-watch.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/function/90-exec.html b/packages/node_modules/@node-red/nodes/locales/ja/function/90-exec.html
index 7eb75b10a..d034f71e1 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/function/90-exec.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/function/90-exec.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/network/06-httpproxy.html b/packages/node_modules/@node-red/nodes/locales/ja/network/06-httpproxy.html
index 03beddb8d..24b15aa29 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/network/06-httpproxy.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/network/06-httpproxy.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/locales/ja/network/31-tcpin.html
index efe82cbb1..e63c93ae5 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/network/31-tcpin.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/network/31-tcpin.html
@@ -14,12 +14,12 @@
limitations under the License.
-->
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/network/32-udp.html b/packages/node_modules/@node-red/nodes/locales/ja/network/32-udp.html
index ec07a865e..fffcbcec5 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/network/32-udp.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/network/32-udp.html
@@ -14,13 +14,13 @@
limitations under the License.
-->
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/parsers/70-HTML.html b/packages/node_modules/@node-red/nodes/locales/ja/parsers/70-HTML.html
index eb7b00dff..19be36aed 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/parsers/70-HTML.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/parsers/70-HTML.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
+
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/storage/23-watch.html b/packages/node_modules/@node-red/nodes/locales/ja/storage/23-watch.html
index 45f658c05..3a4594ccc 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/storage/23-watch.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/storage/23-watch.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ko/network/06-httpproxy.html b/packages/node_modules/@node-red/nodes/locales/ko/network/06-httpproxy.html
index 4357c7f2b..cdfccd799 100644
--- a/packages/node_modules/@node-red/nodes/locales/ko/network/06-httpproxy.html
+++ b/packages/node_modules/@node-red/nodes/locales/ko/network/06-httpproxy.html
@@ -14,7 +14,7 @@
limitations under the License.
-->
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/locales/ko/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/locales/ko/network/31-tcpin.html
index 1c665bb8d..53c61e679 100644
--- a/packages/node_modules/@node-red/nodes/locales/ko/network/31-tcpin.html
+++ b/packages/node_modules/@node-red/nodes/locales/ko/network/31-tcpin.html
@@ -14,12 +14,12 @@
limitations under the License.
-->
-
-
-
-
-
-