diff --git a/package.json b/package.json index b596e10b6..ad65edd90 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,13 @@ } ], "dependencies": { - "acorn": "8.7.1", + "acorn": "8.8.1", "acorn-walk": "8.2.0", - "ajv": "8.11.0", - "async-mutex": "0.3.2", + "ajv": "8.11.2", + "async-mutex": "0.4.0", "basic-auth": "2.0.1", "bcryptjs": "2.4.3", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "cheerio": "1.0.0-rc.10", "clone": "2.1.2", "content-type": "1.0.4", @@ -40,16 +40,16 @@ "cookie-parser": "1.4.6", "cors": "2.8.5", "cronosjs": "1.7.1", - "denque": "2.0.1", - "express": "4.18.1", + "denque": "2.1.0", + "express": "4.18.2", "express-session": "1.17.3", "form-data": "4.0.0", "fs-extra": "10.1.0", "got": "11.8.5", "hash-sum": "2.0.0", - "hpagent": "1.0.0", + "hpagent": "1.2.0", "https-proxy-agent": "5.0.1", - "i18next": "21.8.14", + "i18next": "21.10.0", "iconv-lite": "0.6.3", "is-utf8": "0.2.1", "js-yaml": "4.1.0", @@ -60,7 +60,7 @@ "memorystore": "1.6.7", "mime": "3.0.0", "moment": "2.29.4", - "moment-timezone": "0.5.34", + "moment-timezone": "0.5.39", "mqtt": "4.3.7", "multer": "1.4.5-lts.1", "mustache": "4.2.0", @@ -73,19 +73,19 @@ "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", "raw-body": "2.5.1", - "semver": "7.3.7", - "tar": "6.1.11", - "tough-cookie": "4.0.0", - "uglify-js": "3.16.2", + "semver": "7.3.8", + "tar": "6.1.12", + "tough-cookie": "4.1.2", + "uglify-js": "3.17.4", "uuid": "8.3.2", "ws": "7.5.6", "xml2js": "0.4.23" }, "optionalDependencies": { - "bcrypt": "5.0.1" + "bcrypt": "5.1.0" }, "devDependencies": { - "dompurify": "2.3.9", + "dompurify": "2.4.1", "grunt": "1.5.3", "grunt-chmod": "~1.1.1", "grunt-cli": "~1.4.3", @@ -108,13 +108,13 @@ "i18next-http-backend": "1.4.1", "jquery-i18next": "1.2.1", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", - "marked": "4.0.18", + "marked": "4.2.3", "minami": "1.2.3", "mocha": "9.2.2", "node-red-node-test-helper": "^0.3.0", - "nodemon": "2.0.19", + "nodemon": "2.0.20", "proxy": "^1.0.2", - "sass": "1.53.0", + "sass": "1.56.1", "should": "13.2.3", "sinon": "11.1.2", "stoppable": "^1.1.0", diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json index dd7020e75..01fcb0ec8 100644 --- a/packages/node_modules/@node-red/editor-api/package.json +++ b/packages/node_modules/@node-red/editor-api/package.json @@ -19,11 +19,11 @@ "@node-red/util": "3.1.0-beta.0", "@node-red/editor-client": "3.1.0-beta.0", "bcryptjs": "2.4.3", - "body-parser": "1.20.0", + "body-parser": "1.20.1", "clone": "2.1.2", "cors": "2.8.5", "express-session": "1.17.3", - "express": "4.18.1", + "express": "4.18.2", "memorystore": "1.6.7", "mime": "3.0.0", "multer": "1.4.5-lts.1", @@ -35,6 +35,6 @@ "ws": "7.5.6" }, "optionalDependencies": { - "bcrypt": "5.0.1" + "bcrypt": "5.1.0" } } diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index c7c14c955..9ffde4df0 100755 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -57,18 +57,22 @@ "addFlowToRight": "Add flow to the right", "hideFlow": "Hide flow", "hideOtherFlows": "Hide other flows", - "showAllFlows": "Show all flows", + "showAllFlows": "Show all flows (__count__ hidden)", "hideAllFlows": "Hide all flows", "hiddenFlows": "List __count__ hidden flow", "hiddenFlows_plural": "List __count__ hidden flows", - "showLastHiddenFlow": "Show last hidden flow", + "showLastHiddenFlow": "Reopen hidden flow", "listFlows": "List flows", "listSubflows": "List subflows", "status": "Status", "enabled": "Enabled", "disabled": "Disabled", "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": { "label": { @@ -684,7 +688,8 @@ "globalConfig": "Global Configuration Nodes", "triggerAction": "Trigger action", "find": "Find in workspace", - "copyItemUrl": "Copy item url" + "copyItemUrl": "Copy item url", + "copyURL2Clipboard": "Copied url to clipboard" }, "help": { "name": "Help", diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json index fdd29c16a..30761ef14 100644 --- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json @@ -68,7 +68,11 @@ "enabled": "有効", "disabled": "無効", "info": "詳細", - "selectNodes": "ノードをクリックして選択" + "selectNodes": "ノードをクリックして選択", + "enableFlow": "フローを有効化", + "disableFlow": "フローを無効化", + "moveToStart": "フローを先頭へ移動", + "moveToEnd": "フローを最後へ移動" }, "menu": { "label": { @@ -683,7 +687,9 @@ "empty": "空", "globalConfig": "グローバル設定ノード", "triggerAction": "アクションを実行", - "find": "ワークスペース内を検索" + "find": "ワークスペース内を検索", + "copyItemUrl": "要素のURLをコピー", + "copyURL2Clipboard": "URLをクリップボードにコピーしました" }, "help": { "name": "ヘルプ", @@ -1168,8 +1174,7 @@ "takeATour": "ツアーを開始", "start": "開始", "next": "次へ", - "welcomeTours": "ウェルカムツアー", - "tours": "ツアー" + "welcomeTours": "ウェルカムツアー" }, "diagnostics": { "title": "システム情報" @@ -1348,7 +1353,9 @@ "show-project-settings": "プロジェクト設定を表示", "show-version-control-tab": "バージョンコントロールタブを表示", "start-flows": "フローを開始", - "stop-flows": "フローを停止" + "stop-flows": "フローを停止", + "copy-item-url": "要素のURLをコピー", + "copy-item-edit-url": "要素の編集URLをコピー" }, "env-var": { "environment": "環境変数", diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index 9da5aad05..6dd500581 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -2834,7 +2834,7 @@ RED.nodes = (function() { }, addWorkspace: addWorkspace, removeWorkspace: removeWorkspace, - getWorkspaceOrder: function() { return workspacesOrder }, + getWorkspaceOrder: function() { return [...workspacesOrder] }, setWorkspaceOrder: function(order) { workspacesOrder = order; }, workspace: getWorkspace, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js index f547203d4..53a908c67 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js @@ -423,11 +423,10 @@ RED.clipboard = (function() { } } - function showImportNodes(mode) { + function showImportNodes(library = 'clipboard') { if (disabled) { return; } - mode = mode || "clipboard"; dialogContainer.empty(); dialogContainer.append($(importNodesDialog)); @@ -533,8 +532,8 @@ RED.clipboard = (function() { $("#red-ui-clipboard-dialog-import-file-upload").trigger("click"); }) - tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode); - if (mode === 'clipboard') { + tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+library); + if (library === 'clipboard') { setTimeout(function() { $("#red-ui-clipboard-dialog-import-text").trigger("focus"); },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) { return; } - mode = mode || "clipboard"; - dialogContainer.empty(); dialogContainer.append($(exportNodesDialog)); @@ -654,7 +656,12 @@ RED.clipboard = (function() { $("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select(); dialogContainer.i18n(); + 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) { evt.preventDefault(); @@ -670,7 +677,8 @@ RED.clipboard = (function() { var nodes = JSON.parse(flow); 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); } else { flow = JSON.stringify(nodes); @@ -679,6 +687,7 @@ RED.clipboard = (function() { setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50); $("#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") { $("#red-ui-clipboard-dialog-export-fmt-full").trigger("click"); } else { $("#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 winHeight = $(window).height(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js index 2d95f894a..8d0f1dbd3 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js @@ -94,8 +94,8 @@ RED.menu = (function() { var link = $(linkContent).appendTo(item); opt.link = link; - if (typeof opt.onselect === 'string') { - var shortcut = RED.keyboard.getShortcut(opt.onselect); + if (typeof opt.onselect === 'string' || opt.shortcut) { + var shortcut = opt.shortcut || RED.keyboard.getShortcut(opt.onselect); if (shortcut && shortcut.key) { opt.shortcutSpan = $(''+RED.keyboard.formatKey(shortcut.key, true)+'').appendTo(link.find(".red-ui-menu-label")); } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js index 8901cf11f..a8e7ea727 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js @@ -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 scrollRight; @@ -809,17 +831,17 @@ RED.tabs = (function() { }); RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); } - if (tab.hideable) { - li.addClass("red-ui-tabs-closeable") - var closeLink = $("",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li); - closeLink.append(''); - closeLink.append(''); - closeLink.on("click",function(event) { - event.preventDefault(); - hideTab(tab.id); - }); - RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); - } + // if (tab.hideable) { + // li.addClass("red-ui-tabs-closeable") + // var closeLink = $("",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li); + // closeLink.append(''); + // closeLink.append(''); + // closeLink.on("click",function(event) { + // event.preventDefault(); + // hideTab(tab.id); + // }); + // RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); + // } var badges = $('').appendTo(li); if (options.onselect) { @@ -938,6 +960,9 @@ RED.tabs = (function() { activeIndex: function() { return ul.find("li.active").index() }, + getTabIndex: function (id) { + return ul.find("a[href='#"+id+"']").parent().index() + }, contains: function(id) { return ul.find("a[href='#"+id+"']").length > 0; }, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js index 66ae2b943..8052d561f 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js @@ -1,21 +1,6 @@ RED.contextMenu = (function () { let menu; - function createMenu() { - // menu = RED.popover.menu({ - // options: [ - // { - // label: 'delete selection', - // onselect: function() { - // RED.actions.invoke('core:delete-selection') - // RED.view.focus() - // } - // }, - // { label: 'world' } - // ], - // width: 200, - // }) - } function disposeMenu() { $(document).off("mousedown.red-ui-workspace-context-menu"); @@ -28,114 +13,118 @@ RED.contextMenu = (function () { if (menu) { menu.remove() } + let menuItems = [] + if (options.options) { + menuItems = options.options + } else if (options.type === 'workspace') { + const selection = RED.view.selection() + const noSelection = !selection || Object.keys(selection).length === 0 + const hasSelection = (selection.nodes && selection.nodes.length > 0); + const hasMultipleSelection = hasSelection && selection.nodes.length > 1; + const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || []; + const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || []; + const hasLinks = wireLinks.length > 0; + const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1 + const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1 + const canDelete = hasSelection || hasLinks + const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group' - const selection = RED.view.selection() - const noSelection = !selection || Object.keys(selection).length === 0 - const hasSelection = (selection.nodes && selection.nodes.length > 0); - const hasMultipleSelection = hasSelection && selection.nodes.length > 1; - const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || []; - const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || []; - const hasLinks = wireLinks.length > 0; - const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1 - const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1 - const canDelete = hasSelection || hasLinks - const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group' - - const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g - const offset = $("#red-ui-workspace-chart").offset() - - let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft() - let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop() - - if (RED.view.snapGrid) { - const gridSize = RED.view.gridSize() - addX = gridSize * Math.floor(addX / gridSize) - addY = gridSize * Math.floor(addY / gridSize) - } - - const menuItems = [ - { onselect: 'core:show-action-list', onpostselect: function () { } }, - { - label: RED._("contextMenu.insert"), - options: [ - { - label: RED._("contextMenu.node"), - onselect: function () { - RED.view.showQuickAddDialog({ - position: [addX, addY], - touchTrigger: true, - splice: isSingleLink ? selection.links[0] : undefined, - // spliceMultiple: isMultipleLinks - }) - } - }, - (hasLinks) ? { // has least 1 wire selected - label: RED._("contextMenu.junction"), - onselect: 'core:split-wires-with-junctions', - disabled: !hasLinks - } : { - label: RED._("contextMenu.junction"), - onselect: function () { - const nn = { - _def: { defaults: {} }, - type: 'junction', - z: RED.workspaces.active(), - id: RED.nodes.id(), - x: addX, - y: addY, - w: 0, h: 0, - outputs: 1, - inputs: 1, - dirty: true - } - const historyEvent = { - dirty: RED.nodes.dirty(), - t: 'add', - junctions: [nn] - } - RED.nodes.addJunction(nn); - RED.history.push(historyEvent); - RED.nodes.dirty(true); - RED.view.select({nodes: [nn] }); - RED.view.redraw(true) - } - }, - { - label: RED._("contextMenu.linkNodes"), - onselect: 'core:split-wire-with-link-nodes', - disabled: !hasLinks - } - ] - + const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g + const offset = $("#red-ui-workspace-chart").offset() + let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft() + let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop() + if (RED.view.snapGrid) { + const gridSize = RED.view.gridSize() + addX = gridSize * Math.floor(addX / gridSize) + addY = gridSize * Math.floor(addY / gridSize) } - ] - menuItems.push( - null, - { onselect: 'core:undo', disabled: RED.history.list().length === 0 }, - { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 }, - null, - { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection }, - { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection }, - { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() }, - { onselect: 'core:delete-selection', disabled: !canDelete }, - { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") }, - { onselect: 'core:select-all-nodes' } - ) + menuItems.push( + { onselect: 'core:show-action-list', onpostselect: function () { } }, + { + label: RED._("contextMenu.insert"), + options: [ + { + label: RED._("contextMenu.node"), + onselect: function () { + RED.view.showQuickAddDialog({ + position: [addX, addY], + touchTrigger: true, + splice: isSingleLink ? selection.links[0] : undefined, + // spliceMultiple: isMultipleLinks + }) + } + }, + (hasLinks) ? { // has least 1 wire selected + label: RED._("contextMenu.junction"), + onselect: 'core:split-wires-with-junctions', + disabled: !hasLinks + } : { + label: RED._("contextMenu.junction"), + onselect: function () { + const nn = { + _def: { defaults: {} }, + type: 'junction', + z: RED.workspaces.active(), + id: RED.nodes.id(), + x: addX, + y: addY, + w: 0, h: 0, + outputs: 1, + inputs: 1, + dirty: true + } + const historyEvent = { + dirty: RED.nodes.dirty(), + t: 'add', + junctions: [nn] + } + RED.nodes.addJunction(nn); + RED.history.push(historyEvent); + RED.nodes.dirty(true); + RED.view.select({nodes: [nn] }); + RED.view.redraw(true) + } + }, + { + label: RED._("contextMenu.linkNodes"), + onselect: 'core:split-wire-with-link-nodes', + disabled: !hasLinks + } + ] + + + + } + ) - if (hasSelection) { menuItems.push( null, - isGroup ? - { onselect: 'core:ungroup-selection', disabled: !isGroup } - : { onselect: 'core:group-selection', disabled: !hasSelection } + { onselect: 'core:undo', disabled: RED.history.list().length === 0 }, + { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 }, + null, + { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection }, + { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection }, + { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() }, + { onselect: 'core:delete-selection', disabled: !canDelete }, + { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") }, + { onselect: 'core:select-all-nodes' } ) - if (canRemoveFromGroup) { - menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") }) - } + if (hasSelection) { + menuItems.push( + null, + isGroup ? + { onselect: 'core:ungroup-selection', disabled: !isGroup } + : { onselect: 'core:group-selection', disabled: !hasSelection } + ) + if (canRemoveFromGroup) { + menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") }) + } + + } } var direction = "right"; @@ -144,7 +133,7 @@ RED.contextMenu = (function () { ($(window).width() -MENU_WIDTH)) { direction = "left"; } - + menu = RED.menu.init({ direction: direction, onpreselect: function() { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js b/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js index ca4f651ab..e979adf65 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js @@ -431,44 +431,7 @@ RED.subflow = (function() { $("#red-ui-subflow-delete").on("click", function(event) { event.preventDefault(); - var subflow = RED.nodes.subflow(RED.workspaces.active()); - if (subflow.instances.length > 0) { - var msg = $('
') - $('

').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg); - $('

').text(RED._("subflow.confirmDelete")).appendTo(msg); - var confirmDeleteNotification = RED.notify(msg, { - modal: true, - fixed: true, - buttons: [ - { - text: RED._('common.label.cancel'), - click: function() { - confirmDeleteNotification.close(); - } - }, - { - text: RED._('workspace.confirmDelete'), - class: "primary", - click: function() { - confirmDeleteNotification.close(); - completeDelete(); - } - } - ] - }); - - return; - } else { - completeDelete(); - } - function completeDelete() { - var startDirty = RED.nodes.dirty(); - var historyEvent = removeSubflow(RED.workspaces.active()); - historyEvent.t = 'delete'; - historyEvent.dirty = startDirty; - RED.history.push(historyEvent); - } - + RED.subflow.delete(RED.workspaces.active()) }); refreshToolbar(activeSubflow); @@ -481,7 +444,48 @@ RED.subflow = (function() { $("#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) { + const msg = $('

') + $('

').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg); + $('

').text(RED._("subflow.confirmDelete")).appendTo(msg); + const confirmDeleteNotification = RED.notify(msg, { + modal: true, + fixed: true, + buttons: [ + { + text: RED._('common.label.cancel'), + click: function() { + confirmDeleteNotification.close(); + } + }, + { + text: RED._('workspace.confirmDelete'), + class: "primary", + click: function() { + confirmDeleteNotification.close(); + completeDelete(); + } + } + ] + }); + return; + } else { + completeDelete(); + } + function completeDelete() { + const startDirty = RED.nodes.dirty(); + const historyEvent = removeSubflow(subflow.id); + historyEvent.t = 'delete'; + historyEvent.dirty = startDirty; + RED.history.push(historyEvent); + } + } function removeSubflow(id, keepInstanceNodes) { // TODO: A lot of this logic is common with RED.nodes.removeWorkspace var removedNodes = []; @@ -1323,7 +1327,10 @@ RED.subflow = (function() { init: init, createSubflow: createSubflow, convertToSubflow: convertToSubflow, + // removeSubflow: Internal function to remove subflow removeSubflow: removeSubflow, + // delete: Prompt user for confirmation + delete: deleteSubflow, refresh: refresh, removeInput: removeSubflowInput, removeOutput: removeSubflowOutput, 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 1ed5791a6..0f02077d8 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 @@ -1211,7 +1211,7 @@ RED.view.tools = (function() { url += '/edit' } if (RED.clipboard.copyText(url)) { - RED.notify('Copied url to clipboard', { timeout: 2000 }) + RED.notify(RED._("sidebar.info.copyURL2Clipboard"), { timeout: 2000 }) } } } 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 99855b6c9..dafcddda7 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 @@ -211,6 +211,7 @@ RED.view = (function() { evt.preventDefault() evt.stopPropagation() RED.contextMenu.show({ + type: 'workspace', x:evt.clientX-5, y:evt.clientY-5 }) 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 ae38f2c4d..d274ba519 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 @@ -126,6 +126,166 @@ RED.workspaces = (function() { var workspace_tabs; 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() { workspace_tabs = RED.tabs.create({ id: "red-ui-workspace-tabs", @@ -189,13 +349,19 @@ RED.workspaces = (function() { RED.history.push({ t:'reorder', workspaces: { - from:oldOrder, - to:newOrder + from: oldOrder, + to: newOrder }, dirty:RED.nodes.dirty() }); - RED.nodes.dirty(true); - setWorkspaceOrder(newOrder); + // 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); + setWorkspaceOrder(newOrder); + } }, onselect: function(selectedTabs) { RED.view.select(false) @@ -214,12 +380,12 @@ RED.workspaces = (function() { }, onhide: function(tab) { hideStack.push(tab.id); - - var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); - hiddenTabs[tab.id] = true; - RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs)); - - RED.events.emit("workspace:hide",{workspace: tab.id}) + if (tab.type === "tab") { + var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); + hiddenTabs[tab.id] = true; + RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs)); + RED.events.emit("workspace:hide",{workspace: tab.id}) + } }, onshow: function(tab) { removeFromHideStack(tab.id); @@ -234,77 +400,8 @@ RED.workspaces = (function() { scrollable: true, addButton: "core:add-flow", addButtonCaption: RED._("workspace.addFlow"), - menu: function() { - var menuItems = [ - { - 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; - } + menu: function() { return getMenuItems(true) }, + contextmenu: function(tab) { return getMenuItems(false, tab) } }); workspaceTabCount = 0; } @@ -355,16 +452,31 @@ RED.workspaces = (function() { }); 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:remove-flow",removeWorkspace); RED.actions.add("core:enable-flow",enableWorkspace); 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() { - var selection = workspace_tabs.selection(); - if (selection.length === 0) { - selection = [{id:activeWorkspace}] + RED.actions.add("core:hide-flow", function(workspace) { + let selection + if (workspace) { + selection = [workspace] + } else { + selection = workspace_tabs.selection(); + if (selection.length === 0) { + selection = [{id:activeWorkspace}] + } } var hiddenTabs = []; selection.forEach(function(ws) { @@ -378,10 +490,15 @@ RED.workspaces = (function() { workspace_tabs.clearSelection(); }) - RED.actions.add("core:hide-other-flows", function() { - var selection = workspace_tabs.selection(); - if (selection.length === 0) { - selection = [{id:activeWorkspace}] + RED.actions.add("core:hide-other-flows", function(workspace) { + let selection + if (workspace) { + selection = [workspace] + } else { + selection = workspace_tabs.selection(); + if (selection.length === 0) { + selection = [{id:activeWorkspace}] + } } var selected = new Set(selection.map(function(ws) { return ws.id })) @@ -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) { - var newOrder = order.filter(function(id) { - return RED.nodes.workspace(id) !== undefined; - }) + var newOrder = order.filter(id => !!RED.nodes.workspace(id)) 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); + return newOrder } function flashTab(tabId) { 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 07bb1f080..1652a91db 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 @@ -10,6 +10,7 @@ +


diff --git a/packages/node_modules/@node-red/nodes/core/function/16-range.js b/packages/node_modules/@node-red/nodes/core/function/16-range.js index a5dede4ea..61ffd53fb 100644 --- a/packages/node_modules/@node-red/nodes/core/function/16-range.js +++ b/packages/node_modules/@node-red/nodes/core/function/16-range.js @@ -32,11 +32,15 @@ module.exports = function(RED) { if (value !== undefined) { var n = Number(value); 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.maxin) { n = node.maxin; } } - if (node.action == "roll") { + if (node.action === "roll") { var divisor = node.maxin - node.minin; n = ((n - node.minin) % divisor + divisor) % divisor + node.minin; } diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js b/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js index 9c55fa2b6..04f2bb71f 100644 --- a/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js +++ b/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js @@ -19,9 +19,9 @@ module.exports = function(RED) { function CSVNode(n) { RED.nodes.createNode(this,n); 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.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.lineend = "\n"; this.multi = n.multi || "one"; diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html b/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html index b391f5c04..f25363565 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html +++ b/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html @@ -34,11 +34,14 @@ the range specified within the target range.

Scale and wrap within the target range means that the result will be wrapped within the target range.

+

Scale, but drop if outside input range means that the result will + be scaled, but any inputs outside of the inout range will be dropped.

For example an input 0 - 10 mapped to 0 - 100.

+
modeinputoutput
scale
12
120
limit
12
100
wrap
12
20
drop
12
(no output)
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json index 979bb7f87..3ba344ae0 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json @@ -813,7 +813,8 @@ "scale": { "payload": "Scale the message property", "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.", "errors": { diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-CSV.html b/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-CSV.html index dc4dd98ff..baa3b036b 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-CSV.html +++ b/packages/node_modules/@node-red/nodes/locales/en-US/parsers/70-CSV.html @@ -47,5 +47,6 @@

If 'include null values' option is checked, null values will be returned in result, ie. middle value '"1",,3'.

The node can accept a multi-part input as long as the parts property is set correctly, for example from a file-in node or split node.

If outputting multiple messages they will have their parts property set and form a complete message sequence.

+

If the node is set to only send column headers once, then setting msg.reset to any value will cause the node to resend the headers.

Note: the column template must be comma separated - even if a different separator is chosen for the data.

diff --git a/packages/node_modules/@node-red/nodes/locales/ja/messages.json b/packages/node_modules/@node-red/nodes/locales/ja/messages.json index 0068cd20d..2365f7f7a 100644 --- a/packages/node_modules/@node-red/nodes/locales/ja/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/ja/messages.json @@ -777,8 +777,8 @@ "change": "値の置換", "delete": "値の削除", "move": "値の移動", - "toValue": "対象の値", - "to": "対象の値", + "toValue": "代入する値", + "to": "移動先", "search": "検索する文字列", "replace": "置換後の文字列" }, @@ -813,7 +813,8 @@ "scale": { "payload": "msg.payloadの値を拡大/縮小", "limit": "入力値の範囲外の値を最小値/最大値とし拡大/縮小", - "wrap": "入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小" + "wrap": "入力値の範囲外の値を範囲幅で割った余りとし拡大/縮小", + "drop": "値を拡大/縮小(入力範囲外の時はメッセージを削除)" }, "tip": "注釈: 本ノードは、数値のみ扱うことができます。", "errors": { diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json index 9db16efc0..c4b7023dd 100644 --- a/packages/node_modules/@node-red/nodes/package.json +++ b/packages/node_modules/@node-red/nodes/package.json @@ -15,22 +15,22 @@ } ], "dependencies": { - "acorn": "8.7.1", + "acorn": "8.8.1", "acorn-walk": "8.2.0", - "ajv": "8.11.0", - "body-parser": "1.20.0", + "ajv": "8.11.2", + "body-parser": "1.20.1", "cheerio": "1.0.0-rc.10", "content-type": "1.0.4", "cookie-parser": "1.4.6", "cookie": "0.5.0", "cors": "2.8.5", "cronosjs": "1.7.1", - "denque": "2.0.1", + "denque": "2.1.0", "form-data": "4.0.0", "fs-extra": "10.1.0", "got": "11.8.5", "hash-sum": "2.0.0", - "hpagent": "1.0.0", + "hpagent": "1.2.0", "https-proxy-agent": "5.0.1", "is-utf8": "0.2.1", "js-yaml": "4.1.0", @@ -41,7 +41,7 @@ "node-watch": "0.7.3", "on-headers": "1.0.2", "raw-body": "2.5.1", - "tough-cookie": "4.0.0", + "tough-cookie": "4.1.2", "uuid": "8.3.2", "ws": "7.5.6", "xml2js": "0.4.23", diff --git a/packages/node_modules/@node-red/registry/package.json b/packages/node_modules/@node-red/registry/package.json index 088bba36a..8dbe03d5b 100644 --- a/packages/node_modules/@node-red/registry/package.json +++ b/packages/node_modules/@node-red/registry/package.json @@ -19,8 +19,8 @@ "@node-red/util": "3.1.0-beta.0", "clone": "2.1.2", "fs-extra": "10.1.0", - "semver": "7.3.7", - "tar": "6.1.11", - "uglify-js": "3.16.2" + "semver": "7.3.8", + "tar": "6.1.12", + "uglify-js": "3.17.4" } } diff --git a/packages/node_modules/@node-red/runtime/package.json b/packages/node_modules/@node-red/runtime/package.json index 14171f1d6..f3c58ee71 100644 --- a/packages/node_modules/@node-red/runtime/package.json +++ b/packages/node_modules/@node-red/runtime/package.json @@ -18,9 +18,9 @@ "dependencies": { "@node-red/registry": "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", - "express": "4.18.1", + "express": "4.18.2", "fs-extra": "10.1.0", "json-stringify-safe": "5.0.1" } diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json index aa82273f6..a02b99711 100644 --- a/packages/node_modules/@node-red/util/package.json +++ b/packages/node_modules/@node-red/util/package.json @@ -16,11 +16,11 @@ ], "dependencies": { "fs-extra": "10.1.0", - "i18next": "21.8.14", + "i18next": "21.10.0", "json-stringify-safe": "5.0.1", "jsonata": "1.8.6", "lodash.clonedeep": "^4.5.0", "moment": "2.29.4", - "moment-timezone": "0.5.34" + "moment-timezone": "0.5.39" } } diff --git a/packages/node_modules/node-red/package.json b/packages/node_modules/node-red/package.json index b4c4e53f0..e87a14c97 100644 --- a/packages/node_modules/node-red/package.json +++ b/packages/node_modules/node-red/package.json @@ -37,14 +37,14 @@ "@node-red/nodes": "3.1.0-beta.0", "basic-auth": "2.0.1", "bcryptjs": "2.4.3", - "express": "4.18.1", + "express": "4.18.2", "fs-extra": "10.1.0", "node-red-admin": "^3.0.0", "nopt": "5.0.0", - "semver": "7.3.7" + "semver": "7.3.8" }, "optionalDependencies": { - "bcrypt": "5.0.1" + "bcrypt": "5.1.0" }, "engines": { "node": ">=14" diff --git a/test/nodes/core/function/16-range_spec.js b/test/nodes/core/function/16-range_spec.js index a0dcd0078..620d21b12 100644 --- a/test/nodes/core/function/16-range_spec.js +++ b/test/nodes/core/function/16-range_spec.js @@ -106,6 +106,27 @@ describe('range Node', function() { 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) { 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:[]}];