mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
upstream merge
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
"view": {
|
||||
"view": "View",
|
||||
"grid": "Grid",
|
||||
"storeZoom": "Restore zoom level on load",
|
||||
"storePosition": "Restore scroll position on load",
|
||||
"showGrid": "Show grid",
|
||||
"snapGrid": "Snap to grid",
|
||||
"gridSize": "Grid size",
|
||||
@@ -894,6 +896,8 @@
|
||||
"addTitle": "add an item"
|
||||
},
|
||||
"search": {
|
||||
"history": "Search history",
|
||||
"clear": "clear all",
|
||||
"empty": "No matches found",
|
||||
"addNode": "add a node..."
|
||||
},
|
||||
@@ -1091,7 +1095,8 @@
|
||||
"not-git": "Not a git repository",
|
||||
"no-resource": "Repository not found",
|
||||
"cant-get-ssh-key-path": "Error! Can't get selected SSH key path.",
|
||||
"unexpected_error": "unexpected_error"
|
||||
"unexpected_error": "unexpected_error",
|
||||
"clearContext": "Clear context when switching projects"
|
||||
},
|
||||
"delete": {
|
||||
"confirm": "Are you sure you want to delete this project?"
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
"view": {
|
||||
"view": "表示",
|
||||
"grid": "グリッド",
|
||||
"storeZoom": "読み込み時に拡大/縮小のレベルを復元",
|
||||
"storePosition": "読み込み時にスクロール位置を復元",
|
||||
"showGrid": "グリッドを表示",
|
||||
"snapGrid": "ノードの配置を補助",
|
||||
"gridSize": "グリッドの大きさ",
|
||||
@@ -894,6 +896,8 @@
|
||||
"addTitle": "要素を追加"
|
||||
},
|
||||
"search": {
|
||||
"history": "検索履歴",
|
||||
"clear": "全て削除",
|
||||
"empty": "一致したものが見つかりませんでした",
|
||||
"addNode": "ノードを追加..."
|
||||
},
|
||||
@@ -1091,7 +1095,8 @@
|
||||
"not-git": "Gitリポジトリではありません",
|
||||
"no-resource": "リポジトリが見つかりません",
|
||||
"cant-get-ssh-key-path": "エラー! 選択したSSHキーのパスを取得できません。",
|
||||
"unexpected_error": "予期しないエラー"
|
||||
"unexpected_error": "予期しないエラー",
|
||||
"clearContext": "プロジェクトを切り替る際にコンテキストを初期化"
|
||||
},
|
||||
"delete": {
|
||||
"confirm": "プロジェクトを削除しても良いですか?"
|
||||
@@ -1151,5 +1156,137 @@
|
||||
"ru": "ロシア語",
|
||||
"zh-CN": "中国語(簡体)",
|
||||
"zh-TW": "中国語(繁体)"
|
||||
},
|
||||
"action-list": {
|
||||
"toggle-show-tips": "ヒント表示切替",
|
||||
"show-about": "Node-REDの説明を表示",
|
||||
"show-welcome-tour": "ウェルカムツアー表示",
|
||||
"show-next-tab": "次のタブを表示",
|
||||
"show-previous-tab": "前のタブを表示",
|
||||
"add-flow": "フローを追加",
|
||||
"add-flow-to-right": "フローを右に追加",
|
||||
"edit-flow": "フローを編集",
|
||||
"remove-flow": "フローを削除",
|
||||
"enable-flow": "フローを有効化",
|
||||
"disable-flow": "フローを無効化",
|
||||
"hide-flow": "フローを隠す",
|
||||
"hide-other-flows": "他のフローを非表示",
|
||||
"hide-all-flows": "全てのフローを非表示",
|
||||
"show-all-flows": "全てのフローを表示",
|
||||
"show-last-hidden-flow": "最後に非表示にしたフローを表示",
|
||||
"list-hidden-flows": "非表示フローを表示",
|
||||
"list-flows": "フロー一覧",
|
||||
"list-subflows": "サブフロー一覧",
|
||||
"go-to-previous-location": "前の位置に移動",
|
||||
"go-to-next-location": "次の位置に移動",
|
||||
"copy-selection-to-internal-clipboard": "選択をクリップボードにコピー",
|
||||
"cut-selection-to-internal-clipboard": "選択をクリップボードに切り取り",
|
||||
"paste-from-internal-clipboard": "クリップボードから貼り付け",
|
||||
"detach-selected-nodes": "選択ノードを接続から外す",
|
||||
"delete-selection": "選択を削除",
|
||||
"delete-selection-and-reconnect": "選択を削除し再接続",
|
||||
"edit-selected-node": "選択したノードを編集",
|
||||
"go-to-selection": "選択に移動",
|
||||
"undo": "変更操作を戻す",
|
||||
"redo": "変更操作をやり直し",
|
||||
"select-all-nodes": "全てのノードを選択",
|
||||
"select-none": "ノードを選択",
|
||||
"enable-selected-nodes": "選択ノードを有効化",
|
||||
"disable-selected-nodes": "選択ノードを無効化",
|
||||
"toggle-show-grid": "グリッド表示切替",
|
||||
"toggle-snap-grid": "ノードの配置補助切替",
|
||||
"toggle-status": "ステータス表示切替",
|
||||
"show-selected-node-labels": "選択したノードのラベルを表示",
|
||||
"hide-selected-node-labels": "選択したノードのラベルを非表示",
|
||||
"scroll-view-up": "上スクロール",
|
||||
"scroll-view-right": "右スクロール",
|
||||
"scroll-view-down": "下スクロール",
|
||||
"scroll-view-left": "左スクロール",
|
||||
"step-view-up": "一単位上スクロール",
|
||||
"step-view-right": "一単位右スクロール",
|
||||
"step-view-down": "一単位下スクロール",
|
||||
"step-view-left": "一単位左スクロール",
|
||||
"move-selection-up": "選択を上移動",
|
||||
"move-selection-right": "選択を右移動",
|
||||
"move-selection-down": "選択を下移動",
|
||||
"move-selection-left": "選択を左移動",
|
||||
"move-selection-forwards": "選択を前面に移動",
|
||||
"move-selection-backwards": "選択を背面に移動",
|
||||
"move-selection-to-front": "選択を最前面に移動",
|
||||
"move-selection-to-back": "選択を最背面に移動",
|
||||
"step-selection-up": "選択を一単位上移動",
|
||||
"step-selection-right": "選択を一単位右移動",
|
||||
"step-selection-down": "選択を一単位下移動",
|
||||
"step-selection-left": "選択を一単位左移動",
|
||||
"select-connected-nodes": "接続されたノードを選択",
|
||||
"select-downstream-nodes": "後方に接続されたノードを選択",
|
||||
"select-upstream-nodes": "前方に接続されたノードを選択",
|
||||
"go-to-next-node": "次のノードに移動",
|
||||
"go-to-previous-node": "前のノードに移動",
|
||||
"go-to-next-sibling": "次の兄弟ノードに移動",
|
||||
"go-to-previous-sibling": "前の兄弟ノードに移動",
|
||||
"go-to-nearest-node-on-left": "最も近い左側ノードに移動",
|
||||
"go-to-nearest-node-on-right": "最も近い右側ノードに移動",
|
||||
"go-to-nearest-node-above": "最も近い上側ノードに移動",
|
||||
"go-to-nearest-node-below": "最も近い下側ノードに移動",
|
||||
"align-selection-to-grid": "選択を整列",
|
||||
"align-selection-to-left": "選択を左揃え",
|
||||
"align-selection-to-right": "選択を右揃え",
|
||||
"align-selection-to-top": "選択を上揃え",
|
||||
"align-selection-to-bottom": "選択を下揃え",
|
||||
"align-selection-to-middle": "選択を上下中央揃え",
|
||||
"align-selection-to-center": "選択を左右中央揃え",
|
||||
"distribute-selection-horizontally": "選択を左右に整列",
|
||||
"distribute-selection-vertically": "選択を上下に整列",
|
||||
"wire-series-of-nodes": "ノードを一続きに接続",
|
||||
"wire-node-to-multiple": "ノードを複数に接続",
|
||||
"show-user-settings": "ユーザ設定を表示",
|
||||
"show-help": "ヘルプを表示",
|
||||
"toggle-palette": "パレットの表示切替",
|
||||
"show-event-log": "イベントログを表示",
|
||||
"manage-palette": "パレットの管理",
|
||||
"toggle-sidebar": "サイドバーの表示切替",
|
||||
"show-info-tab": "ノード情報タブの表示",
|
||||
"show-help-tab": "ノードヘルプタブの表示",
|
||||
"show-config-tab": "設定ノードタブの表示",
|
||||
"select-all-config-nodes": "全ての設定ノードを選択",
|
||||
"delete-config-selection": "選択した設定ノードを削除",
|
||||
"show-context-tab": "コンテキストデータタブを表示",
|
||||
"create-subflow": "サブフローを作成",
|
||||
"convert-to-subflow": "選択をサブフローに変換",
|
||||
"group-selection": "選択をグループ化",
|
||||
"ungroup-selection": "選択をグループ解除",
|
||||
"merge-selection-to-group": "選択をグループにマージ",
|
||||
"remove-selection-from-group": "選択をグループから削除",
|
||||
"copy-group-style": "グループのスタイルをコピー",
|
||||
"paste-group-style": "グループのスタイルを貼り付け",
|
||||
"show-export-dialog": "書き出しダイアログを表示",
|
||||
"show-import-dialog": "読み込みダイアログを表示",
|
||||
"show-library-export-dialog": "ライブラリ書き出しダイアログを表示",
|
||||
"show-library-import-dialog": "ライブラリ読み込みダイアログを表示",
|
||||
"show-examples-import-dialog": "サンプル読み込みダイアログを表示",
|
||||
"search": "検索",
|
||||
"show-action-list": "アクション一覧を表示",
|
||||
"confirm-edit-tray": "編集を完了",
|
||||
"cancel-edit-tray": "編集をキャンセル",
|
||||
"show-remote-diff": "リモートとの変更差分を表示",
|
||||
"deploy-flows": "フローをデプロイ",
|
||||
"restart-flows": "フローを再起動",
|
||||
"set-deploy-type-to-full": "デプロイを「全て」に設定",
|
||||
"set-deploy-type-to-modified-flows": "デプロイを「変更したフロー」に設定",
|
||||
"set-deploy-type-to-modified-nodes": "デプロイを「変更したノード」に設定",
|
||||
"show-debug-tab": "デバッグタブを表示",
|
||||
"clear-debug-messages": "デバッグメッセージをクリア",
|
||||
"clear-filtered-debug-messages": "フィルタしたデバッグメッセージをクリア",
|
||||
"activate-selected-debug-nodes": "選択したデバッグノードを有効化",
|
||||
"activate-all-debug-nodes": "全てのデバッグノードを有効化",
|
||||
"activate-all-flow-debug-nodes": "フロー内の全デバッグノードを有効化",
|
||||
"deactivate-selected-debug-nodes": "選択したデバッグノードを無効化",
|
||||
"deactivate-all-debug-nodes": "全てのデバッグノードを無効化",
|
||||
"deactivate-all-flow-debug-nodes": "フロー内の全デバッグノードを無効化",
|
||||
"zoom-in": "ズームイン",
|
||||
"zoom-out": "ズームアウト",
|
||||
"zoom-reset": "ズームリセット",
|
||||
"toggle-navigator": "ナビゲータ表示切替"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "2.1.6",
|
||||
"version": "2.2.0",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -684,6 +684,13 @@ RED.history = (function() {
|
||||
peek: function() {
|
||||
return undoHistory[undoHistory.length-1];
|
||||
},
|
||||
replace: function(ev) {
|
||||
if (undoHistory.length === 0) {
|
||||
RED.history.push(ev);
|
||||
} else {
|
||||
undoHistory[undoHistory.length-1] = ev;
|
||||
}
|
||||
},
|
||||
clear: function() {
|
||||
undoHistory = [];
|
||||
redoHistory = [];
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
},
|
||||
"red-ui-workspace": {
|
||||
"backspace": "core:delete-selection",
|
||||
"ctrl-backspace": "core:delete-selection-and-reconnect",
|
||||
"delete": "core:delete-selection",
|
||||
"ctrl-delete": "core:delete-selection-and-reconnect",
|
||||
"enter": "core:edit-selected-node",
|
||||
"ctrl-enter": "core:go-to-selection",
|
||||
"ctrl-c": "core:copy-selection-to-internal-clipboard",
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
**/
|
||||
RED.nodes = (function() {
|
||||
|
||||
var PORT_TYPE_INPUT = 1;
|
||||
var PORT_TYPE_OUTPUT = 0;
|
||||
|
||||
var node_defs = {};
|
||||
var linkTabMap = {};
|
||||
|
||||
@@ -2458,6 +2461,144 @@ RED.nodes = (function() {
|
||||
return helpContent;
|
||||
}
|
||||
|
||||
function getNodeIslands(nodes) {
|
||||
var selectedNodes = new Set(nodes);
|
||||
// Maps node => island index
|
||||
var nodeToIslandIndex = new Map();
|
||||
// Maps island index => [nodes in island]
|
||||
var islandIndexToNodes = new Map();
|
||||
var internalLinks = new Set();
|
||||
nodes.forEach((node, index) => {
|
||||
nodeToIslandIndex.set(node,index);
|
||||
islandIndexToNodes.set(index, [node]);
|
||||
var inboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_INPUT);
|
||||
var outboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT);
|
||||
inboundLinks.forEach(l => {
|
||||
if (selectedNodes.has(l.source)) {
|
||||
internalLinks.add(l)
|
||||
}
|
||||
})
|
||||
outboundLinks.forEach(l => {
|
||||
if (selectedNodes.has(l.target)) {
|
||||
internalLinks.add(l)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
internalLinks.forEach(l => {
|
||||
let source = l.source;
|
||||
let target = l.target;
|
||||
if (nodeToIslandIndex.get(source) !== nodeToIslandIndex.get(target)) {
|
||||
let sourceIsland = nodeToIslandIndex.get(source);
|
||||
let islandToMove = nodeToIslandIndex.get(target);
|
||||
let nodesToMove = islandIndexToNodes.get(islandToMove);
|
||||
nodesToMove.forEach(n => {
|
||||
nodeToIslandIndex.set(n,sourceIsland);
|
||||
islandIndexToNodes.get(sourceIsland).push(n);
|
||||
})
|
||||
islandIndexToNodes.delete(islandToMove);
|
||||
}
|
||||
})
|
||||
const result = [];
|
||||
islandIndexToNodes.forEach((nodes,index) => {
|
||||
result.push(nodes);
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
function detachNodes(nodes) {
|
||||
let allSelectedNodes = [];
|
||||
nodes.forEach(node => {
|
||||
if (node.type === 'group') {
|
||||
let groupNodes = RED.group.getNodes(node,true,true);
|
||||
allSelectedNodes = allSelectedNodes.concat(groupNodes);
|
||||
} else {
|
||||
allSelectedNodes.push(node);
|
||||
}
|
||||
})
|
||||
if (allSelectedNodes.length > 0 ) {
|
||||
const nodeIslands = RED.nodes.getNodeIslands(allSelectedNodes);
|
||||
let removedLinks = [];
|
||||
let newLinks = [];
|
||||
let createdLinkIds = new Set();
|
||||
|
||||
nodeIslands.forEach(nodes => {
|
||||
let selectedNodes = new Set(nodes);
|
||||
let allInboundLinks = [];
|
||||
let allOutboundLinks = [];
|
||||
// Identify links that enter or exit this island of nodes
|
||||
nodes.forEach(node => {
|
||||
var inboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_INPUT);
|
||||
var outboundLinks = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT);
|
||||
inboundLinks.forEach(l => {
|
||||
if (!selectedNodes.has(l.source)) {
|
||||
allInboundLinks.push(l)
|
||||
}
|
||||
})
|
||||
outboundLinks.forEach(l => {
|
||||
if (!selectedNodes.has(l.target)) {
|
||||
allOutboundLinks.push(l)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
// Identify the links to restore
|
||||
allInboundLinks.forEach(inLink => {
|
||||
// For Each inbound link,
|
||||
// - get source node.
|
||||
// - trace through to all outbound links
|
||||
let sourceNode = inLink.source;
|
||||
let targetNodes = new Set();
|
||||
let visited = new Set();
|
||||
let stack = [inLink.target];
|
||||
while (stack.length > 0) {
|
||||
let node = stack.pop(stack);
|
||||
visited.add(node)
|
||||
let links = RED.nodes.getNodeLinks(node, PORT_TYPE_OUTPUT);
|
||||
links.forEach(l => {
|
||||
if (visited.has(l.target)) {
|
||||
return
|
||||
}
|
||||
visited.add(l.target);
|
||||
if (selectedNodes.has(l.target)) {
|
||||
// internal link
|
||||
stack.push(l.target)
|
||||
} else {
|
||||
targetNodes.add(l.target)
|
||||
}
|
||||
})
|
||||
}
|
||||
targetNodes.forEach(target => {
|
||||
let linkId = `${sourceNode.id}[${inLink.sourcePort}] -> ${target.id}`
|
||||
if (!createdLinkIds.has(linkId)) {
|
||||
createdLinkIds.add(linkId);
|
||||
let link = {
|
||||
source: sourceNode,
|
||||
sourcePort: inLink.sourcePort,
|
||||
target: target
|
||||
}
|
||||
let existingLinks = RED.nodes.filterLinks(link)
|
||||
if (existingLinks.length === 0) {
|
||||
newLinks.push(link);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 2. delete all those links
|
||||
allInboundLinks.forEach(l => { RED.nodes.removeLink(l); removedLinks.push(l)})
|
||||
allOutboundLinks.forEach(l => { RED.nodes.removeLink(l); removedLinks.push(l)})
|
||||
})
|
||||
|
||||
newLinks.forEach(l => RED.nodes.addLink(l));
|
||||
return {
|
||||
newLinks,
|
||||
removedLinks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
RED.events.on("registry:node-type-added",function(type) {
|
||||
@@ -2539,7 +2680,7 @@ RED.nodes = (function() {
|
||||
add: addNode,
|
||||
remove: removeNode,
|
||||
clear: clear,
|
||||
|
||||
detachNodes: detachNodes,
|
||||
moveNodesForwards: moveNodesForwards,
|
||||
moveNodesBackwards: moveNodesBackwards,
|
||||
moveNodesToFront: moveNodesToFront,
|
||||
@@ -2551,7 +2692,20 @@ RED.nodes = (function() {
|
||||
|
||||
addLink: addLink,
|
||||
removeLink: removeLink,
|
||||
|
||||
getNodeLinks: function(id, portType) {
|
||||
if (typeof id !== 'string') {
|
||||
id = id.id;
|
||||
}
|
||||
if (nodeLinks[id]) {
|
||||
if (portType === 1) {
|
||||
// Return cloned arrays so they can be safely modified by caller
|
||||
return [].concat(nodeLinks[id].in)
|
||||
} else {
|
||||
return [].concat(nodeLinks[id].out)
|
||||
}
|
||||
}
|
||||
return [];
|
||||
},
|
||||
addWorkspace: addWorkspace,
|
||||
removeWorkspace: removeWorkspace,
|
||||
getWorkspaceOrder: function() { return workspacesOrder },
|
||||
@@ -2625,6 +2779,7 @@ RED.nodes = (function() {
|
||||
getAllFlowNodes: getAllFlowNodes,
|
||||
getAllUpstreamNodes: getAllUpstreamNodes,
|
||||
getAllDownstreamNodes: getAllDownstreamNodes,
|
||||
getNodeIslands: getNodeIslands,
|
||||
createExportableNodeSet: createExportableNodeSet,
|
||||
createCompleteNodeSet: createCompleteNodeSet,
|
||||
updateConfigNodeUsers: updateConfigNodeUsers,
|
||||
|
||||
@@ -556,8 +556,7 @@ var RED = (function() {
|
||||
|
||||
$(".red-ui-header-toolbar").show();
|
||||
|
||||
|
||||
RED.sidebar.show(":first");
|
||||
RED.sidebar.show(":first", true);
|
||||
|
||||
setTimeout(function() {
|
||||
loader.end();
|
||||
|
||||
@@ -160,18 +160,19 @@ RED.actionList = (function() {
|
||||
createDialog();
|
||||
}
|
||||
dialog.slideDown(300);
|
||||
searchInput.searchBox('value',v)
|
||||
searchInput.searchBox('value',v);
|
||||
searchResults.editableList('empty');
|
||||
results = [];
|
||||
var actions = RED.actions.list();
|
||||
actions.sort(function(A,B) {
|
||||
return A.id.localeCompare(B.id);
|
||||
var Akey = A.label;
|
||||
var Bkey = B.label;
|
||||
return Akey.localeCompare(Bkey);
|
||||
});
|
||||
actions.forEach(function(action) {
|
||||
action.label = action.id.replace(/:/,": ").replace(/-/g," ").replace(/(^| )./g,function() { return arguments[0].toUpperCase()});
|
||||
action._label = action.label.toLowerCase();
|
||||
searchResults.editableList('addItem',action)
|
||||
})
|
||||
searchResults.editableList('addItem',action);
|
||||
});
|
||||
RED.events.emit("actionList:open");
|
||||
visible = true;
|
||||
}
|
||||
|
||||
@@ -1,33 +1,39 @@
|
||||
RED.actions = (function() {
|
||||
var actions = {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function addAction(name,handler) {
|
||||
function addAction(name,handler,options) {
|
||||
if (typeof handler !== 'function') {
|
||||
throw new Error("Action handler not a function");
|
||||
}
|
||||
if (actions[name]) {
|
||||
throw new Error("Cannot override existing action");
|
||||
}
|
||||
actions[name] = handler;
|
||||
actions[name] = {
|
||||
handler: handler,
|
||||
options: options,
|
||||
};
|
||||
}
|
||||
function removeAction(name) {
|
||||
delete actions[name];
|
||||
}
|
||||
function getAction(name) {
|
||||
return actions[name];
|
||||
return actions[name].handler;
|
||||
}
|
||||
function invokeAction() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var name = args.shift();
|
||||
if (actions.hasOwnProperty(name)) {
|
||||
actions[name].apply(null, args);
|
||||
var handler = actions[name].handler;
|
||||
handler.apply(null, args);
|
||||
}
|
||||
}
|
||||
function listActions() {
|
||||
var result = [];
|
||||
var missing = [];
|
||||
Object.keys(actions).forEach(function(action) {
|
||||
var def = actions[action];
|
||||
var shortcut = RED.keyboard.getShortcut(action);
|
||||
var isUser = false;
|
||||
if (shortcut) {
|
||||
@@ -35,13 +41,38 @@ RED.actions = (function() {
|
||||
} else {
|
||||
isUser = !!RED.keyboard.getUserShortcut(action);
|
||||
}
|
||||
if (!def.label) {
|
||||
var name = action;
|
||||
var options = def.options;
|
||||
var key = options ? options.label : undefined;
|
||||
if (!key) {
|
||||
key = "action-list." +name.replace(/^.*:/,"");
|
||||
}
|
||||
var label = RED._(key);
|
||||
if (label === key) {
|
||||
// no translation. convert `name` to description
|
||||
label = name.replace(/(^.+:([a-z]))|(-([a-z]))/g, function() {
|
||||
if (arguments[5] === 0) {
|
||||
return arguments[2].toUpperCase();
|
||||
} else {
|
||||
return " "+arguments[4].toUpperCase();
|
||||
}
|
||||
});
|
||||
missing.push(key);
|
||||
}
|
||||
def.label = label;
|
||||
}
|
||||
//console.log("; missing:", missing);
|
||||
|
||||
result.push({
|
||||
id:action,
|
||||
scope:shortcut?shortcut.scope:undefined,
|
||||
key:shortcut?shortcut.key:undefined,
|
||||
user:isUser
|
||||
})
|
||||
})
|
||||
user:isUser,
|
||||
label: def.label,
|
||||
options: def.options,
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -350,6 +350,15 @@ RED.popover = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
target.on("remove", function (ev) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
if (active) {
|
||||
active = false;
|
||||
setTimeout(closePopup,delay.hide);
|
||||
}
|
||||
});
|
||||
if (trigger === 'hover') {
|
||||
target.on('mouseenter',function(e) {
|
||||
clearTimeout(timer);
|
||||
|
||||
@@ -557,23 +557,19 @@ RED.tabs = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
li.one("transitionend", function(evt) {
|
||||
li.remove();
|
||||
if (tabs[id].pinned) {
|
||||
pinnedTabsCount--;
|
||||
}
|
||||
if (options.onremove) {
|
||||
options.onremove(tabs[id]);
|
||||
}
|
||||
delete tabs[id];
|
||||
updateTabWidths();
|
||||
if (collapsibleMenu) {
|
||||
collapsibleMenu.remove();
|
||||
collapsibleMenu = null;
|
||||
}
|
||||
})
|
||||
li.addClass("hide-tab");
|
||||
li.width(0);
|
||||
li.remove();
|
||||
if (tabs[id].pinned) {
|
||||
pinnedTabsCount--;
|
||||
}
|
||||
if (options.onremove) {
|
||||
options.onremove(tabs[id]);
|
||||
}
|
||||
delete tabs[id];
|
||||
updateTabWidths();
|
||||
if (collapsibleMenu) {
|
||||
collapsibleMenu.remove();
|
||||
collapsibleMenu = null;
|
||||
}
|
||||
}
|
||||
|
||||
function findPreviousVisibleTab(li) {
|
||||
|
||||
@@ -333,6 +333,19 @@ RED.deploy = (function() {
|
||||
var unknownNodes = [];
|
||||
var invalidNodes = [];
|
||||
|
||||
RED.nodes.eachConfig(function(node) {
|
||||
if (node.valid === undefined) {
|
||||
RED.editor.validateNode(node);
|
||||
}
|
||||
if (!node.valid && !node.d) {
|
||||
invalidNodes.push(getNodeInfo(node));
|
||||
}
|
||||
if (node.type === "unknown") {
|
||||
if (unknownNodes.indexOf(node.name) == -1) {
|
||||
unknownNodes.push(node.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.nodes.eachNode(function(node) {
|
||||
if (!node.valid && !node.d) {
|
||||
invalidNodes.push(getNodeInfo(node));
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
editState.changed = true;
|
||||
}
|
||||
if (!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) {
|
||||
var icon = $("#red-ui-editor-node-icon").val()||""
|
||||
var icon = $("#red-ui-editor-node-icon").val()||"";
|
||||
if (!this.isDefaultIcon) {
|
||||
if (icon !== node.icon) {
|
||||
if ((icon !== node.icon) &&
|
||||
(icon !== "")) {
|
||||
editState.changes.icon = node.icon;
|
||||
node.icon = icon;
|
||||
editState.changed = true;
|
||||
@@ -101,14 +102,14 @@
|
||||
if (showLabel) {
|
||||
// Default to show label
|
||||
if (node.l !== false) {
|
||||
editState.changes.l = node.l
|
||||
editState.changes.l = node.l;
|
||||
editState.changed = true;
|
||||
}
|
||||
node.l = false;
|
||||
} else {
|
||||
// Node has showLabel:false (eg link nodes)
|
||||
if (node.hasOwnProperty('l') && node.l) {
|
||||
editState.changes.l = node.l
|
||||
editState.changes.l = node.l;
|
||||
editState.changed = true;
|
||||
}
|
||||
delete node.l;
|
||||
@@ -118,20 +119,20 @@
|
||||
if (showLabel) {
|
||||
// Default to show label
|
||||
if (node.hasOwnProperty('l') && !node.l) {
|
||||
editState.changes.l = node.l
|
||||
editState.changes.l = node.l;
|
||||
editState.changed = true;
|
||||
}
|
||||
delete node.l;
|
||||
} else {
|
||||
if (!node.l) {
|
||||
editState.changes.l = node.l
|
||||
editState.changes.l = node.l;
|
||||
editState.changed = true;
|
||||
}
|
||||
node.l = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
function buildAppearanceForm(container,node) {
|
||||
@@ -164,10 +165,10 @@
|
||||
var categories = RED.palette.getCategories();
|
||||
categories.sort(function(A,B) {
|
||||
return A.label.localeCompare(B.label);
|
||||
})
|
||||
});
|
||||
categories.forEach(function(cat) {
|
||||
categorySelector.append($("<option/>").val(cat.id).text(cat.label));
|
||||
})
|
||||
});
|
||||
categorySelector.append($("<option/>").attr('disabled',true).text("---"));
|
||||
categorySelector.append($("<option/>").val("_custom_").text(RED._("palette.addCategory")));
|
||||
|
||||
@@ -180,7 +181,7 @@
|
||||
$("#subflow-appearance-input-category").width(250);
|
||||
$("#subflow-appearance-input-custom-category").hide();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$("#subflow-appearance-input-category").val(node.category||"subflows");
|
||||
var userCount = 0;
|
||||
@@ -204,7 +205,7 @@
|
||||
$("#node-input-show-label").toggleButton({
|
||||
enabledLabel: RED._("editor.show"),
|
||||
disabledLabel: RED._("editor.hide")
|
||||
})
|
||||
});
|
||||
|
||||
if (!node.hasOwnProperty("l")) {
|
||||
// Show label unless def.showLabel set to false
|
||||
@@ -230,7 +231,7 @@
|
||||
"#E9967A", "#F3B567", "#FDD0A2",
|
||||
"#FDF0C2", "#FFAAAA", "#FFCC66",
|
||||
"#FFF0F0", "#FFFFFF"
|
||||
]
|
||||
];
|
||||
|
||||
RED.editor.colorPicker.create({
|
||||
id: "red-ui-editor-node-color",
|
||||
@@ -245,9 +246,9 @@
|
||||
nodeDiv.css('backgroundColor',colour);
|
||||
var borderColor = RED.utils.getDarkerColor(colour);
|
||||
if (borderColor !== colour) {
|
||||
nodeDiv.css('border-color',borderColor)
|
||||
nodeDiv.css('border-color',borderColor);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +265,7 @@
|
||||
nodeDiv.css('backgroundColor',colour);
|
||||
var borderColor = RED.utils.getDarkerColor(colour);
|
||||
if (borderColor !== colour) {
|
||||
nodeDiv.css('border-color',borderColor)
|
||||
nodeDiv.css('border-color',borderColor);
|
||||
}
|
||||
|
||||
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
|
||||
@@ -292,7 +293,7 @@
|
||||
|
||||
RED.popover.tooltip(iconButton, function() {
|
||||
return $("#red-ui-editor-node-icon").val() || RED._("editor.default");
|
||||
})
|
||||
});
|
||||
$('<input type="hidden" id="red-ui-editor-node-icon">').val(node.icon).appendTo(iconRow);
|
||||
}
|
||||
|
||||
@@ -417,11 +418,11 @@
|
||||
});
|
||||
rows.sort(function(A,B) {
|
||||
return A.i-B.i;
|
||||
})
|
||||
});
|
||||
rows.forEach(function(r,i) {
|
||||
r.r.find("label").text((i+1)+".");
|
||||
r.r.appendTo(outputsDiv);
|
||||
})
|
||||
});
|
||||
if (rows.length === 0) {
|
||||
buildLabelRow("output",i,"").appendTo(outputsDiv);
|
||||
} else {
|
||||
@@ -467,7 +468,7 @@
|
||||
clear.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
input.val("");
|
||||
})
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -501,6 +502,12 @@
|
||||
}
|
||||
var v = $(this).val();
|
||||
hasNonBlankLabel = hasNonBlankLabel || v!== "";
|
||||
|
||||
// mark changed output port labels as dirty
|
||||
if (node.type === "subflow" && (!node.outputLabels || node.outputLabels[index] !== v)) {
|
||||
node.out[index].dirty = true;
|
||||
}
|
||||
|
||||
newValue[index] = v;
|
||||
});
|
||||
|
||||
@@ -509,6 +516,12 @@
|
||||
changes.outputLabels = node.outputLabels;
|
||||
node.outputLabels = newValue;
|
||||
changed = true;
|
||||
|
||||
// trigger redraw of dirty port labels
|
||||
if (node.type === "subflow") {
|
||||
RED.view.redraw();
|
||||
}
|
||||
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -590,12 +590,14 @@ RED.group = (function() {
|
||||
markDirty(group);
|
||||
}
|
||||
|
||||
function getNodes(group,recursive) {
|
||||
function getNodes(group,recursive,excludeGroup) {
|
||||
var nodes = [];
|
||||
group.nodes.forEach(function(n) {
|
||||
nodes.push(n);
|
||||
if (n.type !== 'group' || !excludeGroup) {
|
||||
nodes.push(n);
|
||||
}
|
||||
if (recursive && n.type === 'group') {
|
||||
nodes = nodes.concat(getNodes(n,recursive))
|
||||
nodes = nodes.concat(getNodes(n,recursive,excludeGroup))
|
||||
}
|
||||
})
|
||||
return nodes;
|
||||
|
||||
@@ -49,15 +49,15 @@ RED.keyboard = (function() {
|
||||
"]": 221,
|
||||
"{": 219,// <- QWERTY specific
|
||||
"}": 221 // <- QWERTY specific
|
||||
}
|
||||
};
|
||||
var metaKeyCodes = {
|
||||
16: true,
|
||||
17: true,
|
||||
18: true,
|
||||
91: true,
|
||||
93: true
|
||||
}
|
||||
var actionToKeyMap = {}
|
||||
};
|
||||
var actionToKeyMap = {};
|
||||
var defaultKeyMap = {};
|
||||
|
||||
// FF generates some different keycodes because reasons.
|
||||
@@ -65,7 +65,7 @@ RED.keyboard = (function() {
|
||||
59:186,
|
||||
61:187,
|
||||
173:189
|
||||
}
|
||||
};
|
||||
|
||||
function migrateOldKeymap() {
|
||||
// pre-0.18
|
||||
@@ -80,7 +80,7 @@ RED.keyboard = (function() {
|
||||
}
|
||||
|
||||
function getUserKey(action) {
|
||||
return RED.settings.get('editor.keymap',{})[action]
|
||||
return RED.settings.get('editor.keymap',{})[action];
|
||||
}
|
||||
|
||||
function mergeKeymaps(defaultKeymap, themeKeymap) {
|
||||
@@ -105,7 +105,7 @@ RED.keyboard = (function() {
|
||||
scope:scope,
|
||||
key:key,
|
||||
user:false
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,13 +115,13 @@ RED.keyboard = (function() {
|
||||
if (themeKeymap.hasOwnProperty(action)) {
|
||||
if (!themeKeymap[action].key) {
|
||||
// No key for this action - default is no keybinding
|
||||
delete mergedKeymap[action]
|
||||
delete mergedKeymap[action];
|
||||
} else {
|
||||
mergedKeymap[action] = [{
|
||||
scope: themeKeymap[action].scope || "*",
|
||||
key: themeKeymap[action].key,
|
||||
user: false
|
||||
}]
|
||||
}];
|
||||
if (mergedKeymap[action][0].scope === "workspace") {
|
||||
mergedKeymap[action][0].scope = "red-ui-workspace";
|
||||
}
|
||||
@@ -179,7 +179,7 @@ RED.keyboard = (function() {
|
||||
close: function() {
|
||||
RED.menu.refreshShortcuts();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function revertToDefault(action) {
|
||||
@@ -327,7 +327,7 @@ RED.keyboard = (function() {
|
||||
scope:scope,
|
||||
key:key,
|
||||
user:false
|
||||
}
|
||||
};
|
||||
}
|
||||
if (!ondown) {
|
||||
var userAction = getUserKey(cbdown);
|
||||
@@ -350,7 +350,7 @@ RED.keyboard = (function() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keys.push([key,mod])
|
||||
keys.push([key,mod]);
|
||||
}
|
||||
var slot = handlers;
|
||||
for (i=0;i<keys.length;i++) {
|
||||
@@ -373,7 +373,7 @@ RED.keyboard = (function() {
|
||||
//slot[key] = {scope: scope, ondown:cbdown};
|
||||
}
|
||||
slot.handlers = slot.handlers || [];
|
||||
slot.handlers.push({scope:scope,ondown:cbdown})
|
||||
slot.handlers.push({scope:scope,ondown:cbdown});
|
||||
slot.scope = scope;
|
||||
slot.ondown = cbdown;
|
||||
}
|
||||
@@ -390,12 +390,12 @@ RED.keyboard = (function() {
|
||||
if (parsedKey) {
|
||||
keys.push(parsedKey);
|
||||
} else {
|
||||
console.log("Unrecognised key specifier:",key)
|
||||
console.log("Unrecognised key specifier:",key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keys.push([key,mod])
|
||||
keys.push([key,mod]);
|
||||
}
|
||||
var slot = handlers;
|
||||
for (i=0;i<keys.length;i++) {
|
||||
@@ -417,7 +417,7 @@ RED.keyboard = (function() {
|
||||
}
|
||||
if (typeof slot.ondown === "string") {
|
||||
if (typeof modifiers === 'boolean' && modifiers) {
|
||||
actionToKeyMap[slot.ondown] = {user: modifiers}
|
||||
actionToKeyMap[slot.ondown] = {user: modifiers};
|
||||
} else {
|
||||
delete actionToKeyMap[slot.ondown];
|
||||
}
|
||||
@@ -433,11 +433,11 @@ RED.keyboard = (function() {
|
||||
function formatKey(key,plain) {
|
||||
var formattedKey = isMac?key.replace(/ctrl-?/,"⌘"):key;
|
||||
formattedKey = isMac?formattedKey.replace(/alt-?/,"⌥"):key;
|
||||
formattedKey = formattedKey.replace(/shift-?/,"⇧")
|
||||
formattedKey = formattedKey.replace(/left/,"←")
|
||||
formattedKey = formattedKey.replace(/up/,"↑")
|
||||
formattedKey = formattedKey.replace(/right/,"→")
|
||||
formattedKey = formattedKey.replace(/down/,"↓")
|
||||
formattedKey = formattedKey.replace(/shift-?/,"⇧");
|
||||
formattedKey = formattedKey.replace(/left/,"←");
|
||||
formattedKey = formattedKey.replace(/up/,"↑");
|
||||
formattedKey = formattedKey.replace(/right/,"→");
|
||||
formattedKey = formattedKey.replace(/down/,"↓");
|
||||
if (plain) {
|
||||
return formattedKey;
|
||||
}
|
||||
@@ -461,7 +461,6 @@ RED.keyboard = (function() {
|
||||
var container = $(this);
|
||||
var object = container.data('data');
|
||||
|
||||
|
||||
if (!container.hasClass('keyboard-shortcut-entry-expanded')) {
|
||||
endEditShortcut();
|
||||
|
||||
@@ -485,7 +484,7 @@ RED.keyboard = (function() {
|
||||
}
|
||||
$(this).toggleClass("input-error",!valid);
|
||||
okButton.attr("disabled",!valid);
|
||||
})
|
||||
});
|
||||
|
||||
var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope);
|
||||
scopeSelect.i18n();
|
||||
@@ -495,7 +494,7 @@ RED.keyboard = (function() {
|
||||
scopeSelect.val(object.scope||'*');
|
||||
scopeSelect.on("change", function() {
|
||||
keyInput.trigger("change");
|
||||
})
|
||||
});
|
||||
|
||||
var div = $('<div class="keyboard-shortcut-edit button-group-vertical"></div>').appendTo(scope);
|
||||
var okButton = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-check"></i></button>').appendTo(div);
|
||||
@@ -521,10 +520,13 @@ RED.keyboard = (function() {
|
||||
id:object.id,
|
||||
scope:shortcut?shortcut.scope:undefined,
|
||||
key:shortcut?shortcut.key:undefined,
|
||||
user:shortcut?shortcut.user:undefined
|
||||
}
|
||||
user:shortcut?shortcut.user:undefined,
|
||||
|
||||
label: object.label,
|
||||
options: object.options,
|
||||
};
|
||||
buildShortcutRow(container,obj);
|
||||
})
|
||||
});
|
||||
|
||||
keyInput.trigger("focus");
|
||||
}
|
||||
@@ -559,7 +561,7 @@ RED.keyboard = (function() {
|
||||
delete object.scope;
|
||||
} else {
|
||||
keyDiv.parent().removeClass("keyboard-shortcut-entry-unassigned");
|
||||
keyDiv.append(RED.keyboard.formatKey(key))
|
||||
keyDiv.append(RED.keyboard.formatKey(key));
|
||||
$("<span>").text(scope).appendTo(scopeDiv);
|
||||
object.key = key;
|
||||
object.scope = scope;
|
||||
@@ -572,7 +574,7 @@ RED.keyboard = (function() {
|
||||
userKeymap[object.id] = {
|
||||
scope:shortcut.scope,
|
||||
key:shortcut.key
|
||||
}
|
||||
};
|
||||
RED.settings.set('editor.keymap',userKeymap);
|
||||
}
|
||||
}
|
||||
@@ -588,13 +590,7 @@ RED.keyboard = (function() {
|
||||
var item = $('<div class="keyboard-shortcut-entry">').appendTo(container);
|
||||
container.data('data',object);
|
||||
|
||||
var text = object.id.replace(/(^.+:([a-z]))|(-([a-z]))/g,function() {
|
||||
if (arguments[5] === 0) {
|
||||
return arguments[2].toUpperCase();
|
||||
} else {
|
||||
return " "+arguments[4].toUpperCase();
|
||||
}
|
||||
});
|
||||
var text = object.label;
|
||||
var label = $('<div>').addClass("keyboard-shortcut-entry-text").text(text).appendTo(item);
|
||||
|
||||
var user = $('<i class="fa fa-user"></i>').prependTo(label);
|
||||
@@ -635,8 +631,9 @@ RED.keyboard = (function() {
|
||||
} else {
|
||||
filterValue = filterValue.replace(/\s/g,"");
|
||||
shortcutList.editableList('filter', function(data) {
|
||||
return data.id.toLowerCase().replace(/^.*:/,"").replace("-","").indexOf(filterValue) > -1;
|
||||
})
|
||||
var label = data.label.toLowerCase();
|
||||
return label.indexOf(filterValue) > -1;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -657,9 +654,9 @@ RED.keyboard = (function() {
|
||||
});
|
||||
var shortcuts = RED.actions.list();
|
||||
shortcuts.sort(function(A,B) {
|
||||
var Aid = A.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
|
||||
var Bid = B.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
|
||||
return Aid.localeCompare(Bid);
|
||||
var Akey = A.label;
|
||||
var Bkey = B.label;
|
||||
return Akey.localeCompare(Bkey);
|
||||
});
|
||||
knownShortcuts = new Set();
|
||||
shortcuts.forEach(function(s) {
|
||||
|
||||
@@ -1212,6 +1212,9 @@ RED.projects = (function() {
|
||||
}
|
||||
}).appendTo(row);
|
||||
|
||||
row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-open"></div>').hide().appendTo(container);
|
||||
$('<span style="display: flex; align-items: center;"><input style="padding:0; margin: 0 5px 0 0" checked type="checkbox" id="red-ui-projects-dialog-screen-clear-context"> <label for="red-ui-projects-dialog-screen-clear-context" style="padding:0; margin: 0"> <span data-i18n="projects.create.clearContext"></span></label></span>').appendTo(row).i18n();
|
||||
|
||||
row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-empty red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(container);
|
||||
$('<label for="red-ui-projects-dialog-screen-create-project-name">'+RED._("projects.create.project-name")+'</label>').appendTo(row);
|
||||
|
||||
@@ -1501,7 +1504,8 @@ RED.projects = (function() {
|
||||
};
|
||||
}
|
||||
} else if (projectType === 'open') {
|
||||
return switchProject(selectedProject.name,function(err,data) {
|
||||
var clearContext = $("#red-ui-projects-dialog-screen-clear-context").prop("checked")
|
||||
return switchProject(selectedProject.name, clearContext, function(err,data) {
|
||||
if (err) {
|
||||
if (err.code !== 'credentials_load_failed') {
|
||||
console.log(RED._("projects.create.unexpected_error"),err)
|
||||
@@ -1595,7 +1599,7 @@ RED.projects = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function switchProject(name,done) {
|
||||
function switchProject(name,clearContext,done) {
|
||||
RED.deploy.setDeployInflight(true);
|
||||
RED.projects.settings.switchProject(name);
|
||||
sendRequest({
|
||||
@@ -1614,7 +1618,7 @@ RED.projects = (function() {
|
||||
'*': done
|
||||
},
|
||||
}
|
||||
},{active:true}).then(function() {
|
||||
},{active:true, clearContext:clearContext}).then(function() {
|
||||
dialog.dialog( "close" );
|
||||
RED.events.emit("project:change", {name:name});
|
||||
}).always(function() {
|
||||
@@ -1687,7 +1691,7 @@ RED.projects = (function() {
|
||||
dialogHeight = 590 - (750 - winHeight);
|
||||
}
|
||||
$(".red-ui-projects-dialog-box").height(dialogHeight);
|
||||
$(".red-ui-projects-dialog-project-list-inner-container").height(Math.max(500,dialogHeight) - 180);
|
||||
$(".red-ui-projects-dialog-project-list-inner-container").height(Math.max(500,dialogHeight) - 210);
|
||||
dialog.dialog('option','title',screen.title||"");
|
||||
dialog.dialog("open");
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ RED.search = (function() {
|
||||
var selected = -1;
|
||||
var visible = false;
|
||||
|
||||
var searchHistory = [];
|
||||
var index = {};
|
||||
var currentResults = [];
|
||||
var previousActiveElement;
|
||||
@@ -52,10 +53,22 @@ RED.search = (function() {
|
||||
}
|
||||
l = l||n.label||n.name||n.id||"";
|
||||
|
||||
|
||||
var properties = ['id','type','name','label','info'];
|
||||
if (n._def && n._def.defaults) {
|
||||
properties = properties.concat(Object.keys(n._def.defaults));
|
||||
const node_def = n && n._def;
|
||||
if (node_def) {
|
||||
if (node_def.defaults) {
|
||||
properties = properties.concat(Object.keys(node_def.defaults));
|
||||
}
|
||||
if (n.type !== "group" && node_def.paletteLabel && node_def.paletteLabel !== node_def.type) {
|
||||
try {
|
||||
const label = ("" + (typeof node_def.paletteLabel === "function" ? node_def.paletteLabel.call(node_def) : node_def.paletteLabel)).toLowerCase();
|
||||
if(label && label !== (""+node_def.type).toLowerCase()) {
|
||||
indexProperty(n, l, label);
|
||||
}
|
||||
} catch(err) {
|
||||
console.warn(`error indexing ${l}`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i=0;i<properties.length;i++) {
|
||||
if (n.hasOwnProperty(properties[i])) {
|
||||
@@ -205,6 +218,20 @@ RED.search = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function populateSearchHistory() {
|
||||
if (searchHistory.length > 0) {
|
||||
searchResults.editableList('addItem',{
|
||||
historyHeader: true
|
||||
});
|
||||
searchHistory.forEach(function(entry) {
|
||||
searchResults.editableList('addItem',{
|
||||
history: true,
|
||||
value: entry
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
function createDialog() {
|
||||
dialog = $("<div>",{id:"red-ui-search",class:"red-ui-search"}).appendTo("#red-ui-main-container");
|
||||
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
|
||||
@@ -213,7 +240,12 @@ RED.search = (function() {
|
||||
change: function() {
|
||||
searchResults.editableList('empty');
|
||||
selected = -1;
|
||||
currentResults = search($(this).val());
|
||||
var value = $(this).val();
|
||||
if (value === "") {
|
||||
populateSearchHistory();
|
||||
return;
|
||||
}
|
||||
currentResults = search(value);
|
||||
if (currentResults.length > 0) {
|
||||
for (i=0;i<Math.min(currentResults.length,25);i++) {
|
||||
searchResults.editableList('addItem',currentResults[i])
|
||||
@@ -285,7 +317,12 @@ RED.search = (function() {
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} if ($(children[selected]).hasClass("red-ui-search-history")) {
|
||||
var object = $(children[selected]).find(".red-ui-editableList-item-content").data('data');
|
||||
if (object) {
|
||||
searchInput.searchBox('value',object.value)
|
||||
}
|
||||
} else if (!$(children[selected]).hasClass("red-ui-search-historyHeader")) {
|
||||
if (currentResults.length > 0) {
|
||||
reveal(currentResults[Math.max(0,selected)].node);
|
||||
}
|
||||
@@ -301,7 +338,32 @@ RED.search = (function() {
|
||||
addItem: function(container,i,object) {
|
||||
var node = object.node;
|
||||
var div;
|
||||
if (object.more) {
|
||||
if (object.historyHeader) {
|
||||
container.parent().addClass("red-ui-search-historyHeader")
|
||||
$('<div>',{class:"red-ui-search-empty"}).text(RED._("search.history")).appendTo(container);
|
||||
$('<button type="button" class="red-ui-button red-ui-button-small"></button>').text(RED._("search.clear")).appendTo(container).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
searchHistory = [];
|
||||
searchResults.editableList('empty');
|
||||
});
|
||||
} else if (object.history) {
|
||||
container.parent().addClass("red-ui-search-history")
|
||||
div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
|
||||
div.text(object.value);
|
||||
div.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
searchInput.searchBox('value',object.value)
|
||||
searchInput.focus();
|
||||
})
|
||||
$('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-remove"></i></button>').appendTo(container).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
var index = searchHistory.indexOf(object.value);
|
||||
searchHistory.splice(index,1);
|
||||
searchResults.editableList('removeItem', object);
|
||||
});
|
||||
|
||||
|
||||
} else if (object.more) {
|
||||
container.parent().addClass("red-ui-search-more")
|
||||
div = $('<a>',{href:'#',class:"red-ui-search-result red-ui-search-empty"}).appendTo(container);
|
||||
div.text(RED._("palette.editor.more",{count:object.more.results.length-object.more.start}));
|
||||
@@ -356,6 +418,12 @@ RED.search = (function() {
|
||||
}
|
||||
|
||||
function reveal(node) {
|
||||
var searchVal = searchInput.val();
|
||||
var existingIndex = searchHistory.indexOf(searchVal);
|
||||
if (existingIndex > -1) {
|
||||
searchHistory.splice(existingIndex,1);
|
||||
}
|
||||
searchHistory.unshift(searchInput.val());
|
||||
hide();
|
||||
RED.view.reveal(node.id);
|
||||
}
|
||||
@@ -374,9 +442,14 @@ RED.search = (function() {
|
||||
|
||||
if (dialog === null) {
|
||||
createDialog();
|
||||
} else {
|
||||
searchResults.editableList('empty');
|
||||
}
|
||||
dialog.slideDown(300);
|
||||
searchInput.searchBox('value',v)
|
||||
if (!v || v === "") {
|
||||
populateSearchHistory();
|
||||
}
|
||||
RED.events.emit("search:open");
|
||||
visible = true;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,15 @@ RED.sidebar = (function() {
|
||||
var sidebar_tabs;
|
||||
var knownTabs = {};
|
||||
|
||||
// We store the current sidebar tab id in localStorage as 'last-sidebar-tab'
|
||||
// This is restored when the editor is reloaded.
|
||||
// We use sidebar_tabs.onchange to update localStorage. However that will
|
||||
// also get triggered when the first tab gets added to the tabs - typically
|
||||
// the 'info' tab. So we use the following variable to store the retrieved
|
||||
// value from localStorage before we start adding the actual tabs
|
||||
var lastSessionSelectedTab = null;
|
||||
|
||||
|
||||
function addTab(title,content,closeable,visible) {
|
||||
var options;
|
||||
if (typeof title === "string") {
|
||||
@@ -194,16 +203,16 @@ RED.sidebar = (function() {
|
||||
RED.events.emit("sidebar:resize");
|
||||
}
|
||||
|
||||
function showSidebar(id) {
|
||||
function showSidebar(id, skipShowSidebar) {
|
||||
if (id === ":first") {
|
||||
id = RED.settings.get("editor.sidebar.order",["info", "help", "version-control", "debug"])[0]
|
||||
id = lastSessionSelectedTab || RED.settings.get("editor.sidebar.order",["info", "help", "version-control", "debug"])[0]
|
||||
}
|
||||
if (id) {
|
||||
if (!containsTab(id) && knownTabs[id]) {
|
||||
sidebar_tabs.addTab(knownTabs[id]);
|
||||
}
|
||||
sidebar_tabs.activateTab(id);
|
||||
if (!RED.menu.isSelected("menu-item-sidebar")) {
|
||||
if (!skipShowSidebar && !RED.menu.isSelected("menu-item-sidebar")) {
|
||||
RED.menu.setSelected("menu-item-sidebar",true);
|
||||
}
|
||||
}
|
||||
@@ -227,6 +236,7 @@ RED.sidebar = (function() {
|
||||
if (tab.toolbar) {
|
||||
$(tab.toolbar).show();
|
||||
}
|
||||
RED.settings.setLocal("last-sidebar-tab", tab.id)
|
||||
},
|
||||
onremove: function(tab) {
|
||||
$(tab.wrapper).hide();
|
||||
@@ -255,7 +265,9 @@ RED.sidebar = (function() {
|
||||
}
|
||||
});
|
||||
RED.popover.tooltip($("#red-ui-sidebar-separator").find(".red-ui-sidebar-control-right"),RED._("keyboard.toggleSidebar"),"core:toggle-sidebar");
|
||||
showSidebar();
|
||||
|
||||
lastSessionSelectedTab = RED.settings.getLocal("last-sidebar-tab")
|
||||
|
||||
RED.sidebar.info.init();
|
||||
RED.sidebar.help.init();
|
||||
RED.sidebar.config.init();
|
||||
|
||||
@@ -27,5 +27,7 @@ RED.state = {
|
||||
PANNING: 10,
|
||||
SELECTING_NODE: 11,
|
||||
GROUP_DRAGGING: 12,
|
||||
GROUP_RESIZE: 13
|
||||
GROUP_RESIZE: 13,
|
||||
DETACHED_DRAGGING: 14,
|
||||
SLICING: 15
|
||||
}
|
||||
|
||||
@@ -64,15 +64,17 @@ RED.sidebar.help = (function() {
|
||||
style: "compact",
|
||||
delay: 100,
|
||||
change: function() {
|
||||
var val = $(this).val().toLowerCase();
|
||||
if (val) {
|
||||
const searchFor = $(this).val().toLowerCase();
|
||||
if (searchFor) {
|
||||
showTOC();
|
||||
var c = treeList.treeList('filter',function(item) {
|
||||
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)
|
||||
let found = item.nodeType && item.nodeType.toLowerCase().indexOf(searchFor) > -1;
|
||||
found = found || item.subflowLabel && item.subflowLabel.toLowerCase().indexOf(searchFor) > -1;
|
||||
found = found || item.palleteLabel && item.palleteLabel.toLowerCase().indexOf(searchFor) > -1;
|
||||
return found;
|
||||
},true)
|
||||
} else {
|
||||
treeList.treeList('filter',null);
|
||||
@@ -224,17 +226,21 @@ RED.sidebar.help = (function() {
|
||||
|
||||
|
||||
moduleNames.forEach(function(moduleName) {
|
||||
var module = modules[moduleName];
|
||||
var nodeTypes = [];
|
||||
|
||||
var setNames = Object.keys(module.sets);
|
||||
const module = modules[moduleName];
|
||||
const nodeTypes = [];
|
||||
const moduleSets = module.sets;
|
||||
const setNames = Object.keys(moduleSets);
|
||||
setNames.forEach(function(setName) {
|
||||
module.sets[setName].types.forEach(function(nodeType) {
|
||||
const moduleSet = moduleSets[setName];
|
||||
moduleSet.types.forEach(function(nodeType) {
|
||||
if ($("script[data-help-name='"+nodeType+"']").length) {
|
||||
const n = {_def:RED.nodes.getType(nodeType),type:nodeType}
|
||||
n.name = getNodePaletteLabel(n);
|
||||
nodeTypes.push({
|
||||
id: "node-type:"+nodeType,
|
||||
nodeType: nodeType,
|
||||
element:getNodeLabel({_def:RED.nodes.getType(nodeType),type:nodeType})
|
||||
palleteLabel: n.name,
|
||||
element: getNodeLabel(n)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -254,18 +260,21 @@ RED.sidebar.help = (function() {
|
||||
treeList.treeList("data",helpData);
|
||||
}
|
||||
|
||||
function getNodeLabel(n) {
|
||||
var div = $('<div>',{class:"red-ui-node-list-item"});
|
||||
var icon = RED.utils.createNodeIcon(n).appendTo(div);
|
||||
var label = n.name;
|
||||
function getNodePaletteLabel(n) {
|
||||
let label = n.name;
|
||||
if (!label && n._def && n._def.paletteLabel) {
|
||||
try {
|
||||
label = (typeof n._def.paletteLabel === "function" ? n._def.paletteLabel.call(n._def) : n._def.paletteLabel)||"";
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
label = label || n.type;
|
||||
$('<div>',{class:"red-ui-node-label"}).text(n.name||n.type).appendTo(icon);
|
||||
return label || n.type;
|
||||
}
|
||||
|
||||
function getNodeLabel(n) {
|
||||
const div = $('<div>',{class:"red-ui-node-list-item"});
|
||||
const icon = RED.utils.createNodeIcon(n).appendTo(div);
|
||||
$('<div>',{class:"red-ui-node-label"}).text(getNodePaletteLabel(n)).appendTo(icon);
|
||||
return div;
|
||||
}
|
||||
|
||||
|
||||
@@ -256,6 +256,10 @@ RED.tourGuide = (function() {
|
||||
}
|
||||
$('<div>').css("text-align","left").html(getLocaleText(step.description)).appendTo(stepDescription);
|
||||
|
||||
if (step.image) {
|
||||
$(`<img src="red/tours/${step.image}" />`).appendTo(stepDescription)
|
||||
}
|
||||
|
||||
var stepToolbar = $('<div>',{class:"red-ui-tourGuide-toolbar"}).appendTo(stepContent);
|
||||
|
||||
// var breadcrumbs = $('<div>',{class:"red-ui-tourGuide-breadcrumbs"}).appendTo(stepToolbar);
|
||||
|
||||
@@ -121,6 +121,13 @@ RED.userSettings = (function() {
|
||||
// {setting:"theme", label:"Theme",options:function(done){ done([{val:'',text:'default'}].concat(RED.settings.theme("themes"))) }},
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
title: "menu.label.view.view",
|
||||
options: [
|
||||
{setting:"view-store-zoom",label:"menu.label.view.storeZoom", default: false, toggle:true, onchange: function(val) { if (!val) { RED.settings.removeLocal("zoom-level")}}},
|
||||
{setting:"view-store-position",label:"menu.label.view.storePosition", default: false, toggle:true, onchange: function(val) { if (!val) { RED.settings.removeLocal("scroll-positions")}}},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "menu.label.view.grid",
|
||||
options: [
|
||||
|
||||
@@ -725,6 +725,90 @@ RED.view.tools = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function wireSeriesOfNodes() {
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length > 1) {
|
||||
var i = 0;
|
||||
var newLinks = [];
|
||||
while (i < selection.nodes.length - 1) {
|
||||
var nodeA = selection.nodes[i];
|
||||
var nodeB = selection.nodes[i+1];
|
||||
if (nodeA.outputs > 0 && nodeB.inputs > 0) {
|
||||
var existingLinks = RED.nodes.filterLinks({
|
||||
source: nodeA,
|
||||
target: nodeB,
|
||||
sourcePort: 0
|
||||
})
|
||||
if (existingLinks.length === 0) {
|
||||
var newLink = {
|
||||
source: nodeA,
|
||||
target: nodeB,
|
||||
sourcePort: 0
|
||||
}
|
||||
RED.nodes.addLink(newLink);
|
||||
newLinks.push(newLink);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (newLinks.length > 0) {
|
||||
RED.history.push({
|
||||
t: 'add',
|
||||
links: newLinks,
|
||||
dirty: RED.nodes.dirty()
|
||||
})
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function wireNodeToMultiple() {
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length > 1) {
|
||||
var sourceNode = selection.nodes[0];
|
||||
if (sourceNode.outputs === 0) {
|
||||
return;
|
||||
}
|
||||
var i = 1;
|
||||
var newLinks = [];
|
||||
while (i < selection.nodes.length) {
|
||||
var targetNode = selection.nodes[i];
|
||||
if (targetNode.inputs > 0) {
|
||||
var existingLinks = RED.nodes.filterLinks({
|
||||
source: sourceNode,
|
||||
target: targetNode,
|
||||
sourcePort: Math.min(sourceNode.outputs-1,i-1)
|
||||
})
|
||||
if (existingLinks.length === 0) {
|
||||
var newLink = {
|
||||
source: sourceNode,
|
||||
target: targetNode,
|
||||
sourcePort: Math.min(sourceNode.outputs-1,i-1)
|
||||
}
|
||||
RED.nodes.addLink(newLink);
|
||||
newLinks.push(newLink);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (newLinks.length > 0) {
|
||||
RED.history.push({
|
||||
t: 'add',
|
||||
links: newLinks,
|
||||
dirty: RED.nodes.dirty()
|
||||
})
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
|
||||
@@ -783,7 +867,8 @@ RED.view.tools = (function() {
|
||||
RED.actions.add("core:distribute-selection-horizontally", function() { distributeSelection('h') })
|
||||
RED.actions.add("core:distribute-selection-vertically", function() { distributeSelection('v') })
|
||||
|
||||
|
||||
RED.actions.add("core:wire-series-of-nodes", function() { wireSeriesOfNodes() })
|
||||
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
|
||||
|
||||
// RED.actions.add("core:add-node", function() { addNode() })
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,13 @@
|
||||
stroke-dasharray: 10 5;
|
||||
}
|
||||
|
||||
.nr-ui-view-slice {
|
||||
stroke-width: 1px;
|
||||
stroke: $view-lasso-stroke;
|
||||
fill: none;
|
||||
stroke-dasharray: 10 5;
|
||||
}
|
||||
|
||||
.node_label_italic, // deprecated: use red-ui-flow-node-label-italic
|
||||
.red-ui-flow-node-label-italic {
|
||||
font-style: italic;
|
||||
|
||||
@@ -204,6 +204,28 @@
|
||||
font-style: italic;
|
||||
color: $form-placeholder-color;
|
||||
}
|
||||
.red-ui-search-history {
|
||||
button {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
&:hover button {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
.red-ui-search-historyHeader {
|
||||
button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 7px;
|
||||
}
|
||||
}
|
||||
.red-ui-search-history-result {
|
||||
|
||||
}
|
||||
|
||||
.red-ui-search-result-action {
|
||||
color: $primary-text-color;
|
||||
|
||||
@@ -78,6 +78,12 @@
|
||||
}
|
||||
.red-ui-tourGuide-popover-description {
|
||||
padding: 10px 20px 5px;
|
||||
|
||||
img {
|
||||
max-height: 150px;
|
||||
border: 1px solid var(--red-ui-tourGuide-border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
.red-ui-tourGuide-popover-full {
|
||||
.red-ui-tourGuide-popover-description {
|
||||
|
||||
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/delete-repair.gif
vendored
Normal file
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/delete-repair.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/detach-repair.gif
vendored
Normal file
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/detach-repair.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/slice.gif
vendored
Normal file
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/slice.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/subflow-labels.png
vendored
Normal file
BIN
packages/node_modules/@node-red/editor-client/src/tours/images/subflow-labels.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
@@ -1,12 +1,12 @@
|
||||
export default {
|
||||
version: "2.1.0",
|
||||
version: "2.2.0",
|
||||
steps: [
|
||||
{
|
||||
titleIcon: "fa fa-map-o",
|
||||
title: {
|
||||
"en-US": "Welcome to Node-RED 2.1!",
|
||||
"ja": "Node-RED 2.1へようこそ!"
|
||||
},
|
||||
"en-US": "Welcome to Node-RED 2.2!",
|
||||
"ja": "Node-RED 2.2へようこそ!"
|
||||
},
|
||||
description: {
|
||||
"en-US": "Let's take a moment to discover the new features in this release.",
|
||||
"ja": "本リリースの新機能を見つけてみましょう。"
|
||||
@@ -14,215 +14,142 @@ export default {
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "A new Tour Guide",
|
||||
"ja": "新しいツアーガイド"
|
||||
"en-US": "Search history",
|
||||
"ja": "検索履歴"
|
||||
},
|
||||
description: {
|
||||
"en-US": "<p>First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.</p>" +
|
||||
"<p>You can choose not to see this tour in the future by disabling it under the View tab of User Settings.</p>",
|
||||
"ja": "<p>最初に、既に見つけている様に、新機能の本ツアーがあります。本ツアーは、新バージョンのNode-REDフローエディタを初めて開いた時のみ表示されます。</p>" +
|
||||
"<p>ユーザ設定の表示タブの中で、この機能を無効化することで、本ツアーを表示しないようにすることもできます。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "New Edit menu",
|
||||
"ja": "新しい編集メニュー"
|
||||
"en-US": "<p>The Search dialog now keeps a history of your searches, making it easier to go back to a previous search.</p>",
|
||||
"ja": "<p>検索ダイアログが検索履歴を保持するようになりました。これによって、過去の検索に戻りやすくなりました。</p>"
|
||||
},
|
||||
prepare() {
|
||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||
$("#menu-item-edit-menu").parent().addClass("open");
|
||||
},
|
||||
complete() {
|
||||
$("#menu-item-edit-menu").parent().removeClass("open");
|
||||
},
|
||||
element: "#menu-item-edit-menu-submenu",
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
description: {
|
||||
"en-US": "<p>The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.</p>" +
|
||||
"<p>The menu now displays keyboard shortcuts for the options.</p>",
|
||||
"ja": "<p>メインメニューに「編集」セクションが追加されました。本セクションには、切り取り/貼り付けや、変更操作を戻す/やり直しの様な使い慣れたオプションが含まれています。</p>" +
|
||||
"<p>本メニューには、オプションのためのキーボードショートカットも表示されるようになりました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Arranging nodes",
|
||||
"ja": "ノードの配置"
|
||||
},
|
||||
prepare() {
|
||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||
$("#menu-item-arrange-menu").parent().addClass("open");
|
||||
},
|
||||
complete() {
|
||||
$("#menu-item-arrange-menu").parent().removeClass("open");
|
||||
},
|
||||
element: "#menu-item-arrange-menu-submenu",
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
description: {
|
||||
"en-US": "<p>The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.</p>",
|
||||
"ja": "<p>メニューの新しい「配置」セクションには、ノードの配置を助ける新しいオプションが提供されています。ノードの端を揃えたり、均等に配置したり、表示順序を変更したりできます。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Hiding tabs",
|
||||
"ja": "タブの非表示"
|
||||
},
|
||||
element: "#red-ui-workspace-tabs > li.active",
|
||||
description: {
|
||||
"en-US": '<p>Tabs can now be hidden by clicking their <i class="fa fa-eye-slash"></i> icon.</p><p>The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.',
|
||||
"ja": '<p><i class="fa fa-eye-slash"></i> アイコンをクリックすることで、タブを非表示にできます。</p><p>情報サイドバーには、全てのタブが一覧表示されており、現在非表示になっているタブを確認できます。'
|
||||
},
|
||||
interactive: false,
|
||||
prepare() {
|
||||
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","block");
|
||||
},
|
||||
complete() {
|
||||
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","");
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Tab menu",
|
||||
"ja": "タブメニュー"
|
||||
},
|
||||
element: "#red-ui-workspace-tabs-menu",
|
||||
description: {
|
||||
"en-US": "<p>The new tab menu also provides lots of new options for your tabs.</p>",
|
||||
"ja": "<p>新しいタブメニューには、タブに関する沢山の新しいオプションが提供されています。</p>"
|
||||
},
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
prepare() {
|
||||
$("#red-ui-workspace > .red-ui-tabs > .red-ui-tabs-menu a").trigger("click");
|
||||
},
|
||||
complete() {
|
||||
$(document).trigger("click");
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Flow and Group level environment variables",
|
||||
"ja": "フローとグループの環境変数"
|
||||
},
|
||||
element: "#red-ui-workspace-tabs > li.active",
|
||||
interactive: false,
|
||||
description: {
|
||||
"en-US": "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>",
|
||||
"ja": "<p>フローとグループには、内部のノードから参照できる環境変数を設定できるようになりました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: "#red-ui-search .red-ui-searchBox-form",
|
||||
prepare(done) {
|
||||
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
|
||||
setTimeout(done,700);
|
||||
RED.search.show();
|
||||
setTimeout(done,400);
|
||||
},
|
||||
complete() {
|
||||
RED.search.hide();
|
||||
},
|
||||
element: "#red-ui-tab-editor-tab-envProperties-link-button",
|
||||
description: {
|
||||
"en-US": "<p>Their edit dialogs have a new Environment Variables section.</p>",
|
||||
"ja": "<p>編集ダイアログに環境変数セクションが追加されました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: ".node-input-env-container-row",
|
||||
direction: "left",
|
||||
title: {
|
||||
"en-US": "Remembering Zoom & Position",
|
||||
"ja": "拡大/縮小のレベルや位置を記憶"
|
||||
},
|
||||
description: {
|
||||
"en-US": '<p>The environment variables are listed in this table and new ones can be added by clicking the <i class="fa fa-plus"></i> button.</p>',
|
||||
"ja": '<p>この表に環境変数が一覧表示されており、<i class="fa fa-plus"></i>ボタンをクリックすることで新しい変数を追加できます。</p>'
|
||||
"en-US": "<p>The editor has new options to restore the zoom level and scroll position when reloading the editor.</p>",
|
||||
"ja": "<p>エディタを再読み込みした時に、拡大/縮小のレベルやスクロール位置を復元するための新しいオプションを利用できます。</p>"
|
||||
},
|
||||
element: function() { return $("#user-settings-view-store-position").parent()},
|
||||
prepare(done) {
|
||||
RED.actions.invoke("core:show-user-settings")
|
||||
setTimeout(done,400);
|
||||
},
|
||||
complete(done) {
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
setTimeout(done,500);
|
||||
$("#node-dialog-ok").trigger("click");
|
||||
setTimeout(done,400);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "New wiring actions",
|
||||
"ja": "新しいワイヤー操作"
|
||||
},
|
||||
// image: "images/",
|
||||
description: {
|
||||
"en-US": `<p>A pair of new actions have been added to help with wiring nodes together:</p>
|
||||
<ul>
|
||||
<li><b><code>Wire Series Of Nodes</code></b> - adds a wire (if necessary) between each pair of nodes in the order they were selected.</li>
|
||||
<li><b><code>Wire Node To Multiple</code></b> - wires the first node selected to all of the other selected nodes.</li>
|
||||
</ul>
|
||||
<p>Actions can be accessed from the Action List in the main menu.</p>`,
|
||||
"ja": `<p>ノード接続を支援する2つの新しい操作が追加されました:</p>
|
||||
<ul>
|
||||
<li><b><code>Wire Series Of Nodes</code></b> - ノードを選択した順序で、各ノードのペアの間にワイヤーを(必要に応じて)追加します。</li>
|
||||
<li><b><code>Wire Node To Multiple</code></b> - 最初に選択したノードから、他の選択した全てのノードに対して、ワイヤーを追加します。</li>
|
||||
</ul>
|
||||
<p>メインメニュー内の動作一覧から、これらの操作を利用できます。</p>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Deleting nodes and reconnecting wires",
|
||||
"ja": "ノードの削除とワイヤーの再接続"
|
||||
},
|
||||
image: "images/delete-repair.gif",
|
||||
description: {
|
||||
"en-US": `<p>It is now possible to delete a selection of nodes and automatically repair the wiring behind them.</p>
|
||||
<p>This is really useful if you want to remove a node from the middle of the flow.</p>
|
||||
<p>Hold the Ctrl (or Cmd) key when you press Delete and the nodes will be gone and the wires repaired.</p>
|
||||
`,
|
||||
"ja": `<p>選択したノードを削除した後、その背後にあるワイヤーを自動的に修復できるようになりました。</p>
|
||||
<p>これは、フローの中からノードを削除する時に、とても便利に使えます。</p>
|
||||
<p>Ctrl (またはCmd)キーを押しながらDeleteキーを押すと、ノードがなくなり、ワイヤーが修復されます。</p>
|
||||
`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Link Call node added",
|
||||
"ja": "Link Callノードを追加"
|
||||
"en-US": "Detaching nodes from a flow",
|
||||
"ja": "フローからノードの切り離し"
|
||||
},
|
||||
prepare(done) {
|
||||
this.paletteWasClosed = $("#red-ui-main-container").hasClass("red-ui-palette-closed");
|
||||
RED.actions.invoke("core:toggle-palette",true)
|
||||
$('[data-palette-type="link call"]')[0].scrollIntoView({block:"center"})
|
||||
setTimeout(done,100);
|
||||
},
|
||||
element: '[data-palette-type="link call"]',
|
||||
direction: "right",
|
||||
image: "images/detach-repair.gif",
|
||||
description: {
|
||||
"en-US": "<p>The <code>Link Call</code> node lets you call another flow that begins with a <code>Link In</code> node and get the result back when the message reaches a <code>Link Out</code> node.</p>",
|
||||
"ja": "<p><code>Link Call</code>ノードを用いることで、<code>Link In</code>ノードから始まるフローを呼び出し、<code>Link Out</code>ノードに到達した時に、結果を取得できます。</p>"
|
||||
"en-US": `<p>If you want to remove a node from a flow without deleting it,
|
||||
you can use the <b><code>Detach Selected Nodes</code></b> action.</p>
|
||||
<p>The nodes will be removed from their flow, the wiring repaired behind them, and then attached to the mouse
|
||||
so you can drop them wherever you want in the workspace.</p>
|
||||
<p>There isn't a default keyboard shortcut assigned for this new action, but
|
||||
you can add your own via the Keyboard pane of the main Settings dialog.</p>`,
|
||||
"ja": `<p>ノードを削除することなく、フローからノードを除きたい場合は、<b><code>Detach Selected Nodes</code></b>操作を利用できます。</p>
|
||||
<p>フローからノードが除かれた後、背後のワイヤーが修復され、ノードはマウスポインタにつながります。そのため、ワークスペースの好きな所にノードを配置できます。</p>
|
||||
<p>この新しい操作に対して、デフォルトのキーボードショートカットは登録されていませんが、メイン設定ダイアログのキーボード設定から追加できます。</p>`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "MQTT nodes support dynamic connections",
|
||||
"ja": "MQTTノードが動的接続をサポート"
|
||||
"en-US": "More wiring tricks",
|
||||
"ja": "その他のワイヤー操作"
|
||||
},
|
||||
prepare(done) {
|
||||
$('[data-palette-type="mqtt out"]')[0].scrollIntoView({block:"center"})
|
||||
setTimeout(done,100);
|
||||
},
|
||||
element: '[data-palette-type="mqtt out"]',
|
||||
direction: "right",
|
||||
image: "images/slice.gif",
|
||||
description: {
|
||||
"en-US": '<p>The <code>MQTT</code> nodes now support creating their connections and subscriptions dynamically.</p>',
|
||||
"ja": '<p><code>MQTT</code>ノードは、動的な接続や購読ができるようになりました。</p>'
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "File nodes renamed",
|
||||
"ja": "ファイルノードの名前変更"
|
||||
},
|
||||
prepare(done) {
|
||||
$('[data-palette-type="file"]')[0].scrollIntoView({block:"center"});
|
||||
setTimeout(done,100);
|
||||
},
|
||||
complete() {
|
||||
if (this.paletteWasClosed) {
|
||||
RED.actions.invoke("core:toggle-palette",false)
|
||||
}
|
||||
},
|
||||
element: '[data-palette-type="file"]',
|
||||
direction: "right",
|
||||
description: {
|
||||
"en-US": "<p>The file nodes have been renamed to make it clearer which node does what.</p>",
|
||||
"ja": "<p>fileノードの名前が変更され、どのノードが何を行うかが明確になりました。</p>"
|
||||
"en-US": `<p>A couple more wiring tricks to share.</p>
|
||||
<p>You can now select multiple wires by holding the Ctrl (or Cmd) key
|
||||
when clicking on a wire. This makes it easier to delete multiple wires in one go.</p>
|
||||
<p>If you hold the Ctrl (or Cmd) key, then click and drag with the right-hand mouse button,
|
||||
you can slice through wires to remove them.</p>`,
|
||||
"ja": `<p>その他のいくつかのワイヤー操作</p>
|
||||
<p>Ctrl (またはCmd)キーを押しながらワイヤーをクリックすることで、複数のワイヤーを選択できるようになりました。これによって、複数のワイヤーを一度に削除することが簡単になりました。</p>
|
||||
<p>Ctrl (またはCmd)キーを押しながら、マウスの右ボタンを用いてドラッグすると、ワイヤーを切って削除できます。</p>`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Deep copy option on Change node",
|
||||
"ja": "Changeノードのディープコピーオプション"
|
||||
},
|
||||
prepare(done) {
|
||||
var def = RED.nodes.getType('change');
|
||||
RED.editor.edit({id:"test",type:"change",rules:[{t:"set",p:"payload",pt:"msg", tot:"msg",to:"anotherProperty"}],_def:def, _:def._});
|
||||
setTimeout(done,700);
|
||||
},
|
||||
complete(done) {
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
setTimeout(done,500);
|
||||
},
|
||||
element: function() {
|
||||
return $(".node-input-rule-property-deepCopy").next();
|
||||
"en-US": "Subflow Output Labels",
|
||||
"ja": "サブフローの出力ラベル"
|
||||
},
|
||||
image: "images/subflow-labels.png",
|
||||
description: {
|
||||
"en-US": "<p>The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.</p>",
|
||||
"ja": "<p>値を代入に、値のディープコピーを作成するオプションが追加されました。これによって参照ではなく、完全なコピーが作成されます。</p>"
|
||||
}
|
||||
"en-US": "<p>If a subflow has labels set for its outputs, they now get shown on the ports within the subflow template view.</p>",
|
||||
"ja": "<p>サブフローの出力にラベルが設定されている場合、サブフローテンプレート画面内のポートにラベルが表示されるようになりました。</p>"
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "And that's not all...",
|
||||
"ja": "これが全てではありません..."
|
||||
"en-US": "Node Updates",
|
||||
"ja": "ノードの更新"
|
||||
},
|
||||
// image: "images/",
|
||||
description: {
|
||||
"en-US": "<p>There are many more smaller changes, including:</p><ul><li>Auto-complete suggestions in the <code>msg</code> TypedInput.</li><li>Support for <code>msg.resetTimeout</code> in the <code>Join</code> node.</li><li>Pushing messages to the front of the queue in the <code>Delay</code> node's rate limiting mode.</li><li>An optional second output on the <code>Delay</code> node for rate limited messages.</li></ul>",
|
||||
"ja": "<p>以下の様な小さな変更が沢山あります:</p><ul><li><code>msg</code> TypedInputの自動補完提案</li><li><code>Join</code>ノードで<code>msg.resetTimeout</code>のサポート</li><li><code>Delay</code>ノードの流量制御モードにおいて先頭メッセージをキューに追加</li><li><code>Delay</code>ノードで流量制限されたメッセージ向けの任意の2つ目の出力</li></ul>"
|
||||
"en-US": `<ul>
|
||||
<li>The JSON node will now handle parsing Buffer payloads</li>
|
||||
<li>The TCP Client nodes support TLS connections</li>
|
||||
<li>The WebSocket node allows you to specify a sub-protocol when connecting</li>
|
||||
</ul>`,
|
||||
"ja": `<ul>
|
||||
<li>JSONノードが、バッファ形式のペイロードを解析できるようになりました。</li>
|
||||
<li>TCPクライアントノードが、TLS接続をサポートしました。</li>
|
||||
<li>WebSocketノードで、接続時にサブプロトコルを指定できるようになりました。</li>
|
||||
</ul>`
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -31,12 +31,12 @@ interface NodeStatus {
|
||||
}
|
||||
|
||||
declare class node {
|
||||
/**
|
||||
* Send 1 or more messages asynchronously
|
||||
* @param {object | object[]} msg The msg object
|
||||
* @param {Boolean} [clone=true] Flag to indicate the `msg` should be cloned. Default = `true`
|
||||
* @see node-red documentation [writing-functions: sending messages asynchronously](https://nodered.org/docs/user-guide/writing-functions#sending-messages-asynchronously)
|
||||
*/
|
||||
/**
|
||||
* Send 1 or more messages asynchronously
|
||||
* @param {object | object[]} msg The msg object
|
||||
* @param {Boolean} [clone=true] Flag to indicate the `msg` should be cloned. Default = `true`
|
||||
* @see node-red documentation [writing-functions: sending messages asynchronously](https://nodered.org/docs/user-guide/writing-functions#sending-messages-asynchronously)
|
||||
*/
|
||||
static send(msg:object|object[], clone?:Boolean): void;
|
||||
/** Inform runtime this instance has completed its operation */
|
||||
static done();
|
||||
@@ -57,11 +57,13 @@ declare class node {
|
||||
*/
|
||||
static status(status:string|boolean|number);
|
||||
/** the id of this node */
|
||||
public readonly id:string;
|
||||
public static readonly id:string;
|
||||
/** the name of this node */
|
||||
public readonly name:string;
|
||||
public static readonly name:string;
|
||||
/** the path identifier for this node */
|
||||
public static readonly path:string;
|
||||
/** the number of outputs of this node */
|
||||
public readonly outputCount:number;
|
||||
public static readonly outputCount:number;
|
||||
}
|
||||
declare class context {
|
||||
/**
|
||||
@@ -93,27 +95,27 @@ declare class context {
|
||||
/**
|
||||
* Set one or multiple values in context (synchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[]);
|
||||
/**
|
||||
* Set one or multiple values in context (asynchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param callback - (optional) Callback function (`(err) => {}`)
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], callback?: Function);
|
||||
/**
|
||||
* Set one or multiple values in context (synchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param store - (optional) Name of context store
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], store?: string);
|
||||
/**
|
||||
* Set one or multiple values in context (asynchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param store - (optional) Name of context store
|
||||
* @param callback - (optional) Callback function (`(err) => {}`)
|
||||
*/
|
||||
@@ -158,27 +160,27 @@ declare class flow {
|
||||
/**
|
||||
* Set one or multiple values in context (synchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[]);
|
||||
/**
|
||||
* Set one or multiple values in context (asynchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param callback - (optional) Callback function (`(err) => {}`)
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], callback?: Function);
|
||||
/**
|
||||
* Set one or multiple values in context (synchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param store - (optional) Name of context store
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], store?: string);
|
||||
/**
|
||||
* Set one or multiple values in context (asynchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param store - (optional) Name of context store
|
||||
* @param callback - (optional) Callback function (`(err) => {}`)
|
||||
*/
|
||||
@@ -225,32 +227,32 @@ declare class global {
|
||||
/**
|
||||
* Set one or multiple values in context (synchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[]);
|
||||
/**
|
||||
* Set one or multiple values in context (asynchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param callback - (optional) Callback function (`(err) => {}`)
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], callback?: Function);
|
||||
/**
|
||||
* Set one or multiple values in context (synchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param store - (optional) Name of context store
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], store?: string);
|
||||
/**
|
||||
* Set one or multiple values in context (asynchronous).
|
||||
* @param name - Name (or array of names) to set in context
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param value - The value (or array of values) to store in context. If the value(s) are null/undefined, the context item(s) will be removed.
|
||||
* @param store - (optional) Name of context store
|
||||
* @param callback - (optional) Callback function (`(err) => {}`)
|
||||
*/
|
||||
static set(name: string | string[], value?: any | any[], store?: string, callback?: Function);
|
||||
|
||||
|
||||
/** Get an array of the keys in the context store */
|
||||
static keys(): Array<string>;
|
||||
/** Get an array of the keys in the context store */
|
||||
|
||||
Reference in New Issue
Block a user