1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Resolve merge conflict

This commit is contained in:
Hiroyasu Nishiyama 2022-12-27 23:45:25 +09:00
commit 99bd957ea0
26 changed files with 549 additions and 324 deletions

View File

@ -26,13 +26,13 @@
} }
], ],
"dependencies": { "dependencies": {
"acorn": "8.7.1", "acorn": "8.8.1",
"acorn-walk": "8.2.0", "acorn-walk": "8.2.0",
"ajv": "8.11.0", "ajv": "8.11.2",
"async-mutex": "0.3.2", "async-mutex": "0.4.0",
"basic-auth": "2.0.1", "basic-auth": "2.0.1",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.20.0", "body-parser": "1.20.1",
"cheerio": "1.0.0-rc.10", "cheerio": "1.0.0-rc.10",
"clone": "2.1.2", "clone": "2.1.2",
"content-type": "1.0.4", "content-type": "1.0.4",
@ -40,16 +40,16 @@
"cookie-parser": "1.4.6", "cookie-parser": "1.4.6",
"cors": "2.8.5", "cors": "2.8.5",
"cronosjs": "1.7.1", "cronosjs": "1.7.1",
"denque": "2.0.1", "denque": "2.1.0",
"express": "4.18.1", "express": "4.18.2",
"express-session": "1.17.3", "express-session": "1.17.3",
"form-data": "4.0.0", "form-data": "4.0.0",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"got": "11.8.5", "got": "11.8.5",
"hash-sum": "2.0.0", "hash-sum": "2.0.0",
"hpagent": "1.0.0", "hpagent": "1.2.0",
"https-proxy-agent": "5.0.1", "https-proxy-agent": "5.0.1",
"i18next": "21.8.14", "i18next": "21.10.0",
"iconv-lite": "0.6.3", "iconv-lite": "0.6.3",
"is-utf8": "0.2.1", "is-utf8": "0.2.1",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
@ -60,7 +60,7 @@
"memorystore": "1.6.7", "memorystore": "1.6.7",
"mime": "3.0.0", "mime": "3.0.0",
"moment": "2.29.4", "moment": "2.29.4",
"moment-timezone": "0.5.34", "moment-timezone": "0.5.39",
"mqtt": "4.3.7", "mqtt": "4.3.7",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"mustache": "4.2.0", "mustache": "4.2.0",
@ -73,19 +73,19 @@
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.1", "raw-body": "2.5.1",
"semver": "7.3.7", "semver": "7.3.8",
"tar": "6.1.11", "tar": "6.1.12",
"tough-cookie": "4.0.0", "tough-cookie": "4.1.2",
"uglify-js": "3.16.2", "uglify-js": "3.17.4",
"uuid": "8.3.2", "uuid": "8.3.2",
"ws": "7.5.6", "ws": "7.5.6",
"xml2js": "0.4.23" "xml2js": "0.4.23"
}, },
"optionalDependencies": { "optionalDependencies": {
"bcrypt": "5.0.1" "bcrypt": "5.1.0"
}, },
"devDependencies": { "devDependencies": {
"dompurify": "2.3.9", "dompurify": "2.4.1",
"grunt": "1.5.3", "grunt": "1.5.3",
"grunt-chmod": "~1.1.1", "grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3", "grunt-cli": "~1.4.3",
@ -108,13 +108,13 @@
"i18next-http-backend": "1.4.1", "i18next-http-backend": "1.4.1",
"jquery-i18next": "1.2.1", "jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "4.0.18", "marked": "4.2.3",
"minami": "1.2.3", "minami": "1.2.3",
"mocha": "9.2.2", "mocha": "9.2.2",
"node-red-node-test-helper": "^0.3.0", "node-red-node-test-helper": "^0.3.0",
"nodemon": "2.0.19", "nodemon": "2.0.20",
"proxy": "^1.0.2", "proxy": "^1.0.2",
"sass": "1.53.0", "sass": "1.56.1",
"should": "13.2.3", "should": "13.2.3",
"sinon": "11.1.2", "sinon": "11.1.2",
"stoppable": "^1.1.0", "stoppable": "^1.1.0",

View File

@ -19,11 +19,11 @@
"@node-red/util": "3.1.0-beta.0", "@node-red/util": "3.1.0-beta.0",
"@node-red/editor-client": "3.1.0-beta.0", "@node-red/editor-client": "3.1.0-beta.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.20.0", "body-parser": "1.20.1",
"clone": "2.1.2", "clone": "2.1.2",
"cors": "2.8.5", "cors": "2.8.5",
"express-session": "1.17.3", "express-session": "1.17.3",
"express": "4.18.1", "express": "4.18.2",
"memorystore": "1.6.7", "memorystore": "1.6.7",
"mime": "3.0.0", "mime": "3.0.0",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
@ -35,6 +35,6 @@
"ws": "7.5.6" "ws": "7.5.6"
}, },
"optionalDependencies": { "optionalDependencies": {
"bcrypt": "5.0.1" "bcrypt": "5.1.0"
} }
} }

View File

@ -57,18 +57,22 @@
"addFlowToRight": "Add flow to the right", "addFlowToRight": "Add flow to the right",
"hideFlow": "Hide flow", "hideFlow": "Hide flow",
"hideOtherFlows": "Hide other flows", "hideOtherFlows": "Hide other flows",
"showAllFlows": "Show all flows", "showAllFlows": "Show all flows (__count__ hidden)",
"hideAllFlows": "Hide all flows", "hideAllFlows": "Hide all flows",
"hiddenFlows": "List __count__ hidden flow", "hiddenFlows": "List __count__ hidden flow",
"hiddenFlows_plural": "List __count__ hidden flows", "hiddenFlows_plural": "List __count__ hidden flows",
"showLastHiddenFlow": "Show last hidden flow", "showLastHiddenFlow": "Reopen hidden flow",
"listFlows": "List flows", "listFlows": "List flows",
"listSubflows": "List subflows", "listSubflows": "List subflows",
"status": "Status", "status": "Status",
"enabled": "Enabled", "enabled": "Enabled",
"disabled": "Disabled", "disabled": "Disabled",
"info": "Description", "info": "Description",
"selectNodes": "Click nodes to select" "selectNodes": "Click nodes to select",
"enableFlow": "Enable flow",
"disableFlow": "Disable flow",
"moveToStart": "Move flow to start",
"moveToEnd": "Move flow to end"
}, },
"menu": { "menu": {
"label": { "label": {
@ -684,7 +688,8 @@
"globalConfig": "Global Configuration Nodes", "globalConfig": "Global Configuration Nodes",
"triggerAction": "Trigger action", "triggerAction": "Trigger action",
"find": "Find in workspace", "find": "Find in workspace",
"copyItemUrl": "Copy item url" "copyItemUrl": "Copy item url",
"copyURL2Clipboard": "Copied url to clipboard"
}, },
"help": { "help": {
"name": "Help", "name": "Help",

View File

@ -68,7 +68,11 @@
"enabled": "有効", "enabled": "有効",
"disabled": "無効", "disabled": "無効",
"info": "詳細", "info": "詳細",
"selectNodes": "ノードをクリックして選択" "selectNodes": "ノードをクリックして選択",
"enableFlow": "フローを有効化",
"disableFlow": "フローを無効化",
"moveToStart": "フローを先頭へ移動",
"moveToEnd": "フローを最後へ移動"
}, },
"menu": { "menu": {
"label": { "label": {
@ -683,7 +687,9 @@
"empty": "空", "empty": "空",
"globalConfig": "グローバル設定ノード", "globalConfig": "グローバル設定ノード",
"triggerAction": "アクションを実行", "triggerAction": "アクションを実行",
"find": "ワークスペース内を検索" "find": "ワークスペース内を検索",
"copyItemUrl": "要素のURLをコピー",
"copyURL2Clipboard": "URLをクリップボードにコピーしました"
}, },
"help": { "help": {
"name": "ヘルプ", "name": "ヘルプ",
@ -1168,8 +1174,7 @@
"takeATour": "ツアーを開始", "takeATour": "ツアーを開始",
"start": "開始", "start": "開始",
"next": "次へ", "next": "次へ",
"welcomeTours": "ウェルカムツアー", "welcomeTours": "ウェルカムツアー"
"tours": "ツアー"
}, },
"diagnostics": { "diagnostics": {
"title": "システム情報" "title": "システム情報"
@ -1348,7 +1353,9 @@
"show-project-settings": "プロジェクト設定を表示", "show-project-settings": "プロジェクト設定を表示",
"show-version-control-tab": "バージョンコントロールタブを表示", "show-version-control-tab": "バージョンコントロールタブを表示",
"start-flows": "フローを開始", "start-flows": "フローを開始",
"stop-flows": "フローを停止" "stop-flows": "フローを停止",
"copy-item-url": "要素のURLをコピー",
"copy-item-edit-url": "要素の編集URLをコピー"
}, },
"env-var": { "env-var": {
"environment": "環境変数", "environment": "環境変数",

View File

@ -2834,7 +2834,7 @@ RED.nodes = (function() {
}, },
addWorkspace: addWorkspace, addWorkspace: addWorkspace,
removeWorkspace: removeWorkspace, removeWorkspace: removeWorkspace,
getWorkspaceOrder: function() { return workspacesOrder }, getWorkspaceOrder: function() { return [...workspacesOrder] },
setWorkspaceOrder: function(order) { workspacesOrder = order; }, setWorkspaceOrder: function(order) { workspacesOrder = order; },
workspace: getWorkspace, workspace: getWorkspace,

View File

@ -423,11 +423,10 @@ RED.clipboard = (function() {
} }
} }
function showImportNodes(mode) { function showImportNodes(library = 'clipboard') {
if (disabled) { if (disabled) {
return; return;
} }
mode = mode || "clipboard";
dialogContainer.empty(); dialogContainer.empty();
dialogContainer.append($(importNodesDialog)); dialogContainer.append($(importNodesDialog));
@ -533,8 +532,8 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click"); $("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
}) })
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode); tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+library);
if (mode === 'clipboard') { if (library === 'clipboard') {
setTimeout(function() { setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus"); $("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100) },100)
@ -558,13 +557,16 @@ RED.clipboard = (function() {
}); });
} }
function showExportNodes(mode) { /**
* Show the export dialog
* @params library which export destination to show
* @params mode whether to default to 'auto' (default) or 'flow'
**/
function showExportNodes(library = 'clipboard', mode = 'auto' ) {
if (disabled) { if (disabled) {
return; return;
} }
mode = mode || "clipboard";
dialogContainer.empty(); dialogContainer.empty();
dialogContainer.append($(exportNodesDialog)); dialogContainer.append($(exportNodesDialog));
@ -654,7 +656,12 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select(); $("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select();
dialogContainer.i18n(); dialogContainer.i18n();
var format = RED.settings.flowFilePretty ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini"; var format = RED.settings.flowFilePretty ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini";
const userFormat = RED.settings.get("editor.dialog.export.pretty")
if (userFormat === false || userFormat === true) {
format = userFormat ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini";
}
$("#red-ui-clipboard-dialog-export-fmt-group > a").on("click", function(evt) { $("#red-ui-clipboard-dialog-export-fmt-group > a").on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
@ -670,7 +677,8 @@ RED.clipboard = (function() {
var nodes = JSON.parse(flow); var nodes = JSON.parse(flow);
format = $(this).attr('id'); format = $(this).attr('id');
if (format === 'red-ui-clipboard-dialog-export-fmt-full') { const pretty = format === "red-ui-clipboard-dialog-export-fmt-full";
if (pretty) {
flow = JSON.stringify(nodes,null,4); flow = JSON.stringify(nodes,null,4);
} else { } else {
flow = JSON.stringify(nodes); flow = JSON.stringify(nodes);
@ -679,6 +687,7 @@ RED.clipboard = (function() {
setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50); setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50);
$("#red-ui-clipboard-dialog-export-text").trigger("focus"); $("#red-ui-clipboard-dialog-export-text").trigger("focus");
RED.settings.set("editor.dialog.export.pretty", pretty)
} }
}); });
@ -766,12 +775,15 @@ RED.clipboard = (function() {
} }
} }
} }
if (mode === 'flow' && !$("#red-ui-clipboard-dialog-export-rng-flow").hasClass('disabled')) {
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
}
if (format === "red-ui-clipboard-dialog-export-fmt-full") { if (format === "red-ui-clipboard-dialog-export-fmt-full") {
$("#red-ui-clipboard-dialog-export-fmt-full").trigger("click"); $("#red-ui-clipboard-dialog-export-fmt-full").trigger("click");
} else { } else {
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click"); $("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click");
} }
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode); tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+library);
var dialogHeight = 400; var dialogHeight = 400;
var winHeight = $(window).height(); var winHeight = $(window).height();

View File

@ -94,8 +94,8 @@ RED.menu = (function() {
var link = $(linkContent).appendTo(item); var link = $(linkContent).appendTo(item);
opt.link = link; opt.link = link;
if (typeof opt.onselect === 'string') { if (typeof opt.onselect === 'string' || opt.shortcut) {
var shortcut = RED.keyboard.getShortcut(opt.onselect); var shortcut = opt.shortcut || RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) { if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label")); opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label"));
} }

View File

@ -141,7 +141,29 @@ RED.tabs = (function() {
}) })
} }
if (options.contextmenu) {
wrapper.on('contextmenu', function(evt) {
let clickedTab
let target = evt.target
while(target.nodeName !== 'A' && target.nodeName !== 'UL' && target.nodeName !== 'BODY') {
target = target.parentNode
}
if (target.nodeName === 'A') {
const href = target.getAttribute('href')
if (href) {
clickedTab = tabs[href.slice(1)]
}
}
evt.preventDefault()
evt.stopPropagation()
RED.contextMenu.show({
x:evt.clientX-5,
y:evt.clientY-5,
options: options.contextmenu(clickedTab)
})
return false
})
}
var scrollLeft; var scrollLeft;
var scrollRight; var scrollRight;
@ -809,17 +831,17 @@ RED.tabs = (function() {
}); });
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
} }
if (tab.hideable) { // if (tab.hideable) {
li.addClass("red-ui-tabs-closeable") // li.addClass("red-ui-tabs-closeable")
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li); // var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
closeLink.append('<i class="fa fa-eye" />'); // closeLink.append('<i class="fa fa-eye" />');
closeLink.append('<i class="fa fa-eye-slash" />'); // closeLink.append('<i class="fa fa-eye-slash" />');
closeLink.on("click",function(event) { // closeLink.on("click",function(event) {
event.preventDefault(); // event.preventDefault();
hideTab(tab.id); // hideTab(tab.id);
}); // });
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); // RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
} // }
var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li); var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
if (options.onselect) { if (options.onselect) {
@ -938,6 +960,9 @@ RED.tabs = (function() {
activeIndex: function() { activeIndex: function() {
return ul.find("li.active").index() return ul.find("li.active").index()
}, },
getTabIndex: function (id) {
return ul.find("a[href='#"+id+"']").parent().index()
},
contains: function(id) { contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0; return ul.find("a[href='#"+id+"']").length > 0;
}, },

View File

@ -1,21 +1,6 @@
RED.contextMenu = (function () { RED.contextMenu = (function () {
let menu; let menu;
function createMenu() {
// menu = RED.popover.menu({
// options: [
// {
// label: 'delete selection',
// onselect: function() {
// RED.actions.invoke('core:delete-selection')
// RED.view.focus()
// }
// },
// { label: 'world' }
// ],
// width: 200,
// })
}
function disposeMenu() { function disposeMenu() {
$(document).off("mousedown.red-ui-workspace-context-menu"); $(document).off("mousedown.red-ui-workspace-context-menu");
@ -28,7 +13,10 @@ RED.contextMenu = (function () {
if (menu) { if (menu) {
menu.remove() menu.remove()
} }
let menuItems = []
if (options.options) {
menuItems = options.options
} else if (options.type === 'workspace') {
const selection = RED.view.selection() const selection = RED.view.selection()
const noSelection = !selection || Object.keys(selection).length === 0 const noSelection = !selection || Object.keys(selection).length === 0
const hasSelection = (selection.nodes && selection.nodes.length > 0); const hasSelection = (selection.nodes && selection.nodes.length > 0);
@ -53,7 +41,7 @@ RED.contextMenu = (function () {
addY = gridSize * Math.floor(addY / gridSize) addY = gridSize * Math.floor(addY / gridSize)
} }
const menuItems = [ menuItems.push(
{ onselect: 'core:show-action-list', onpostselect: function () { } }, { onselect: 'core:show-action-list', onpostselect: function () { } },
{ {
label: RED._("contextMenu.insert"), label: RED._("contextMenu.insert"),
@ -110,7 +98,7 @@ RED.contextMenu = (function () {
} }
] )
menuItems.push( menuItems.push(
null, null,
@ -137,6 +125,7 @@ RED.contextMenu = (function () {
} }
} }
}
var direction = "right"; var direction = "right";
var MENU_WIDTH = 500; // can not use menu width here var MENU_WIDTH = 500; // can not use menu width here

View File

@ -431,12 +431,29 @@ RED.subflow = (function() {
$("#red-ui-subflow-delete").on("click", function(event) { $("#red-ui-subflow-delete").on("click", function(event) {
event.preventDefault(); event.preventDefault();
var subflow = RED.nodes.subflow(RED.workspaces.active()); RED.subflow.delete(RED.workspaces.active())
});
refreshToolbar(activeSubflow);
$("#red-ui-workspace-chart").css({"margin-top": "40px"});
$("#red-ui-workspace-toolbar").show();
}
function hideWorkspaceToolbar() {
$("#red-ui-workspace-toolbar").hide().empty();
$("#red-ui-workspace-chart").css({"margin-top": "0"});
}
function deleteSubflow(id) {
const subflow = RED.nodes.subflow(id || RED.workspaces.active());
if (!subflow) {
return
}
if (subflow.instances.length > 0) { if (subflow.instances.length > 0) {
var msg = $('<div>') const msg = $('<div>')
$('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg); $('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
$('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg); $('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg);
var confirmDeleteNotification = RED.notify(msg, { const confirmDeleteNotification = RED.notify(msg, {
modal: true, modal: true,
fixed: true, fixed: true,
buttons: [ buttons: [
@ -462,26 +479,13 @@ RED.subflow = (function() {
completeDelete(); completeDelete();
} }
function completeDelete() { function completeDelete() {
var startDirty = RED.nodes.dirty(); const startDirty = RED.nodes.dirty();
var historyEvent = removeSubflow(RED.workspaces.active()); const historyEvent = removeSubflow(subflow.id);
historyEvent.t = 'delete'; historyEvent.t = 'delete';
historyEvent.dirty = startDirty; historyEvent.dirty = startDirty;
RED.history.push(historyEvent); RED.history.push(historyEvent);
} }
});
refreshToolbar(activeSubflow);
$("#red-ui-workspace-chart").css({"margin-top": "40px"});
$("#red-ui-workspace-toolbar").show();
} }
function hideWorkspaceToolbar() {
$("#red-ui-workspace-toolbar").hide().empty();
$("#red-ui-workspace-chart").css({"margin-top": "0"});
}
function removeSubflow(id, keepInstanceNodes) { function removeSubflow(id, keepInstanceNodes) {
// TODO: A lot of this logic is common with RED.nodes.removeWorkspace // TODO: A lot of this logic is common with RED.nodes.removeWorkspace
var removedNodes = []; var removedNodes = [];
@ -1323,7 +1327,10 @@ RED.subflow = (function() {
init: init, init: init,
createSubflow: createSubflow, createSubflow: createSubflow,
convertToSubflow: convertToSubflow, convertToSubflow: convertToSubflow,
// removeSubflow: Internal function to remove subflow
removeSubflow: removeSubflow, removeSubflow: removeSubflow,
// delete: Prompt user for confirmation
delete: deleteSubflow,
refresh: refresh, refresh: refresh,
removeInput: removeSubflowInput, removeInput: removeSubflowInput,
removeOutput: removeSubflowOutput, removeOutput: removeSubflowOutput,

View File

@ -1211,7 +1211,7 @@ RED.view.tools = (function() {
url += '/edit' url += '/edit'
} }
if (RED.clipboard.copyText(url)) { if (RED.clipboard.copyText(url)) {
RED.notify('Copied url to clipboard', { timeout: 2000 }) RED.notify(RED._("sidebar.info.copyURL2Clipboard"), { timeout: 2000 })
} }
} }
} }

View File

@ -211,6 +211,7 @@ RED.view = (function() {
evt.preventDefault() evt.preventDefault()
evt.stopPropagation() evt.stopPropagation()
RED.contextMenu.show({ RED.contextMenu.show({
type: 'workspace',
x:evt.clientX-5, x:evt.clientX-5,
y:evt.clientY-5 y:evt.clientY-5
}) })

View File

@ -126,6 +126,166 @@ RED.workspaces = (function() {
var workspace_tabs; var workspace_tabs;
var workspaceTabCount = 0; var workspaceTabCount = 0;
function getMenuItems(isMenuButton, tab) {
let hiddenFlows = new Set()
for (let i = 0; i < hideStack.length; i++) {
let ids = hideStack[i]
if (!Array.isArray(ids)) {
ids = [ids]
}
ids.forEach(id => {
if (RED.nodes.workspace(id)) {
hiddenFlows.add(id)
}
})
}
const hiddenflowCount = hiddenFlows.size;
let activeWorkspace = tab || RED.nodes.workspace(RED.workspaces.active()) || RED.nodes.subflow(RED.workspaces.active())
let isFlowDisabled = activeWorkspace ? activeWorkspace.disabled : false
var menuItems = []
if (isMenuButton) {
menuItems.push({
id:"red-ui-tabs-menu-option-search-flows",
label: RED._("workspace.listFlows"),
onselect: "core:list-flows"
},
{
id:"red-ui-tabs-menu-option-search-subflows",
label: RED._("workspace.listSubflows"),
onselect: "core:list-subflows"
},
null)
}
menuItems.push(
{
id:"red-ui-tabs-menu-option-add-flow",
label: RED._("workspace.addFlow"),
onselect: "core:add-flow"
}
)
if (isMenuButton || !!tab) {
menuItems.push(
{
id:"red-ui-tabs-menu-option-add-flow-right",
label: RED._("workspace.addFlowToRight"),
shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
onselect: function() {
RED.actions.invoke("core:add-flow-to-right", tab)
}
},
null
)
if (activeWorkspace && activeWorkspace.type === 'tab') {
menuItems.push(
isFlowDisabled ? {
label: RED._("workspace.enableFlow"),
shortcut: RED.keyboard.getShortcut("core:enable-flow"),
onselect: function() {
RED.actions.invoke("core:enable-flow", tab?tab.id:undefined)
}
} : {
label: RED._("workspace.disableFlow"),
shortcut: RED.keyboard.getShortcut("core:disable-flow"),
onselect: function() {
RED.actions.invoke("core:disable-flow", tab?tab.id:undefined)
}
}
)
}
const currentTabs = workspace_tabs.listTabs()
const activeIndex = currentTabs.findIndex(id => id === activeWorkspace.id)
menuItems.push(
{
label: RED._("workspace.moveToStart"),
shortcut: RED.keyboard.getShortcut("core:move-flow-to-start"),
onselect: function() {
RED.actions.invoke("core:move-flow-to-start", tab?tab.id:undefined)
},
disabled: activeIndex === 0
},
{
label: RED._("workspace.moveToEnd"),
shortcut: RED.keyboard.getShortcut("core:move-flow-to-end"),
onselect: function() {
RED.actions.invoke("core:move-flow-to-end", tab?tab.id:undefined)
},
disabled: activeIndex === currentTabs.length - 1
}
)
}
menuItems.push(null)
if (isMenuButton || !!tab) {
menuItems.push(
{
id:"red-ui-tabs-menu-option-add-hide-flows",
label: RED._("workspace.hideFlow"),
shortcut: RED.keyboard.getShortcut("core:hide-flow"),
onselect: function() {
RED.actions.invoke("core:hide-flow", tab)
}
},
{
id:"red-ui-tabs-menu-option-add-hide-other-flows",
label: RED._("workspace.hideOtherFlows"),
shortcut: RED.keyboard.getShortcut("core:hide-other-flows"),
onselect: function() {
RED.actions.invoke("core:hide-other-flows", tab)
}
}
)
}
menuItems.push(
{
id:"red-ui-tabs-menu-option-add-hide-all-flows",
label: RED._("workspace.hideAllFlows"),
onselect: "core:hide-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-all-flows",
disabled: hiddenflowCount === 0,
label: RED._("workspace.showAllFlows", { count: hiddenflowCount }),
onselect: "core:show-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-last-flow",
disabled: hideStack.length === 0,
label: RED._("workspace.showLastHiddenFlow"),
onselect: "core:show-last-hidden-flow"
}
)
if (tab) {
menuItems.push(
null,
{
label: RED._("common.label.delete"),
onselect: function() {
if (tab.type === 'tab') {
RED.workspaces.delete(tab)
} else if (tab.type === 'subflow') {
RED.subflow.delete(tab.id)
}
}
},
{
label: RED._("menu.label.export"),
shortcut: RED.keyboard.getShortcut("core:show-export-dialog"),
onselect: function() {
RED.workspaces.show(tab.id)
RED.actions.invoke('core:show-export-dialog', null, 'flow')
}
}
)
}
// if (isMenuButton && hiddenflowCount > 0) {
// menuItems.unshift({
// label: RED._("workspace.hiddenFlows",{count: hiddenflowCount}),
// onselect: "core:list-hidden-flows"
// })
// }
return menuItems;
}
function createWorkspaceTabs() { function createWorkspaceTabs() {
workspace_tabs = RED.tabs.create({ workspace_tabs = RED.tabs.create({
id: "red-ui-workspace-tabs", id: "red-ui-workspace-tabs",
@ -194,8 +354,14 @@ RED.workspaces = (function() {
}, },
dirty:RED.nodes.dirty() dirty:RED.nodes.dirty()
}); });
// Only mark flows dirty if flow-order has changed (excluding subflows)
const filteredOldOrder = oldOrder.filter(id => !!RED.nodes.workspace(id))
const filteredNewOrder = newOrder.filter(id => !!RED.nodes.workspace(id))
if (JSON.stringify(filteredOldOrder) !== JSON.stringify(filteredNewOrder)) {
RED.nodes.dirty(true); RED.nodes.dirty(true);
setWorkspaceOrder(newOrder); setWorkspaceOrder(newOrder);
}
}, },
onselect: function(selectedTabs) { onselect: function(selectedTabs) {
RED.view.select(false) RED.view.select(false)
@ -214,12 +380,12 @@ RED.workspaces = (function() {
}, },
onhide: function(tab) { onhide: function(tab) {
hideStack.push(tab.id); hideStack.push(tab.id);
if (tab.type === "tab") {
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
hiddenTabs[tab.id] = true; hiddenTabs[tab.id] = true;
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs)); RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
RED.events.emit("workspace:hide",{workspace: tab.id}) RED.events.emit("workspace:hide",{workspace: tab.id})
}
}, },
onshow: function(tab) { onshow: function(tab) {
removeFromHideStack(tab.id); removeFromHideStack(tab.id);
@ -234,77 +400,8 @@ RED.workspaces = (function() {
scrollable: true, scrollable: true,
addButton: "core:add-flow", addButton: "core:add-flow",
addButtonCaption: RED._("workspace.addFlow"), addButtonCaption: RED._("workspace.addFlow"),
menu: function() { menu: function() { return getMenuItems(true) },
var menuItems = [ contextmenu: function(tab) { return getMenuItems(false, tab) }
{
id:"red-ui-tabs-menu-option-search-flows",
label: RED._("workspace.listFlows"),
onselect: "core:list-flows"
},
{
id:"red-ui-tabs-menu-option-search-subflows",
label: RED._("workspace.listSubflows"),
onselect: "core:list-subflows"
},
null,
{
id:"red-ui-tabs-menu-option-add-flow",
label: RED._("workspace.addFlow"),
onselect: "core:add-flow"
},
{
id:"red-ui-tabs-menu-option-add-flow-right",
label: RED._("workspace.addFlowToRight"),
onselect: "core:add-flow-to-right"
},
null,
{
id:"red-ui-tabs-menu-option-add-hide-flows",
label: RED._("workspace.hideFlow"),
onselect: "core:hide-flow"
},
{
id:"red-ui-tabs-menu-option-add-hide-other-flows",
label: RED._("workspace.hideOtherFlows"),
onselect: "core:hide-other-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-all-flows",
label: RED._("workspace.showAllFlows"),
onselect: "core:show-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-hide-all-flows",
label: RED._("workspace.hideAllFlows"),
onselect: "core:hide-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-last-flow",
label: RED._("workspace.showLastHiddenFlow"),
onselect: "core:show-last-hidden-flow"
}
]
let hiddenFlows = new Set()
for (let i = 0; i < hideStack.length; i++) {
let ids = hideStack[i]
if (!Array.isArray(ids)) {
ids = [ids]
}
ids.forEach(id => {
if (RED.nodes.workspace(id)) {
hiddenFlows.add(id)
}
})
}
const flowCount = hiddenFlows.size;
if (flowCount > 0) {
menuItems.unshift({
label: RED._("workspace.hiddenFlows",{count: flowCount}),
onselect: "core:list-hidden-flows"
})
}
return menuItems;
}
}); });
workspaceTabCount = 0; workspaceTabCount = 0;
} }
@ -355,17 +452,32 @@ RED.workspaces = (function() {
}); });
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)}); RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
RED.actions.add("core:add-flow-to-right",function(opts) { addWorkspace(undefined,undefined,workspace_tabs.activeIndex()+1)}); RED.actions.add("core:add-flow-to-right",function(workspace) {
let index
if (workspace) {
index = workspace_tabs.getTabIndex(workspace.id)+1
} else {
index = workspace_tabs.activeIndex()+1
}
addWorkspace(undefined,undefined,index)
});
RED.actions.add("core:edit-flow",editWorkspace); RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace); RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace); RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace); RED.actions.add("core:disable-flow",disableWorkspace);
RED.actions.add("core:move-flow-to-start", function(id) { moveWorkspace(id, 'start') });
RED.actions.add("core:move-flow-to-end", function(id) { moveWorkspace(id, 'end') });
RED.actions.add("core:hide-flow", function() { RED.actions.add("core:hide-flow", function(workspace) {
var selection = workspace_tabs.selection(); let selection
if (workspace) {
selection = [workspace]
} else {
selection = workspace_tabs.selection();
if (selection.length === 0) { if (selection.length === 0) {
selection = [{id:activeWorkspace}] selection = [{id:activeWorkspace}]
} }
}
var hiddenTabs = []; var hiddenTabs = [];
selection.forEach(function(ws) { selection.forEach(function(ws) {
RED.workspaces.hide(ws.id); RED.workspaces.hide(ws.id);
@ -378,11 +490,16 @@ RED.workspaces = (function() {
workspace_tabs.clearSelection(); workspace_tabs.clearSelection();
}) })
RED.actions.add("core:hide-other-flows", function() { RED.actions.add("core:hide-other-flows", function(workspace) {
var selection = workspace_tabs.selection(); let selection
if (workspace) {
selection = [workspace]
} else {
selection = workspace_tabs.selection();
if (selection.length === 0) { if (selection.length === 0) {
selection = [{id:activeWorkspace}] selection = [{id:activeWorkspace}]
} }
}
var selected = new Set(selection.map(function(ws) { return ws.id })) var selected = new Set(selection.map(function(ws) { return ws.id }))
var currentTabs = workspace_tabs.listTabs(); var currentTabs = workspace_tabs.listTabs();
@ -535,16 +652,46 @@ RED.workspaces = (function() {
} }
} }
function moveWorkspace(id, direction) {
const workspace = RED.nodes.workspace(id||activeWorkspace) || RED.nodes.subflow(id||activeWorkspace);
if (!workspace) {
return;
}
const currentOrder = workspace_tabs.listTabs()
const oldOrder = [...currentOrder]
const currentIndex = currentOrder.findIndex(id => id === workspace.id)
currentOrder.splice(currentIndex, 1)
if (direction === 'start') {
currentOrder.unshift(workspace.id)
} else if (direction === 'end') {
currentOrder.push(workspace.id)
}
const newOrder = setWorkspaceOrder(currentOrder)
if (JSON.stringify(newOrder) !== JSON.stringify(oldOrder)) {
RED.history.push({
t:'reorder',
workspaces: {
from:oldOrder,
to:newOrder
},
dirty:RED.nodes.dirty()
});
const filteredOldOrder = oldOrder.filter(id => !!RED.nodes.workspace(id))
const filteredNewOrder = newOrder.filter(id => !!RED.nodes.workspace(id))
if (JSON.stringify(filteredOldOrder) !== JSON.stringify(filteredNewOrder)) {
RED.nodes.dirty(true);
}
}
}
function setWorkspaceOrder(order) { function setWorkspaceOrder(order) {
var newOrder = order.filter(function(id) { var newOrder = order.filter(id => !!RED.nodes.workspace(id))
return RED.nodes.workspace(id) !== undefined;
})
var currentOrder = RED.nodes.getWorkspaceOrder(); var currentOrder = RED.nodes.getWorkspaceOrder();
if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) { if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) {
RED.nodes.setWorkspaceOrder(newOrder); RED.nodes.setWorkspaceOrder(newOrder);
RED.events.emit("flows:reorder",newOrder); RED.events.emit("flows:reorder",newOrder);
} }
workspace_tabs.order(order); workspace_tabs.order(order);
return newOrder
} }
function flashTab(tabId) { function flashTab(tabId) {

View File

@ -10,6 +10,7 @@
<option value="scale" data-i18n="range.scale.payload"></option> <option value="scale" data-i18n="range.scale.payload"></option>
<option value="clamp" data-i18n="range.scale.limit"></option> <option value="clamp" data-i18n="range.scale.limit"></option>
<option value="roll" data-i18n="range.scale.wrap"></option> <option value="roll" data-i18n="range.scale.wrap"></option>
<option value="drop" data-i18n="range.scale.drop"></option>
</select> </select>
</div> </div>
<br/> <br/>

View File

@ -32,11 +32,15 @@ module.exports = function(RED) {
if (value !== undefined) { if (value !== undefined) {
var n = Number(value); var n = Number(value);
if (!isNaN(n)) { if (!isNaN(n)) {
if (node.action == "clamp") { if (node.action === "drop") {
if (n < node.minin) { done(); return; }
if (n > node.maxin) { done(); return; }
}
if (node.action === "clamp") {
if (n < node.minin) { n = node.minin; } if (n < node.minin) { n = node.minin; }
if (n > node.maxin) { n = node.maxin; } if (n > node.maxin) { n = node.maxin; }
} }
if (node.action == "roll") { if (node.action === "roll") {
var divisor = node.maxin - node.minin; var divisor = node.maxin - node.minin;
n = ((n - node.minin) % divisor + divisor) % divisor + node.minin; n = ((n - node.minin) % divisor + divisor) % divisor + node.minin;
} }

View File

@ -19,9 +19,9 @@ module.exports = function(RED) {
function CSVNode(n) { function CSVNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.template = (n.temp || ""); this.template = (n.temp || "");
this.sep = (n.sep || ',').replace("\\t","\t").replace("\\n","\n").replace("\\r","\r"); this.sep = (n.sep || ',').replace(/\\t/g,"\t").replace(/\\n/g,"\n").replace(/\\r/g,"\r");
this.quo = '"'; this.quo = '"';
this.ret = (n.ret || "\n").replace("\\n","\n").replace("\\r","\r"); this.ret = (n.ret || "\n").replace(/\\n/g,"\n").replace(/\\r/g,"\r");
this.winflag = (this.ret === "\r\n"); this.winflag = (this.ret === "\r\n");
this.lineend = "\n"; this.lineend = "\n";
this.multi = n.multi || "one"; this.multi = n.multi || "one";

View File

@ -34,11 +34,14 @@
the range specified within the target range.</p> the range specified within the target range.</p>
<p><i>Scale and wrap within the target range</i> means that the result will <p><i>Scale and wrap within the target range</i> means that the result will
be wrapped within the target range.</p> be wrapped within the target range.</p>
<p><i>Scale, but drop if outside input range</i> means that the result will
be scaled, but any inputs outside of the inout range will be dropped.</p>
<p>For example an input 0 - 10 mapped to 0 - 100.</p> <p>For example an input 0 - 10 mapped to 0 - 100.</p>
<table style="outline-width:#888 solid thin"> <table style="outline-width:#888 solid thin">
<tr><th width="80px">mode</th><th width="80px">input</th><th width="80px">output</th></tr> <tr><th width="80px">mode</th><th width="80px">input</th><th width="80px">output</th></tr>
<tr><td><center>scale</center></td><td><center>12</center></td><td><center>120</center></td></tr> <tr><td><center>scale</center></td><td><center>12</center></td><td><center>120</center></td></tr>
<tr><td><center>limit</center></td><td><center>12</center></td><td><center>100</center></td></tr> <tr><td><center>limit</center></td><td><center>12</center></td><td><center>100</center></td></tr>
<tr><td><center>wrap</center></td><td><center>12</center></td><td><center>20</center></td></tr> <tr><td><center>wrap</center></td><td><center>12</center></td><td><center>20</center></td></tr>
<tr><td><center>drop</center></td><td><center>12</center></td><td><center><i>(no output)</i></center></td></tr>
</table> </table>
</script> </script>

View File

@ -813,7 +813,8 @@
"scale": { "scale": {
"payload": "Scale the message property", "payload": "Scale the message property",
"limit": "Scale and limit to the target range", "limit": "Scale and limit to the target range",
"wrap": "Scale and wrap within the target range" "wrap": "Scale and wrap within the target range",
"drop": "Scale, but drop msg if outside input range"
}, },
"tip": "Tip: This node ONLY works with numbers.", "tip": "Tip: This node ONLY works with numbers.",
"errors": { "errors": {

View File

@ -47,5 +47,6 @@
<p>If 'include null values' option is checked, null values will be returned in result, ie. middle value '"1",,3'.</p> <p>If 'include null values' option is checked, null values will be returned in result, ie. middle value '"1",,3'.</p>
<p>The node can accept a multi-part input as long as the <code>parts</code> property is set correctly, for example from a file-in node or split node.</p> <p>The node can accept a multi-part input as long as the <code>parts</code> property is set correctly, for example from a file-in node or split node.</p>
<p>If outputting multiple messages they will have their <code>parts</code> property set and form a complete message sequence.</p> <p>If outputting multiple messages they will have their <code>parts</code> property set and form a complete message sequence.</p>
<p>If the node is set to only send column headers once, then setting <code>msg.reset</code> to any value will cause the node to resend the headers.</p>
<p><b>Note:</b> the column template must be comma separated - even if a different separator is chosen for the data.</p> <p><b>Note:</b> the column template must be comma separated - even if a different separator is chosen for the data.</p>
</script> </script>

View File

@ -777,8 +777,8 @@
"change": "値の置換", "change": "値の置換",
"delete": "値の削除", "delete": "値の削除",
"move": "値の移動", "move": "値の移動",
"toValue": "対象の値", "toValue": "代入する値",
"to": "対象の値", "to": "移動先",
"search": "検索する文字列", "search": "検索する文字列",
"replace": "置換後の文字列" "replace": "置換後の文字列"
}, },
@ -813,7 +813,8 @@
"scale": { "scale": {
"payload": "msg.payloadの値を拡大/縮小", "payload": "msg.payloadの値を拡大/縮小",
"limit": "入力値の範囲外の値を最小値/最大値とし拡大/縮小", "limit": "入力値の範囲外の値を最小値/最大値とし拡大/縮小",
"wrap": "入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小" "wrap": "入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小",
"drop": "値を拡大/縮小(入力範囲外の時はメッセージを削除)"
}, },
"tip": "注釈: 本ノードは、数値のみ扱うことができます。", "tip": "注釈: 本ノードは、数値のみ扱うことができます。",
"errors": { "errors": {

View File

@ -15,22 +15,22 @@
} }
], ],
"dependencies": { "dependencies": {
"acorn": "8.7.1", "acorn": "8.8.1",
"acorn-walk": "8.2.0", "acorn-walk": "8.2.0",
"ajv": "8.11.0", "ajv": "8.11.2",
"body-parser": "1.20.0", "body-parser": "1.20.1",
"cheerio": "1.0.0-rc.10", "cheerio": "1.0.0-rc.10",
"content-type": "1.0.4", "content-type": "1.0.4",
"cookie-parser": "1.4.6", "cookie-parser": "1.4.6",
"cookie": "0.5.0", "cookie": "0.5.0",
"cors": "2.8.5", "cors": "2.8.5",
"cronosjs": "1.7.1", "cronosjs": "1.7.1",
"denque": "2.0.1", "denque": "2.1.0",
"form-data": "4.0.0", "form-data": "4.0.0",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"got": "11.8.5", "got": "11.8.5",
"hash-sum": "2.0.0", "hash-sum": "2.0.0",
"hpagent": "1.0.0", "hpagent": "1.2.0",
"https-proxy-agent": "5.0.1", "https-proxy-agent": "5.0.1",
"is-utf8": "0.2.1", "is-utf8": "0.2.1",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
@ -41,7 +41,7 @@
"node-watch": "0.7.3", "node-watch": "0.7.3",
"on-headers": "1.0.2", "on-headers": "1.0.2",
"raw-body": "2.5.1", "raw-body": "2.5.1",
"tough-cookie": "4.0.0", "tough-cookie": "4.1.2",
"uuid": "8.3.2", "uuid": "8.3.2",
"ws": "7.5.6", "ws": "7.5.6",
"xml2js": "0.4.23", "xml2js": "0.4.23",

View File

@ -19,8 +19,8 @@
"@node-red/util": "3.1.0-beta.0", "@node-red/util": "3.1.0-beta.0",
"clone": "2.1.2", "clone": "2.1.2",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"semver": "7.3.7", "semver": "7.3.8",
"tar": "6.1.11", "tar": "6.1.12",
"uglify-js": "3.16.2" "uglify-js": "3.17.4"
} }
} }

View File

@ -18,9 +18,9 @@
"dependencies": { "dependencies": {
"@node-red/registry": "3.1.0-beta.0", "@node-red/registry": "3.1.0-beta.0",
"@node-red/util": "3.1.0-beta.0", "@node-red/util": "3.1.0-beta.0",
"async-mutex": "0.3.2", "async-mutex": "0.4.0",
"clone": "2.1.2", "clone": "2.1.2",
"express": "4.18.1", "express": "4.18.2",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"json-stringify-safe": "5.0.1" "json-stringify-safe": "5.0.1"
} }

View File

@ -16,11 +16,11 @@
], ],
"dependencies": { "dependencies": {
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"i18next": "21.8.14", "i18next": "21.10.0",
"json-stringify-safe": "5.0.1", "json-stringify-safe": "5.0.1",
"jsonata": "1.8.6", "jsonata": "1.8.6",
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"moment": "2.29.4", "moment": "2.29.4",
"moment-timezone": "0.5.34" "moment-timezone": "0.5.39"
} }
} }

View File

@ -37,14 +37,14 @@
"@node-red/nodes": "3.1.0-beta.0", "@node-red/nodes": "3.1.0-beta.0",
"basic-auth": "2.0.1", "basic-auth": "2.0.1",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"express": "4.18.1", "express": "4.18.2",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"node-red-admin": "^3.0.0", "node-red-admin": "^3.0.0",
"nopt": "5.0.0", "nopt": "5.0.0",
"semver": "7.3.7" "semver": "7.3.8"
}, },
"optionalDependencies": { "optionalDependencies": {
"bcrypt": "5.0.1" "bcrypt": "5.1.0"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=14"

View File

@ -106,6 +106,27 @@ describe('range Node', function() {
genericRangeTest("clamp", 0, 10, 0, 1000, false, -1, 0, done); genericRangeTest("clamp", 0, 10, 0, 1000, false, -1, 0, done);
}); });
it('drops msg if in drop mode and input outside range', function(done) {
var flow = [{"id":"rangeNode1","type":"range","minin":2,"maxin":8,"minout":20,"maxout":80,"action":"drop","round":true,"name":"rangeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
helper.load(rangeNode, flow, function() {
var rangeNode1 = helper.getNode("rangeNode1");
var helperNode1 = helper.getNode("helperNode1");
helperNode1.on("input", function(msg) {
try {
msg.should.have.property('payload');
msg.payload.should.equal(50);
done();
} catch(err) {
done(err);
}
});
rangeNode1.receive({payload:1});
rangeNode1.receive({payload:9});
rangeNode1.receive({payload:5});
});
});
it('just passes on msg if payload not present', function(done) { it('just passes on msg if payload not present', function(done) {
var flow = [{"id":"rangeNode1","type":"range","minin":0,"maxin":100,"minout":0,"maxout":100,"action":"scale","round":true,"name":"rangeNode","wires":[["helperNode1"]]}, var flow = [{"id":"rangeNode1","type":"range","minin":0,"maxin":100,"minout":0,"maxout":100,"action":"scale","round":true,"name":"rangeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}]; {id:"helperNode1", type:"helper", wires:[]}];