node-red/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js

650 lines
26 KiB
JavaScript
Raw Normal View History

/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.workspaces = (function() {
2015-07-01 00:42:03 +02:00
var activeWorkspace = 0;
var workspaceIndex = 0;
var viewStack = [];
var viewStackPos = 0;
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
function addToViewStack(id) {
if (viewStackPos !== viewStack.length) {
viewStack.splice(viewStackPos);
}
viewStack.push(id);
viewStackPos = viewStack.length;
// console.warn("addToViewStack",id,viewStack);
}
function addWorkspace(ws,skipHistoryEntry,targetIndex) {
if (ws) {
workspace_tabs.addTab(ws,targetIndex);
workspace_tabs.resize();
} else {
var tabId = RED.nodes.id();
do {
workspaceIndex += 1;
2019-05-01 23:41:20 +02:00
} while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
2015-07-01 00:42:03 +02:00
ws = {type:"tab",id:tabId,disabled: false,info:"",label:RED._('workspace.defaultName',{number:workspaceIndex}),env:[]};
RED.nodes.addWorkspace(ws,targetIndex);
workspace_tabs.addTab(ws,targetIndex);
workspace_tabs.activateTab(tabId);
2016-09-23 23:02:12 +02:00
if (!skipHistoryEntry) {
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
}
}
RED.view.focus();
2016-09-23 23:02:12 +02:00
return ws;
}
2016-06-01 00:20:25 +02:00
function deleteWorkspace(ws) {
if (workspaceTabCount === 1) {
return;
}
var workspaceOrder = RED.nodes.getWorkspaceOrder();
ws._index = workspaceOrder.indexOf(ws.id);
2016-06-01 00:20:25 +02:00
removeWorkspace(ws);
var historyEvent = RED.nodes.removeWorkspace(ws.id);
historyEvent.t = 'delete';
historyEvent.dirty = RED.nodes.dirty();
historyEvent.workspaces = [ws];
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
2015-07-01 00:42:03 +02:00
}
var tabflowEditor;
function buildProperties(container, workspace) {
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(container);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
'<div style="min-height:250px;" class="node-text-editor" id="node-input-info"></div>'+
'</div>').appendTo(dialogForm);
tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
value: ""
});
$('#node-info-input-info-expand').on("click", function(e) {
e.preventDefault();
var value = tabflowEditor.getValue();
RED.editor.editMarkdown({
value: value,
width: "Infinity",
cursor: tabflowEditor.getCursorPosition(),
complete: function(v,cursor) {
tabflowEditor.setValue(v, -1);
tabflowEditor.gotoLine(cursor.row+1,cursor.column,false);
setTimeout(function() {
tabflowEditor.focus();
},300);
}
})
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
$("#node-input-name").val(workspace.label);
RED.text.bidi.prepareInput($("#node-input-name"));
tabflowEditor.getSession().setValue(workspace.info || "", -1);
dialogForm.i18n();
}
2021-08-30 01:00:58 +02:00
function getNodeCredentials(type, id, done) {
var timeoutNotification;
var intialTimeout = setTimeout(function() {
timeoutNotification = RED.notify($('<p data-i18n="[prepend]editor.loadCredentials"> <img src="red/images/spin.svg"/></p>').i18n(),{fixed: true})
},800);
$.ajax({
url: "credentials/tab/" + id,
dataType: 'json',
success: function(data) {
if (timeoutNotification) {
timeoutNotification.close();
timeoutNotification = null;
}
clearTimeout(intialTimeout);
done(data);
},
error: function(jqXHR,status,error) {
if (timeoutNotification) {
timeoutNotification.close();
timeoutNotification = null;
}
clearTimeout(intialTimeout);
RED.notify(RED._("editor.errors.credentialLoadFailed"),"error")
done(null);
},
timeout: 30000,
});
}
2018-10-08 17:25:11 +02:00
function showEditWorkspaceDialog(id) {
2016-06-01 00:20:25 +02:00
var workspace = RED.nodes.workspace(id);
2019-06-07 16:14:21 +02:00
if (!workspace) {
var subflow = RED.nodes.subflow(id);
if (subflow) {
RED.editor.editSubflow(subflow);
}
return;
}
2016-06-01 00:20:25 +02:00
RED.view.state(RED.state.EDITING);
var trayOptions = {
2019-09-06 11:25:30 +02:00
title: RED._("workspace.editFlow",{name:RED.utils.sanitize(workspace.label)}),
2016-06-01 00:20:25 +02:00
buttons: [
{
id: "node-dialog-delete",
class: 'leftButton'+((workspaceTabCount === 1)?" disabled":""),
2016-06-01 00:20:25 +02:00
text: RED._("common.label.delete"), //'<i class="fa fa-trash"></i>',
click: function() {
deleteWorkspace(workspace);
RED.tray.close();
}
},
{
id: "node-dialog-cancel",
text: RED._("common.label.cancel"),
click: function() {
RED.tray.close();
}
},
{
id: "node-dialog-ok",
class: "primary",
text: RED._("common.label.done"),
click: function() {
var label = $( "#node-input-name" ).val();
var changed = false;
var changes = {};
2016-06-01 00:20:25 +02:00
if (workspace.label != label) {
changes.label = workspace.label;
changed = true;
workspace.label = label;
workspace_tabs.renameTab(workspace.id,label);
}
var disabled = $("#node-input-disabled").prop("checked");
if (workspace.disabled !== disabled) {
changes.disabled = workspace.disabled;
changed = true;
workspace.disabled = disabled;
}
var info = tabflowEditor.getValue();
if (workspace.info !== info) {
changes.info = workspace.info;
changed = true;
workspace.info = info;
}
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
var old_env = workspace.env;
var new_env = RED.subflow.exportSubflowInstanceEnv(workspace);
if (new_env && (new_env.length > 0)) {
new_env.forEach(function(prop) {
if (prop.type === "cred") {
workspace.credentials = workspace.credentials || {_:{}};
workspace.credentials[prop.name] = prop.value;
workspace.credentials['has_'+prop.name] = (prop.value !== "");
if (prop.value !== '__PWRD__') {
changed = true;
}
delete prop.value;
}
});
}
if (!isSameObj(old_env, new_env)) {
workspace.env = new_env;
changes.env = old_env;
changed = true;
}
if (changed) {
2016-06-01 00:20:25 +02:00
var historyEvent = {
t: "edit",
changes:changes,
node: workspace,
dirty: RED.nodes.dirty()
}
workspace.changed = true;
2016-06-01 00:20:25 +02:00
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
if (changes.hasOwnProperty('disabled')) {
RED.nodes.eachNode(function(n) {
if (n.z === workspace.id) {
n.dirty = true;
}
});
RED.view.redraw();
}
RED.events.emit("flows:change",workspace);
2016-06-01 00:20:25 +02:00
}
RED.tray.close();
}
}
],
resize: function(dimensions) {
var height = dimensions.height;
2017-04-16 21:25:15 +02:00
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
for (var i=0; i<rows.size(); i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorHeight = height -(parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom"))) -100;
$(".node-text-editor").css("height", editorHeight+"px");
tabflowEditor.resize();
$("#red-ui-editor-tab-env-list").editableList("height", height -70);
},
2016-06-01 00:20:25 +02:00
open: function(tray) {
var trayFooter = tray.find(".red-ui-tray-footer");
2019-05-01 23:41:20 +02:00
var trayBody = tray.find('.red-ui-tray-body');
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
var editorTabEl = $('<ul></ul>').appendTo(trayBody);
var editorContent = $('<div></div>').appendTo(trayBody);
var finishedBuilding = false;
var editorTabs = RED.tabs.create({
element:editorTabEl,
onchange:function(tab) {
editorContent.children().hide();
if (tab.onchange) {
tab.onchange.call(tab);
}
tab.content.show();
if (finishedBuilding) {
RED.tray.resize();
}
},
collapsible: true,
menu: false
});
var nodePropertiesTab = {
id: "editor-tab-properties",
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
content: $('<div>', {class:"red-ui-tray-content"}).appendTo(editorContent).hide(),
iconClass: "fa fa-cog"
};
buildProperties(nodePropertiesTab.content, workspace);
editorTabs.addTab(nodePropertiesTab);
var tabPropertiesTab = {
id: "editor-tab-envProperties",
label: RED._("editor-tab.envProperties"),
name: RED._("editor-tab.envProperties"),
content: $('<div>', {
id: "editor-tab-envProperties-content",
class: "red-ui-tray-content"
}).appendTo(editorContent).hide(),
iconClass: "fa fa-list",
};
2021-08-30 01:00:58 +02:00
function cb() {
RED.subflow.buildPropertiesForm(workspace);
editorTabs.addTab(tabPropertiesTab);
if (!workspace.hasOwnProperty("disabled")) {
workspace.disabled = false;
}
$('<input id="node-input-disabled" type="checkbox">').prop("checked",workspace.disabled).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
finishedBuilding = true;
RED.tray.resize();
}
if (workspace.credentials) {
cb();
}
else {
getNodeCredentials("tab", workspace.id, function(data) {
if (data) {
workspace.credentials = data;
workspace.credentials._ = $.extend(true,{},data);
}
cb();
});
}
2016-06-01 00:20:25 +02:00
},
close: function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
RED.view.state(RED.state.DEFAULT);
}
var selection = RED.view.selection();
if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
2020-05-19 02:27:50 +02:00
RED.sidebar.info.refresh(workspace);
}
tabflowEditor.destroy();
2016-06-01 00:20:25 +02:00
}
}
2016-06-01 00:20:25 +02:00
RED.tray.show(trayOptions);
}
2015-07-01 00:42:03 +02:00
2016-06-01 00:20:25 +02:00
var workspace_tabs;
var workspaceTabCount = 0;
2017-04-16 21:25:15 +02:00
function createWorkspaceTabs() {
workspace_tabs = RED.tabs.create({
2019-05-01 23:41:20 +02:00
id: "red-ui-workspace-tabs",
onchange: function(tab) {
var event = {
old: activeWorkspace
}
activeWorkspace = tab.id;
event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event);
window.location.hash = 'flow/'+tab.id;
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled);
2015-10-16 22:56:20 +02:00
RED.sidebar.config.refresh();
RED.view.focus();
},
onclick: function(tab) {
if (tab.id !== activeWorkspace) {
addToViewStack(activeWorkspace);
}
RED.view.focus();
},
ondblclick: function(tab) {
if (tab.type != "subflow") {
2018-10-08 17:25:11 +02:00
showEditWorkspaceDialog(tab.id);
} else {
RED.editor.editSubflow(RED.nodes.subflow(tab.id));
}
},
onadd: function(tab) {
2018-02-23 03:48:40 +01:00
if (tab.type === "tab") {
workspaceTabCount++;
}
$('<span class="red-ui-workspace-disabled-icon"><i class="fa fa-ban"></i> </span>').prependTo("#red-ui-tab-"+(tab.id.replace(".","-"))+" .red-ui-tab-label");
if (tab.disabled) {
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-disabled');
}
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
if (workspaceTabCount === 1) {
2017-09-20 11:30:07 +02:00
showWorkspace();
}
},
onremove: function(tab) {
2018-02-23 03:48:40 +01:00
if (tab.type === "tab") {
workspaceTabCount--;
}
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
if (workspaceTabCount === 0) {
2017-09-20 11:30:07 +02:00
hideWorkspace();
}
2015-07-03 19:31:37 +02:00
},
2016-05-04 16:22:30 +02:00
onreorder: function(oldOrder, newOrder) {
RED.history.push({t:'reorder',order:oldOrder,dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
setWorkspaceOrder(newOrder);
},
onselect: function(selectedTabs) {
RED.view.select(false)
if (selectedTabs.length === 0) {
2019-05-01 23:41:20 +02:00
$("#red-ui-workspace-chart svg").css({"pointer-events":"auto",filter:"none"})
$("#red-ui-workspace-toolbar").css({"pointer-events":"auto",filter:"none"})
2019-04-29 23:38:14 +02:00
$("#red-ui-palette-container").css({"pointer-events":"auto",filter:"none"})
2019-04-30 23:56:39 +02:00
$(".red-ui-sidebar-shade").hide();
} else {
RED.view.select(false)
2019-05-01 23:41:20 +02:00
$("#red-ui-workspace-chart svg").css({"pointer-events":"none",filter:"opacity(60%)"})
$("#red-ui-workspace-toolbar").css({"pointer-events":"none",filter:"opacity(60%)"})
2019-04-29 23:38:14 +02:00
$("#red-ui-palette-container").css({"pointer-events":"none",filter:"opacity(60%)"})
2019-04-30 23:56:39 +02:00
$(".red-ui-sidebar-shade").show();
}
},
2016-09-26 23:56:28 +02:00
minimumActiveTabWidth: 150,
scrollable: true,
2018-10-17 14:45:57 +02:00
addButton: "core:add-flow",
2019-03-04 23:37:51 +01:00
addButtonCaption: RED._("workspace.addFlow"),
searchButton: "core:list-flows",
searchButtonCaption: RED._("workspace.listFlows")
});
workspaceTabCount = 0;
}
2017-09-20 11:30:07 +02:00
function showWorkspace() {
2019-05-01 23:41:20 +02:00
$("#red-ui-workspace .red-ui-tabs").show()
$("#red-ui-workspace-chart").show()
$("#red-ui-workspace-footer").children().show()
2017-09-20 11:30:07 +02:00
}
function hideWorkspace() {
2019-05-01 23:41:20 +02:00
$("#red-ui-workspace .red-ui-tabs").hide()
$("#red-ui-workspace-chart").hide()
$("#red-ui-workspace-footer").children().hide()
2017-09-20 11:30:07 +02:00
}
2015-07-01 00:42:03 +02:00
function init() {
2019-05-01 23:41:20 +02:00
$('<ul id="red-ui-workspace-tabs"></ul>').appendTo("#red-ui-workspace");
$('<div id="red-ui-workspace-tabs-shade" class="hide"></div>').appendTo("#red-ui-workspace");
2019-05-01 23:41:20 +02:00
$('<div id="red-ui-workspace-chart" tabindex="1"></div>').appendTo("#red-ui-workspace");
$('<div id="red-ui-workspace-toolbar"></div>').appendTo("#red-ui-workspace");
$('<div id="red-ui-workspace-footer" class="red-ui-component-footer"></div>').appendTo("#red-ui-workspace");
$('<div id="red-ui-editor-shade" class="hide"></div>').appendTo("#red-ui-workspace");
2019-05-01 23:41:20 +02:00
createWorkspaceTabs();
RED.events.on("sidebar:resize",workspace_tabs.resize);
2015-07-01 00:42:03 +02:00
RED.actions.add("core:show-next-tab",function() {
var oldActive = activeWorkspace;
workspace_tabs.nextTab();
if (oldActive !== activeWorkspace) {
addToViewStack(oldActive)
}
});
RED.actions.add("core:show-previous-tab",function() {
var oldActive = activeWorkspace;
workspace_tabs.previousTab();
if (oldActive !== activeWorkspace) {
addToViewStack(oldActive)
}
});
2015-09-27 21:18:21 +02:00
RED.menu.setAction('menu-item-workspace-delete',function() {
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
});
2015-07-14 00:21:03 +02:00
$(window).on("resize", function() {
2015-07-14 00:21:03 +02:00
workspace_tabs.resize();
});
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace);
2019-06-07 16:14:21 +02:00
RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace);
2017-09-20 11:30:07 +02:00
2019-03-04 23:37:51 +01:00
RED.actions.add("core:list-flows",function() {
RED.actions.invoke("core:search","type:tab ");
})
RED.actions.add("core:go-to-previous-location", function() {
if (viewStackPos > 0) {
if (viewStackPos === viewStack.length) {
// We're at the end of the stack. Remember the activeWorkspace
// so we can come back to it.
viewStack.push(activeWorkspace);
}
RED.workspaces.show(viewStack[--viewStackPos],true);
}
})
RED.actions.add("core:go-to-next-location", function() {
if (viewStackPos < viewStack.length - 1) {
RED.workspaces.show(viewStack[++viewStackPos],true);
}
})
2017-09-20 11:30:07 +02:00
hideWorkspace();
}
function editWorkspace(id) {
2018-10-08 17:25:11 +02:00
showEditWorkspaceDialog(id||activeWorkspace);
}
2015-07-01 00:42:03 +02:00
2019-06-07 16:14:21 +02:00
function enableWorkspace(id) {
setWorkspaceState(id,false);
}
function disableWorkspace(id) {
setWorkspaceState(id,true);
}
function setWorkspaceState(id,disabled) {
var workspace = RED.nodes.workspace(id||activeWorkspace);
if (!workspace) {
return;
}
if (workspace.disabled !== disabled) {
var changes = { disabled: workspace.disabled };
workspace.disabled = disabled;
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
if (id === activeWorkspace) {
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
}
2019-06-07 16:14:21 +02:00
var historyEvent = {
t: "edit",
changes:changes,
node: workspace,
dirty: RED.nodes.dirty()
}
workspace.changed = true;
RED.history.push(historyEvent);
RED.events.emit("flows:change",workspace);
2019-06-07 16:14:21 +02:00
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
var selection = RED.view.selection();
if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
2019-06-07 16:14:21 +02:00
RED.sidebar.info.refresh(workspace);
}
if (changes.hasOwnProperty('disabled')) {
RED.nodes.eachNode(function(n) {
if (n.z === workspace.id) {
n.dirty = true;
}
});
RED.view.redraw();
}
}
}
function removeWorkspace(ws) {
if (!ws) {
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
} else {
if (workspace_tabs.contains(ws.id)) {
workspace_tabs.removeTab(ws.id);
}
2018-10-17 14:45:57 +02:00
if (ws.id === activeWorkspace) {
activeWorkspace = 0;
}
}
}
2016-05-04 16:22:30 +02:00
function setWorkspaceOrder(order) {
var newOrder = order.filter(function(id) {
2016-05-04 16:22:30 +02:00
return RED.nodes.workspace(id) !== undefined;
})
var currentOrder = RED.nodes.getWorkspaceOrder();
if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) {
RED.nodes.setWorkspaceOrder(newOrder);
RED.events.emit("flows:reorder",newOrder);
}
2016-05-04 16:22:30 +02:00
workspace_tabs.order(order);
}
return {
init: init,
add: addWorkspace,
remove: removeWorkspace,
2016-05-04 16:22:30 +02:00
order: setWorkspaceOrder,
edit: editWorkspace,
contains: function(id) {
return workspace_tabs.contains(id);
},
count: function() {
return workspaceTabCount;
},
active: function() {
return activeWorkspace
},
selection: function() {
return workspace_tabs.selection();
},
show: function(id,skipStack) {
if (!workspace_tabs.contains(id)) {
var sf = RED.nodes.subflow(id);
if (sf) {
addWorkspace(
{type:"subflow",id:id,icon:"red/images/subflow_tab.svg",label:sf.name, closeable: true},
null,
workspace_tabs.activeIndex()+1
);
} else {
return;
}
2015-07-01 00:42:03 +02:00
}
if (!skipStack && activeWorkspace !== id) {
addToViewStack(activeWorkspace)
}
workspace_tabs.activateTab(id);
},
refresh: function() {
2016-06-01 00:20:25 +02:00
RED.nodes.eachWorkspace(function(ws) {
workspace_tabs.renameTab(ws.id,ws.label);
})
RED.nodes.eachSubflow(function(sf) {
if (workspace_tabs.contains(sf.id)) {
workspace_tabs.renameTab(sf.id,sf.name);
}
});
2015-10-16 22:56:20 +02:00
RED.sidebar.config.refresh();
},
resize: function() {
workspace_tabs.resize();
2019-06-07 16:14:21 +02:00
},
enable: enableWorkspace,
disable: disableWorkspace
}
})();