mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Move library import/export to single dialog
This commit is contained in:
parent
1795c491a8
commit
3263008379
@ -182,7 +182,11 @@
|
||||
"all":"all flows",
|
||||
"compact":"compact",
|
||||
"formatted":"formatted",
|
||||
"copy": "Export to clipboard"
|
||||
"copy": "Copy to clipboard",
|
||||
"export": "Export to library",
|
||||
"exportAs": "Export as",
|
||||
"overwrite": "Replace",
|
||||
"exists": "<p><b>\"__file__\"</b> already exists.</p><p>Do you want to replace it?</p>"
|
||||
},
|
||||
"import": {
|
||||
"import": "Import to",
|
||||
@ -354,6 +358,7 @@
|
||||
"typeLibrary": "__type__ library",
|
||||
"unnamedType": "Unnamed __type__",
|
||||
"exportToLibrary": "Export nodes to library",
|
||||
"exportedToLibrary": "Nodes exported to library",
|
||||
"dialogSaveOverwrite": "A __libraryType__ called __libraryName__ already exists. Overwrite?",
|
||||
"invalidFilename": "Invalid filename",
|
||||
"savedNodes": "Saved nodes",
|
||||
|
@ -468,7 +468,7 @@ var RED = (function() {
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),options:[
|
||||
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-export-dialog"},
|
||||
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"}
|
||||
{id:"menu-item-export-library",label:RED._("menu.label.library"),onselect:"core:library-export"}
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"});
|
||||
|
@ -24,6 +24,8 @@ RED.clipboard = (function() {
|
||||
var disabled = false;
|
||||
var popover;
|
||||
var currentPopoverError;
|
||||
var activeExportTab;
|
||||
var libraryBrowser;
|
||||
|
||||
function setupDialogs() {
|
||||
dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>')
|
||||
@ -31,7 +33,7 @@ RED.clipboard = (function() {
|
||||
.dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 500,
|
||||
width: 800,
|
||||
resizable: false,
|
||||
buttons: [
|
||||
{
|
||||
@ -41,14 +43,6 @@ RED.clipboard = (function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-close",
|
||||
class: "primary",
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-download",
|
||||
class: "primary",
|
||||
@ -65,15 +59,71 @@ RED.clipboard = (function() {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-copy",
|
||||
id: "clipboard-dialog-export",
|
||||
class: "primary",
|
||||
text: RED._("clipboard.export.copy"),
|
||||
click: function() {
|
||||
$("#clipboard-export").select();
|
||||
document.execCommand("copy");
|
||||
document.getSelection().removeAllRanges();
|
||||
RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"});
|
||||
$( this ).dialog( "close" );
|
||||
if (activeExportTab === "clipboard-dialog-export-tab-clipboard") {
|
||||
$("#clipboard-export").select();
|
||||
document.execCommand("copy");
|
||||
document.getSelection().removeAllRanges();
|
||||
RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"});
|
||||
$( this ).dialog( "close" );
|
||||
} else {
|
||||
var flowToExport = $("#clipboard-export").val();
|
||||
var selectedPath = libraryBrowser.getPath();
|
||||
var filename = $("#clipboard-dialog-tab-library-name").val().trim();
|
||||
var saveFlow = function() {
|
||||
$.ajax({
|
||||
url:'library/flows/'+selectedPath.path + filename,
|
||||
type: "POST",
|
||||
data: flowToExport,
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function() {
|
||||
// RED.library.loadFlowLibrary();
|
||||
$(dialog).dialog( "close" );
|
||||
RED.notify(RED._("library.exportedToLibrary"),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
}
|
||||
});
|
||||
}
|
||||
if (selectedPath.files) {
|
||||
var exists = false;
|
||||
selectedPath.files.forEach(function(f) {
|
||||
if (f.label === filename) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
if (exists) {
|
||||
dialog.dialog("close");
|
||||
var notification = RED.notify(RED._("clipboard.export.exists",{file:RED.utils.sanitize(filename)}),{
|
||||
type: "warning",
|
||||
fixed: true,
|
||||
buttons: [{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.hideNotification()
|
||||
dialog.dialog( "open" );
|
||||
}
|
||||
},{
|
||||
text: RED._("clipboard.export.overwrite"),
|
||||
click: function() {
|
||||
notification.hideNotification()
|
||||
saveFlow();
|
||||
}
|
||||
}]
|
||||
});
|
||||
} else {
|
||||
saveFlow();
|
||||
}
|
||||
} else {
|
||||
saveFlow();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -101,22 +151,39 @@ RED.clipboard = (function() {
|
||||
|
||||
exportNodesDialog =
|
||||
'<div class="form-row">'+
|
||||
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.export.copy"></label>'+
|
||||
'<label style="width:auto;margin-right: 10px;" data-i18n="common.label.export"></label>'+
|
||||
'<span id="export-range-group" class="button-group">'+
|
||||
'<a id="export-range-selected" class="editor-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
|
||||
'<a id="export-range-flow" class="editor-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
|
||||
'<a id="export-range-full" class="editor-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<textarea readonly style="resize: none; width: 100%; border-radius: 4px;font-family: monospace; font-size: 12px; background:#f3f3f3; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" style="text-align: right;">'+
|
||||
'<span id="export-format-group" class="button-group">'+
|
||||
'<a id="export-format-mini" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
||||
'<a id="export-format-full" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
||||
'</span>'+
|
||||
'</div>';
|
||||
'<div style="height: 500px; position:relative; border:1px solid #999;">'+
|
||||
'<div style="position: absolute; top:0;left:0;bottom:0;width:120px;background: #f3f3f3;">'+
|
||||
'<ul id="clipboard-dialog-export-tabs"></ul>'+
|
||||
'</div>'+
|
||||
'<div id="clipboard-dialog-export-tabs-content">'+
|
||||
'<div id="clipboard-dialog-export-tab-clipboard">'+
|
||||
'<div class="form-row">'+
|
||||
'<textarea readonly id="clipboard-export"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" style="text-align: right;">'+
|
||||
'<span id="export-format-group" class="button-group">'+
|
||||
'<a id="export-format-mini" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
||||
'<a id="export-format-full" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'<div id="clipboard-dialog-export-tab-library">'+
|
||||
'<div id="clipboard-dialog-export-tab-library-browser"></div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label data-i18n="clipboard.export.exportAs"></label><input id="clipboard-dialog-tab-library-name" type="text">'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</div>'
|
||||
;
|
||||
|
||||
|
||||
importNodesDialog =
|
||||
'<div class="form-row"><span data-i18n="clipboard.pasteNodes"></span>'+
|
||||
@ -135,6 +202,26 @@ RED.clipboard = (function() {
|
||||
'</div>';
|
||||
}
|
||||
|
||||
var validateExportFilenameTimeout
|
||||
function validateExportFilename() {
|
||||
if (validateExportFilenameTimeout) {
|
||||
clearTimeout(validateExportFilenameTimeout);
|
||||
}
|
||||
validateExportFilenameTimeout = setTimeout(function() {
|
||||
var filenameInput = $("#clipboard-dialog-tab-library-name");
|
||||
var filename = filenameInput.val().trim();
|
||||
var valid = filename.length > 0 && !/[\/\\]/.test(filename);
|
||||
if (valid) {
|
||||
filenameInput.removeClass("input-error");
|
||||
$("#clipboard-dialog-export").button("enable");
|
||||
} else {
|
||||
filenameInput.addClass("input-error");
|
||||
$("#clipboard-dialog-export").button("disable");
|
||||
}
|
||||
},100);
|
||||
}
|
||||
|
||||
|
||||
var validateImportTimeout;
|
||||
|
||||
function validateImport() {
|
||||
@ -239,8 +326,7 @@ RED.clipboard = (function() {
|
||||
|
||||
$("#clipboard-dialog-ok").show();
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-close").hide();
|
||||
$("#clipboard-dialog-copy").hide();
|
||||
$("#clipboard-dialog-export").hide();
|
||||
$("#clipboard-dialog-download").hide();
|
||||
$("#clipboard-dialog-ok").button("disable");
|
||||
$("#clipboard-import").keyup(validateImport);
|
||||
@ -277,13 +363,95 @@ RED.clipboard = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
function exportNodes() {
|
||||
function exportNodes(mode) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mode = mode || "clipboard";
|
||||
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(exportNodesDialog));
|
||||
|
||||
var tabs = RED.tabs.create({
|
||||
id: "clipboard-dialog-export-tabs",
|
||||
vertical: true,
|
||||
onchange: function(tab) {
|
||||
$("#clipboard-dialog-export-tabs-content").children().hide();
|
||||
$("#" + tab.id).show();
|
||||
activeExportTab = tab.id;
|
||||
if (tab.id === "clipboard-dialog-export-tab-clipboard") {
|
||||
$("#clipboard-dialog-export").button("option","label", RED._("clipboard.export.copy"))
|
||||
$("#clipboard-dialog-download").show();
|
||||
} else {
|
||||
$("#clipboard-dialog-export").button("option","label", RED._("clipboard.export.export"))
|
||||
$("#clipboard-dialog-download").hide();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
tabs.addTab({
|
||||
id: "clipboard-dialog-export-tab-clipboard",
|
||||
label: "Clipboard"
|
||||
});
|
||||
tabs.addTab({
|
||||
id: "clipboard-dialog-export-tab-library",
|
||||
label: "Library"
|
||||
});
|
||||
|
||||
tabs.activateTab("clipboard-dialog-export-tab-"+mode);
|
||||
|
||||
$("#clipboard-dialog-tab-library-name").keyup(validateExportFilename);
|
||||
$("#clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
|
||||
$("#clipboard-dialog-export").button("enable");
|
||||
|
||||
libraryBrowser = RED.library.createBrowser({
|
||||
container: $("#clipboard-dialog-export-tab-library-browser"),
|
||||
addFolderButton: true,
|
||||
onselect: function(file) {
|
||||
if (file && file.label) {
|
||||
$("#clipboard-dialog-tab-library-name").val(file.label);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function xformList(list,label,root) {
|
||||
var result = {
|
||||
icon: root===""?"fa fa-archive":'fa fa-folder',
|
||||
label: label,
|
||||
path: root
|
||||
};
|
||||
|
||||
if (list.f) {
|
||||
result.files = list.f.map(function(f) {
|
||||
return {
|
||||
icon: 'fa fa-file-o',
|
||||
label: f,
|
||||
path: root+f
|
||||
}
|
||||
});
|
||||
}
|
||||
result.children = [];
|
||||
if (list.d) {
|
||||
for (var l in list.d) {
|
||||
if (list.d.hasOwnProperty(l)) {
|
||||
if (root+l !== "_examples_") {
|
||||
result.children.push(xformList(list.d[l], l,root+l+"/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
$.getJSON("library/flows", function(data) {
|
||||
var listing = [xformList(data,"Local","")];
|
||||
listing[0].expanded = true;
|
||||
libraryBrowser.data(listing);
|
||||
});
|
||||
$("#clipboard-dialog-tab-library-name").val("flows.json").select();
|
||||
|
||||
|
||||
dialogContainer.i18n();
|
||||
var format = RED.settings.flowFilePretty ? "export-format-full" : "export-format-mini";
|
||||
|
||||
@ -307,6 +475,8 @@ RED.clipboard = (function() {
|
||||
flow = JSON.stringify(nodes);
|
||||
}
|
||||
$("#clipboard-export").val(flow);
|
||||
setTimeout(function() { $("#clipboard-export").scrollTop(0); },50);
|
||||
|
||||
$("#clipboard-export").focus();
|
||||
}
|
||||
});
|
||||
@ -314,7 +484,6 @@ RED.clipboard = (function() {
|
||||
$("#export-range-group > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
$("#clipboard-export").focus();
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
@ -357,13 +526,13 @@ RED.clipboard = (function() {
|
||||
$("#export-copy").addClass('disabled');
|
||||
}
|
||||
$("#clipboard-export").val(flow);
|
||||
setTimeout(function() { $("#clipboard-export").scrollTop(0); },50);
|
||||
$("#clipboard-export").focus();
|
||||
})
|
||||
|
||||
$("#clipboard-dialog-ok").hide();
|
||||
$("#clipboard-dialog-cancel").hide();
|
||||
$("#clipboard-dialog-copy").hide();
|
||||
$("#clipboard-dialog-close").hide();
|
||||
$("#clipboard-dialog-export").hide();
|
||||
var selection = RED.workspaces.selection();
|
||||
if (selection.length > 0) {
|
||||
$("#export-range-selected").click();
|
||||
@ -381,25 +550,11 @@ RED.clipboard = (function() {
|
||||
} else {
|
||||
$("#export-format-mini").click();
|
||||
}
|
||||
$("#clipboard-export")
|
||||
.focus(function() {
|
||||
var textarea = $(this);
|
||||
textarea.select();
|
||||
textarea.mouseup(function() {
|
||||
textarea.unbind("mouseup");
|
||||
return false;
|
||||
})
|
||||
});
|
||||
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
|
||||
|
||||
$("#clipboard-export").focus();
|
||||
if (!document.queryCommandSupported("copy")) {
|
||||
$("#clipboard-dialog-cancel").hide();
|
||||
$("#clipboard-dialog-close").show();
|
||||
} else {
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-copy").show();
|
||||
}
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-export").show();
|
||||
$("#clipboard-dialog-download").show();
|
||||
|
||||
}
|
||||
@ -460,6 +615,7 @@ RED.clipboard = (function() {
|
||||
RED.actions.add("core:show-export-dialog",exportNodes);
|
||||
RED.actions.add("core:show-import-dialog",importNodes);
|
||||
|
||||
RED.actions.add("core:library-export",function() { exportNodes('library') });
|
||||
|
||||
RED.events.on("editor:open",function() { disabled = true; });
|
||||
RED.events.on("editor:close",function() { disabled = false; });
|
||||
@ -468,7 +624,6 @@ RED.clipboard = (function() {
|
||||
RED.events.on("type-search:open",function() { disabled = true; });
|
||||
RED.events.on("type-search:close",function() { disabled = false; });
|
||||
|
||||
|
||||
$('#chart').on("dragenter",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
|
@ -32,7 +32,7 @@
|
||||
* label: 'Local', // label for the item
|
||||
* icon: 'fa fa-rocket', // (optional) icon for the item
|
||||
* selected: true/false, // (optional) if present, display checkbox accordingly
|
||||
* children: [] | function(done) // (optional) an array of child items, or a function
|
||||
* children: [] | function(item,done) // (optional) an array of child items, or a function
|
||||
* // that will call the `done` callback with an array
|
||||
* // of child items
|
||||
* }
|
||||
@ -66,7 +66,7 @@
|
||||
scrollOnAdd: false,
|
||||
height: '100%',
|
||||
addItem: function(container,i,item) {
|
||||
that._addSubtree(container,item,0);
|
||||
that._addSubtree(that._topList,container,item,0);
|
||||
}
|
||||
});
|
||||
if (this.options.data) {
|
||||
@ -80,20 +80,27 @@
|
||||
scrollOnAdd: false,
|
||||
height: 'auto',
|
||||
addItem: function(container,i,item) {
|
||||
that._addSubtree(container,item,depth+1);
|
||||
that._addSubtree(subtree,container,item,depth+1);
|
||||
}
|
||||
});
|
||||
for (var i=0;i<children.length;i++) {
|
||||
subtree.editableList('addItem',children[i])
|
||||
}
|
||||
return subtree;
|
||||
},
|
||||
_addSubtree: function(container, item, depth) {
|
||||
_addSubtree: function(parentList, container, item, depth) {
|
||||
var that = this;
|
||||
item.treeList = {};
|
||||
item.treeList.parentList = parentList;
|
||||
item.treeList.remove = function() {
|
||||
parentList.editableList('removeItem',item);
|
||||
}
|
||||
var labelNodeType = "<label>";
|
||||
if (item.children && item.hasOwnProperty('selected')) {
|
||||
labelNodeType = "<div>";
|
||||
}
|
||||
var label = $(labelNodeType,{tabindex:"0",class:"red-ui-treeList-label"}).appendTo(container);
|
||||
item.treeList.label = label;
|
||||
if (item.class) {
|
||||
label.addClass(item.class);
|
||||
}
|
||||
@ -104,19 +111,22 @@
|
||||
label.on('mouseout',function(e) { that._trigger('itemmouseout',e,item); })
|
||||
|
||||
if (item.children) {
|
||||
$('<span class="red-ui-treeList-icon"><i class="fa fa-angle-right" /></span>').appendTo(label);
|
||||
// $('<span class="red-ui-treeList-icon"><i class="fa fa-folder-o" /></span>').appendTo(label);
|
||||
label.click(function(e) {
|
||||
item.treeList.addChild = function(newItem) {
|
||||
item.treeList.childList.editableList('addItem',newItem)
|
||||
item.children.push(newItem);
|
||||
}
|
||||
item.treeList.expand = function() {
|
||||
if (!container.hasClass("built") && typeof item.children === 'function') {
|
||||
container.addClass('built');
|
||||
var childrenAdded = false;
|
||||
var spinner;
|
||||
item.children(function(children) {
|
||||
item.children(item,function(children) {
|
||||
childrenAdded = true;
|
||||
that._addChildren(container,children,depth);
|
||||
item.treeList.childList = that._addChildren(container,children,depth);
|
||||
if (spinner) {
|
||||
spinner.remove();
|
||||
}
|
||||
that._trigger("childrenloaded",null,item)
|
||||
});
|
||||
if (!childrenAdded) {
|
||||
spinner = $('<div class="red-ui-treeList-spinner">').css({
|
||||
@ -125,7 +135,20 @@
|
||||
}
|
||||
|
||||
}
|
||||
container.toggleClass("expanded");
|
||||
container.addClass("expanded");
|
||||
}
|
||||
item.treeList.collapse = function() {
|
||||
container.removeClass("expanded");
|
||||
}
|
||||
|
||||
$('<span class="red-ui-treeList-icon"><i class="fa fa-angle-right" /></span>').appendTo(label);
|
||||
// $('<span class="red-ui-treeList-icon"><i class="fa fa-folder-o" /></span>').appendTo(label);
|
||||
label.click(function(e) {
|
||||
if (container.hasClass("expanded")) {
|
||||
item.treeList.collapse();
|
||||
} else {
|
||||
item.treeList.expand();
|
||||
}
|
||||
})
|
||||
} else {
|
||||
$('<span class="red-ui-treeList-icon"></span>').appendTo(label);
|
||||
@ -140,21 +163,27 @@
|
||||
item.selected = this.checked;
|
||||
that._trigger("select",e,item);
|
||||
})
|
||||
} else if (!item.children) {
|
||||
} else {
|
||||
label.click(function(e) {
|
||||
that._topList.find(".selected").removeClass("selected");
|
||||
label.addClass("selected");
|
||||
that._trigger("select",e,item)
|
||||
})
|
||||
}
|
||||
if (item.icon) {
|
||||
$('<span class="red-ui-treeList-icon"><i class="'+item.icon+'" /></span>').appendTo(label);
|
||||
}
|
||||
$('<span class="red-ui-treeList-label-text"></span>').text(item.label).appendTo(label);
|
||||
if (item.label) {
|
||||
$('<span class="red-ui-treeList-label-text"></span>').text(item.label).appendTo(label);
|
||||
} else if (item.element) {
|
||||
$(item.element).appendTo(label);
|
||||
}
|
||||
if (item.children) {
|
||||
if (Array.isArray(item.children)) {
|
||||
that._addChildren(container,item.children,depth);
|
||||
item.treeList.childList = that._addChildren(container,item.children,depth);
|
||||
}
|
||||
if (item.expanded) {
|
||||
label.click();
|
||||
item.treeList.expand();
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -168,6 +197,8 @@
|
||||
for (var i=0; i<items.length;i++) {
|
||||
this._topList.editableList('addItem',items[i]);
|
||||
}
|
||||
this._trigger("select")
|
||||
|
||||
} else {
|
||||
return this._data;
|
||||
}
|
||||
@ -178,6 +209,16 @@
|
||||
this._topList.editableList('show',this._data[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
select: function(item) {
|
||||
this._topList.find(".selected").removeClass("selected");
|
||||
item.treeList.label.addClass("selected");
|
||||
this._trigger("select",null,item)
|
||||
|
||||
},
|
||||
selected: function() {
|
||||
var s = this._topList.find(".selected").parent().data('data');
|
||||
return s;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -16,13 +16,105 @@
|
||||
RED.library = (function() {
|
||||
|
||||
var exportToLibraryDialog;
|
||||
var elementPrefix = "node-input-";
|
||||
var loadLibraryBrowser;
|
||||
var saveLibraryBrowser;
|
||||
var libraryEditor;
|
||||
var activeLibrary;
|
||||
|
||||
var _libraryLookup = '<div id="node-dialog-library-load" class="hide">'+
|
||||
'<form class="form-horizontal">'+
|
||||
'<div style="height: 500px; position:relative; ">'+
|
||||
'<div id="node-dialog-library-load-browser"></div>'+
|
||||
'<div id="node-dialog-library-load-preview">'+
|
||||
'<div id="node-dialog-library-load-preview-details">'+
|
||||
'<table id="node-dialog-library-load-preview-details-table" class="node-info"></table>'+
|
||||
'</div>'+
|
||||
'<div id="node-dialog-library-load-preview-text"></div>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</form>'+
|
||||
'</div>'
|
||||
|
||||
|
||||
var _librarySaveConfirm = '<div id="node-dialog-library-save-confirm" class="hide"><form class="form-horizontal"><div style="text-align: center; padding-top: 30px;" id="node-dialog-library-save-content"></div></form></div>';
|
||||
var _librarySave = '<div id="node-dialog-library-save" class="hide"><form class="form-horizontal"><div class="form-row"><label for="node-dialog-library-save-folder" data-i18n="[append]library.folder"><i class="fa fa-folder-open"></i> </label><input type="text" id="node-dialog-library-save-folder" data-i18n="[placeholder]library.folderPlaceholder"></div><div class="form-row"><label for="node-dialog-library-save-filename" data-i18n="[append]library.filename"><i class="fa fa-file"></i> </label><input type="text" id="node-dialog-library-save-filename" data-i18n="[placeholder]library.filenamePlaceholder"></div></form></div>';
|
||||
var _libraryLookup = '<div id="node-dialog-library-lookup" class="hide"><form class="form-horizontal"><div class="form-row"><ul id="node-dialog-library-breadcrumbs" class="breadcrumb"><li class="active"><a href="#" data-i18n="[append]library.breadcrumb"></a></li></ul></div><div class="form-row"><div style="vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;"><div id="node-select-library" style="border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;"><ul></ul></div></div><div style="vertical-align: top; display: inline-block;width: 65%; height: 100%;"><div style="height: 100%; width: 95%;" class="node-text-editor" id="node-select-library-text" ></div></div></div></form></div>';
|
||||
var _librarySave = '<div id="node-dialog-library-save" class="hide">'+
|
||||
'<form class="form-horizontal">'+
|
||||
'<div style="height: 400px; position:relative; ">'+
|
||||
'<div id="node-dialog-library-save-browser"></div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label data-i18n="clipboard.export.exportAs"></label><input id="node-dialog-library-save-filename" type="text">'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</form>'+
|
||||
'</div>'
|
||||
|
||||
function saveToLibrary() {
|
||||
var elementPrefix = activeLibrary.elementPrefix || "node-input-";
|
||||
var name = $("#"+elementPrefix+"name").val().trim();
|
||||
if (name === "") {
|
||||
name = RED._("library.unnamedType",{type:activeLibrary.type});
|
||||
}
|
||||
var filename = $("#node-dialog-library-save-filename").val().trim()
|
||||
var selectedPath = saveLibraryBrowser.getPath();
|
||||
var queryArgs = [];
|
||||
var data = {};
|
||||
for (var i=0; i<activeLibrary.fields.length; i++) {
|
||||
var field = activeLibrary.fields[i];
|
||||
if (field == "name") {
|
||||
data.name = name;
|
||||
} else {
|
||||
data[field] = $("#"+elementPrefix+field).val();
|
||||
}
|
||||
}
|
||||
data.text = activeLibrary.editor.getValue();
|
||||
var saveFlow = function() {
|
||||
$.ajax({
|
||||
url:"library/"+activeLibrary.url+'/'+selectedPath.path + filename,
|
||||
type: "POST",
|
||||
data: JSON.stringify(data),
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
RED.notify(RED._("library.savedType", {type:activeLibrary.type}),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
}
|
||||
});
|
||||
}
|
||||
if (selectedPath.files) {
|
||||
var exists = false;
|
||||
selectedPath.files.forEach(function(f) {
|
||||
if (f.label === filename) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
if (exists) {
|
||||
$( "#node-dialog-library-save" ).dialog("close");
|
||||
var notification = RED.notify(RED._("clipboard.export.exists",{file:RED.utils.sanitize(filename)}),{
|
||||
type: "warning",
|
||||
fixed: true,
|
||||
buttons: [{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.hideNotification()
|
||||
$( "#node-dialog-library-save" ).dialog( "open" );
|
||||
}
|
||||
},{
|
||||
text: RED._("clipboard.export.overwrite"),
|
||||
click: function() {
|
||||
notification.hideNotification()
|
||||
saveFlow();
|
||||
}
|
||||
}]
|
||||
});
|
||||
} else {
|
||||
saveFlow();
|
||||
}
|
||||
} else {
|
||||
saveFlow();
|
||||
}
|
||||
}
|
||||
|
||||
function loadFlowLibrary() {
|
||||
$.getJSON("library/flows",function(data) {
|
||||
@ -88,11 +180,59 @@ RED.library = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
function loadLibraryFolder(url,root,done) {
|
||||
$.getJSON("library/"+url+"/"+root,function(data) {
|
||||
var files = [];
|
||||
var items = data.reduce(function(acc,d) {
|
||||
if (typeof d === "string") {
|
||||
acc.push({
|
||||
icon: 'fa fa-folder',
|
||||
label: d,
|
||||
path: root+d+"/",
|
||||
children: function(item,done) {
|
||||
loadLibraryFolder(url,root+d+"/", function(files,children) {
|
||||
item.files = files;
|
||||
item.children = children; // TODO: should this be done by treeList for us
|
||||
done(children);
|
||||
})
|
||||
}
|
||||
});
|
||||
} else {
|
||||
files.push({
|
||||
icon: 'fa fa-file-o',
|
||||
label: d.fn,
|
||||
path: root+d.fn,
|
||||
props: d
|
||||
})
|
||||
}
|
||||
return acc;
|
||||
},[]);
|
||||
done(files,items);
|
||||
});
|
||||
}
|
||||
|
||||
var validateExportFilenameTimeout;
|
||||
function validateExportFilename(filenameInput) {
|
||||
if (validateExportFilenameTimeout) {
|
||||
clearTimeout(validateExportFilenameTimeout);
|
||||
}
|
||||
validateExportFilenameTimeout = setTimeout(function() {
|
||||
var filename = filenameInput.val().trim();
|
||||
var valid = filename.length > 0 && !/[\/\\]/.test(filename);
|
||||
if (valid) {
|
||||
filenameInput.removeClass("input-error");
|
||||
$("#node-dialog-library-save-button").button("enable");
|
||||
} else {
|
||||
filenameInput.addClass("input-error");
|
||||
$("#node-dialog-library-save-button").button("disable");
|
||||
}
|
||||
},100);
|
||||
}
|
||||
|
||||
function createUI(options) {
|
||||
var libraryData = {};
|
||||
var selectedLibraryItem = null;
|
||||
var libraryEditor = null;
|
||||
elementPrefix = options.elementPrefix || "node-input-";
|
||||
var elementPrefix = options.elementPrefix || "node-input-";
|
||||
|
||||
// Orion editor has set/getText
|
||||
// ACE editor has set/getValue
|
||||
@ -107,64 +247,7 @@ RED.library = (function() {
|
||||
options.editor.getValue = options.editor.getText;
|
||||
}
|
||||
|
||||
function buildFileListItem(item) {
|
||||
var li = document.createElement("li");
|
||||
li.onmouseover = function(e) { $(this).addClass("list-hover"); };
|
||||
li.onmouseout = function(e) { $(this).removeClass("list-hover"); };
|
||||
return li;
|
||||
}
|
||||
|
||||
function buildFileList(root,data) {
|
||||
var ul = document.createElement("ul");
|
||||
var li;
|
||||
for (var i=0; i<data.length; i++) {
|
||||
var v = data[i];
|
||||
if (typeof v === "string") {
|
||||
// directory
|
||||
li = buildFileListItem(v);
|
||||
li.onclick = (function () {
|
||||
var dirName = v;
|
||||
return function(e) {
|
||||
var bcli = $('<li class="active"><span class="divider">/</span> </li>');
|
||||
$('<a href="#"></a>').text(dirName).appendTo(bcli).click(function(e) {
|
||||
$(this).parent().nextAll().remove();
|
||||
$.getJSON("library/"+options.url+root+dirName,function(data) {
|
||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data));
|
||||
});
|
||||
e.stopPropagation();
|
||||
});
|
||||
var bc = $("#node-dialog-library-breadcrumbs");
|
||||
$(".active",bc).removeClass("active");
|
||||
bc.append(bcli);
|
||||
$.getJSON("library/"+options.url+root+dirName,function(data) {
|
||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data));
|
||||
});
|
||||
}
|
||||
})();
|
||||
$('<i class="fa fa-folder"></i>').appendTo(li);
|
||||
$('<span>').text(" "+v).appendTo(li);
|
||||
ul.appendChild(li);
|
||||
} else {
|
||||
// file
|
||||
li = buildFileListItem(v);
|
||||
li.innerText = v.name;
|
||||
li.onclick = (function() {
|
||||
var item = v;
|
||||
return function(e) {
|
||||
$(".list-selected",ul).removeClass("list-selected");
|
||||
$(this).addClass("list-selected");
|
||||
$.get("library/"+options.url+root+item.fn, function(data) {
|
||||
selectedLibraryItem = item;
|
||||
libraryEditor.setValue(data,-1);
|
||||
});
|
||||
}
|
||||
})();
|
||||
ul.appendChild(li);
|
||||
}
|
||||
}
|
||||
return ul;
|
||||
}
|
||||
|
||||
// Add the library button to the name <input> in the edit dialog
|
||||
$('#'+elementPrefix+"name").css("width","calc(100% - 52px)").after(
|
||||
'<div class="btn-group" style="margin-left:5px;">'+
|
||||
'<a id="node-input-'+options.type+'-lookup" class="editor-button" data-toggle="dropdown"><i class="fa fa-book"></i> <i class="fa fa-caret-down"></i></a>'+
|
||||
@ -175,331 +258,332 @@ RED.library = (function() {
|
||||
);
|
||||
|
||||
$('#node-input-'+options.type+'-menu-open-library').click(function(e) {
|
||||
$("#node-select-library").children().remove();
|
||||
var bc = $("#node-dialog-library-breadcrumbs");
|
||||
bc.children().first().nextAll().remove();
|
||||
libraryEditor.setValue('',-1);
|
||||
|
||||
$.getJSON("library/"+options.url,function(data) {
|
||||
$("#node-select-library").append(buildFileList("/",data));
|
||||
$("#node-dialog-library-breadcrumbs a").click(function(e) {
|
||||
$(this).parent().nextAll().remove();
|
||||
$("#node-select-library").children().first().replaceWith(buildFileList("/",data));
|
||||
e.stopPropagation();
|
||||
});
|
||||
$( "#node-dialog-library-lookup" ).dialog( "open" );
|
||||
activeLibrary = options;
|
||||
loadLibraryFolder(options.url, "", function(files,items) {
|
||||
var listing = [{
|
||||
icon: 'fa fa-archive',
|
||||
label: "Local",
|
||||
path: "",
|
||||
expanded: true,
|
||||
writable: false,
|
||||
children: [{
|
||||
icon: 'fa fa-cube',
|
||||
label: options.type,
|
||||
path: options.type+"/",
|
||||
expanded: true,
|
||||
children: items,
|
||||
files: files
|
||||
}]
|
||||
}]
|
||||
loadLibraryBrowser.data(listing);
|
||||
});
|
||||
libraryEditor = ace.edit('node-dialog-library-load-preview-text');
|
||||
libraryEditor.setTheme("ace/theme/tomorrow");
|
||||
if (options.mode) {
|
||||
libraryEditor.getSession().setMode(options.mode);
|
||||
}
|
||||
libraryEditor.setOptions({
|
||||
readOnly: true,
|
||||
highlightActiveLine: false,
|
||||
highlightGutterLine: false
|
||||
});
|
||||
libraryEditor.renderer.$cursorLayer.element.style.opacity=0;
|
||||
libraryEditor.$blockScrolling = Infinity;
|
||||
|
||||
|
||||
$( "#node-dialog-library-load" ).dialog("option","title",RED._("library.typeLibrary", {type:options.type})).dialog( "open" );
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('#node-input-'+options.type+'-menu-save-library').click(function(e) {
|
||||
activeLibrary = options;
|
||||
//var found = false;
|
||||
var name = $("#"+elementPrefix+"name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
|
||||
//var buildPathList = function(data,root) {
|
||||
// var paths = [];
|
||||
// if (data.d) {
|
||||
// for (var i in data.d) {
|
||||
// var dn = root+(root==""?"":"/")+i;
|
||||
// var d = {
|
||||
// label:dn,
|
||||
// files:[]
|
||||
// };
|
||||
// for (var f in data.d[i].f) {
|
||||
// d.files.push(data.d[i].f[f].fn.split("/").slice(-1)[0]);
|
||||
// }
|
||||
// paths.push(d);
|
||||
// paths = paths.concat(buildPathList(data.d[i],root+(root==""?"":"/")+i));
|
||||
// }
|
||||
// }
|
||||
// return paths;
|
||||
//};
|
||||
$("#node-dialog-library-save-folder").attr("value","");
|
||||
|
||||
var filename = name.replace(/[^\w-]/g,"-");
|
||||
if (filename === "") {
|
||||
filename = "unnamed-"+options.type;
|
||||
}
|
||||
$("#node-dialog-library-save-filename").attr("value",filename+".js");
|
||||
|
||||
//var paths = buildPathList(libraryData,"");
|
||||
//$("#node-dialog-library-save-folder").autocomplete({
|
||||
// minLength: 0,
|
||||
// source: paths,
|
||||
// select: function( event, ui ) {
|
||||
// $("#node-dialog-library-save-filename").autocomplete({
|
||||
// minLength: 0,
|
||||
// source: ui.item.files
|
||||
// });
|
||||
// }
|
||||
//});
|
||||
loadLibraryFolder(options.url, "", function(files,items) {
|
||||
var listing = [{
|
||||
icon: 'fa fa-archive',
|
||||
label: "Local",
|
||||
path: "",
|
||||
expanded: true,
|
||||
writable: false,
|
||||
children: [{
|
||||
icon: 'fa fa-cube',
|
||||
label: options.type,
|
||||
path: options.type+"/",
|
||||
expanded: true,
|
||||
children: items,
|
||||
files: files
|
||||
}]
|
||||
}]
|
||||
saveLibraryBrowser.data(listing);
|
||||
});
|
||||
|
||||
$( "#node-dialog-library-save" ).dialog( "open" );
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
libraryEditor = ace.edit('node-select-library-text');
|
||||
libraryEditor.setTheme("ace/theme/tomorrow");
|
||||
if (options.mode) {
|
||||
libraryEditor.getSession().setMode(options.mode);
|
||||
}
|
||||
libraryEditor.setOptions({
|
||||
readOnly: true,
|
||||
highlightActiveLine: false,
|
||||
highlightGutterLine: false
|
||||
});
|
||||
libraryEditor.renderer.$cursorLayer.element.style.opacity=0;
|
||||
libraryEditor.$blockScrolling = Infinity;
|
||||
|
||||
$( "#node-dialog-library-lookup" ).dialog({
|
||||
title: RED._("library.typeLibrary", {type:options.type}),
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 800,
|
||||
height: 450,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.load"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
if (selectedLibraryItem) {
|
||||
for (var i=0; i<options.fields.length; i++) {
|
||||
var field = options.fields[i];
|
||||
$("#"+elementPrefix+field).val(selectedLibraryItem[field]);
|
||||
}
|
||||
options.editor.setValue(libraryEditor.getValue(),-1);
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
var form = $("form",this);
|
||||
form.height(form.parent().height()-30);
|
||||
$("#node-select-library-text").height("100%");
|
||||
$(".form-row:last-child",form).children().height(form.height()-60);
|
||||
},
|
||||
resize: function(e) {
|
||||
var form = $("form",this);
|
||||
form.height(form.parent().height()-30);
|
||||
$(".form-row:last-child",form).children().height(form.height()-60);
|
||||
}
|
||||
});
|
||||
|
||||
function saveToLibrary(overwrite) {
|
||||
var name = $("#"+elementPrefix+"name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
if (name === "") {
|
||||
name = RED._("library.unnamedType",{type:options.type});
|
||||
}
|
||||
var filename = $("#node-dialog-library-save-filename").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
var pathname = $("#node-dialog-library-save-folder").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
if (filename === "" || !/.+\.js$/.test(filename)) {
|
||||
RED.notify(RED._("library.invalidFilename"),"warning");
|
||||
return;
|
||||
}
|
||||
var fullpath = pathname+(pathname===""?"":"/")+filename;
|
||||
if (!overwrite) {
|
||||
//var pathnameParts = pathname.split("/");
|
||||
//var exists = false;
|
||||
//var ds = libraryData;
|
||||
//for (var pnp in pathnameParts) {
|
||||
// if (ds.d && pathnameParts[pnp] in ds.d) {
|
||||
// ds = ds.d[pathnameParts[pnp]];
|
||||
// } else {
|
||||
// ds = null;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//if (ds && ds.f) {
|
||||
// for (var f in ds.f) {
|
||||
// if (ds.f[f].fn == fullpath) {
|
||||
// exists = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//if (exists) {
|
||||
// $("#node-dialog-library-save-content").html(RED._("library.dialogSaveOverwrite",{libraryType:options.type,libraryName:fullpath}));
|
||||
// $("#node-dialog-library-save-confirm").dialog( "open" );
|
||||
// return;
|
||||
//}
|
||||
}
|
||||
var queryArgs = [];
|
||||
var data = {};
|
||||
for (var i=0; i<options.fields.length; i++) {
|
||||
var field = options.fields[i];
|
||||
if (field == "name") {
|
||||
data.name = name;
|
||||
} else {
|
||||
data[field] = $("#"+elementPrefix+field).val();
|
||||
}
|
||||
}
|
||||
|
||||
data.text = options.editor.getValue();
|
||||
$.ajax({
|
||||
url:"library/"+options.url+'/'+fullpath,
|
||||
type: "POST",
|
||||
data: JSON.stringify(data),
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
RED.notify(RED._("library.savedType", {type:options.type}),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
}
|
||||
});
|
||||
}
|
||||
$( "#node-dialog-library-save-confirm" ).dialog({
|
||||
title: RED._("library.saveToLibrary"),
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 530,
|
||||
height: 230,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.save"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
saveToLibrary(true);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
$( "#node-dialog-library-save" ).dialog({
|
||||
title: RED._("library.saveToLibrary"),
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 530,
|
||||
height: 230,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.save"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
saveToLibrary(false);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function exportFlow() {
|
||||
//TODO: don't rely on the main dialog
|
||||
var nns = RED.nodes.createExportableNodeSet(RED.view.selection().nodes);
|
||||
$("#node-input-library-filename").attr('nodes',JSON.stringify(nns));
|
||||
exportToLibraryDialog.dialog( "open" );
|
||||
console.warn("Deprecated call to RED.library.export");
|
||||
}
|
||||
|
||||
function createBrowser(options) {
|
||||
var panes = $('<div class="red-ui-library-browser"></div>').appendTo(options.container);
|
||||
var dirsPane = $('<div class="red-ui-panel"></div>').appendTo(panes);
|
||||
var filesPane = $('<div class="red-ui-panel"></div>').appendTo(panes);
|
||||
//
|
||||
// '<div id="clipboard-dialog-export-tab-library-panes">'+
|
||||
// '<div class="red-ui-panel" id="clipboard-dialog-tab-library-sources-pane"></div>'+
|
||||
// '<div class="red-ui-panel" id="clipboard-dialog-tab-library-listing-pane"></div>'+
|
||||
// '</div>'+
|
||||
RED.panels.create({
|
||||
container:panes,
|
||||
dir: "horizontal"
|
||||
});
|
||||
var dirList = $("<div>").css({width: "100%", height: "100%"}).appendTo(dirsPane)
|
||||
.treeList({}).on('treelistselect', function(event, item) {
|
||||
fileList.treeList('data',item.files||[]);
|
||||
if (addButton) {
|
||||
if (item.writable === false) {
|
||||
addButton.prop('disabled', true);
|
||||
} else {
|
||||
addButton.prop('disabled', false);
|
||||
}
|
||||
}
|
||||
if (options.onpathselect) {
|
||||
options.onpathselect(item);
|
||||
}
|
||||
}).on('treelistchildrenloaded', function(event) {
|
||||
var selected = dirList.treeList('selected');
|
||||
fileList.treeList('data',selected.files||[]);
|
||||
});
|
||||
var addButton;
|
||||
if (options.addFolderButton) {
|
||||
var tools = $("<div>").css({position: "absolute",bottom:"3px",left:"3px"}).appendTo(dirsPane)
|
||||
addButton= $('<button type="button" class="editor-button editor-button-small"><i class="fa fa-plus"> <i class="fa fa-folder-o"></button>').appendTo(tools).click(function(e) {
|
||||
var selected = dirList.treeList('selected');
|
||||
|
||||
var defaultFolderName = "new-folder";
|
||||
var defaultFolderNameMatches = {};
|
||||
selected.children.forEach(function(c) {
|
||||
if (/^new-folder/.test(c.label)) {
|
||||
defaultFolderNameMatches[c.label] = true
|
||||
}
|
||||
});
|
||||
var folderIndex = 2;
|
||||
while(defaultFolderNameMatches[defaultFolderName]) {
|
||||
defaultFolderName = "new-folder-"+(folderIndex++)
|
||||
}
|
||||
|
||||
selected.treeList.expand();
|
||||
var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
|
||||
var newItem = {
|
||||
icon: "fa fa-folder-o",
|
||||
children:[],
|
||||
path: selected.path,
|
||||
element: input
|
||||
}
|
||||
var confirmAdd = function() {
|
||||
var val = input.val().trim();
|
||||
if (val === "") {
|
||||
cancelAdd();
|
||||
return;
|
||||
} else {
|
||||
for (var i=0;i<selected.children.length;i++) {
|
||||
if (selected.children[i].label === val) {
|
||||
cancelAdd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
newItem.treeList.remove();
|
||||
selected.treeList.addChild({
|
||||
icon: "fa fa-folder",
|
||||
children:[],
|
||||
label: val,
|
||||
path: newItem.path+val+"/"
|
||||
});
|
||||
}
|
||||
var cancelAdd = function() {
|
||||
newItem.treeList.remove();
|
||||
}
|
||||
input.on('keydown', function(evt) {
|
||||
if (evt.keyCode === 13) {
|
||||
evt.stopPropagation();
|
||||
confirmAdd();
|
||||
} else if (evt.keyCode === 27) {
|
||||
evt.stopPropagation();
|
||||
cancelAdd();
|
||||
}
|
||||
})
|
||||
input.blur(function() {
|
||||
confirmAdd();
|
||||
})
|
||||
selected.treeList.addChild(newItem);
|
||||
setTimeout(function() {
|
||||
input.focus();
|
||||
input.select();
|
||||
},200);
|
||||
});
|
||||
}
|
||||
|
||||
var fileList = $("<div>").css({width: "100%", height: "100%"}).appendTo(filesPane)
|
||||
.treeList({}).on('treelistselect', function(event, item) {
|
||||
if (options.onselect) {
|
||||
options.onselect(item);
|
||||
}
|
||||
})
|
||||
return {
|
||||
getFile: function() {
|
||||
return fileList.treeList('selected');
|
||||
},
|
||||
getPath: function() {
|
||||
return dirList.treeList('selected');
|
||||
},
|
||||
data: function(content) {
|
||||
dirList.treeList('data',content);
|
||||
setTimeout(function() {
|
||||
dirList.treeList('select',content[0]);
|
||||
},100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
|
||||
|
||||
$(_librarySave).appendTo(document.body);
|
||||
$(_librarySaveConfirm).appendTo(document.body);
|
||||
$(_libraryLookup).appendTo(document.body);
|
||||
|
||||
RED.actions.add("core:library-export",exportFlow);
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
if (!selection.nodes) {
|
||||
RED.menu.setDisabled("menu-item-export-library",true);
|
||||
} else {
|
||||
RED.menu.setDisabled("menu-item-export-library",false);
|
||||
$( "#node-dialog-library-save" ).dialog({
|
||||
title: RED._("library.saveToLibrary"),
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 800,
|
||||
resizable: false,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-library-save-button",
|
||||
text: RED._("common.label.save"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
saveToLibrary(false);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
}
|
||||
});
|
||||
|
||||
saveLibraryBrowser = RED.library.createBrowser({
|
||||
container: $("#node-dialog-library-save-browser"),
|
||||
addFolderButton: true,
|
||||
onpathselect: function(item) {
|
||||
try {
|
||||
if (item.writable === false) {
|
||||
$("#node-dialog-library-save-button").button("disable");
|
||||
} else {
|
||||
$("#node-dialog-library-save-button").button("enable");
|
||||
}
|
||||
} catch(err) {}
|
||||
},
|
||||
onselect: function(file) {
|
||||
$("#node-dialog-library-save-filename").val(file.label);
|
||||
}
|
||||
});
|
||||
$("#node-dialog-library-save-filename").keyup(function() { validateExportFilename($(this))});
|
||||
$("#node-dialog-library-save-filename").on('paste',function() { var input = $(this); setTimeout(function() { validateExportFilename(input)},10)});
|
||||
|
||||
$( "#node-dialog-library-load" ).dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 800,
|
||||
resizable: false,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.load"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
if (selectedLibraryItem) {
|
||||
for (var i=0; i<options.fields.length; i++) {
|
||||
var field = options.fields[i];
|
||||
$("#"+elementPrefix+field).val(selectedLibraryItem[field]);
|
||||
}
|
||||
options.editor.setValue(libraryEditor.getValue(),-1);
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
},
|
||||
close: function(e) {
|
||||
if (libraryEditor) {
|
||||
libraryEditor.destroy();
|
||||
libraryEditor = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
loadLibraryBrowser = RED.library.createBrowser({
|
||||
container: $("#node-dialog-library-load-browser"),
|
||||
onselect: function(file) {
|
||||
var table = $("#node-dialog-library-load-preview-details-table").empty();
|
||||
|
||||
if (file && file.label) {
|
||||
$.get("library/"+activeLibrary.url+"/"+file.path, function(data) {
|
||||
//TODO: nls + sanitize
|
||||
var propRow = $('<tr class="node-info-node-row"><td>Type</td><td></td></tr>').appendTo(table);
|
||||
$(propRow.children()[1]).text(activeLibrary.type);
|
||||
if (file.props.hasOwnProperty('name')) {
|
||||
propRow = $('<tr class="node-info-node-row"><td>Name</td><td>'+file.props.name+'</td></tr>').appendTo(table);
|
||||
$(propRow.children()[1]).text(file.props.name);
|
||||
}
|
||||
for (var p in file.props) {
|
||||
if (file.props.hasOwnProperty(p) && p !== 'name' && p !== 'fn') {
|
||||
propRow = $('<tr class="node-info-node-row"><td></td><td></td></tr>').appendTo(table);
|
||||
$(propRow.children()[0]).text(p);
|
||||
RED.utils.createObjectElement(file.props[p]).appendTo(propRow.children()[1]);
|
||||
}
|
||||
}
|
||||
libraryEditor.setValue(data,-1);
|
||||
});
|
||||
} else {
|
||||
libraryEditor.setValue("",-1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (RED.settings.theme("menu.menu-item-import-library") !== false) {
|
||||
loadFlowLibrary();
|
||||
}
|
||||
|
||||
exportToLibraryDialog = $('<div id="library-dialog" class="hide"><form class="dialog-form form-horizontal"></form></div>')
|
||||
.appendTo("body")
|
||||
.dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 500,
|
||||
resizable: false,
|
||||
title: RED._("library.exportToLibrary"),
|
||||
buttons: [
|
||||
{
|
||||
id: "library-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "library-dialog-ok",
|
||||
class: "primary",
|
||||
text: RED._("common.label.export"),
|
||||
click: function() {
|
||||
//TODO: move this to RED.library
|
||||
var flowName = $("#node-input-library-filename").val();
|
||||
flowName = flowName.trim();
|
||||
if(flowName === "" || flowName.endsWith("/")) {
|
||||
RED.notify(RED._("library.invalidFilename"),"warning");
|
||||
} else {
|
||||
$.ajax({
|
||||
url:'library/flows/'+flowName,
|
||||
type: "POST",
|
||||
data: $("#node-input-library-filename").attr('nodes'),
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function() {
|
||||
RED.library.loadFlowLibrary();
|
||||
RED.notify(RED._("library.savedNodes"),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
}
|
||||
});
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
},
|
||||
close: function(e) {
|
||||
}
|
||||
});
|
||||
exportToLibraryDialog.children(".dialog-form").append($(
|
||||
'<div class="form-row">'+
|
||||
'<label for="node-input-library-filename" data-i18n="[append]editor:library.filename"><i class="fa fa-file"></i> </label>'+
|
||||
'<input type="text" id="node-input-library-filename" data-i18n="[placeholder]editor:library.fullFilenamePlaceholder">'+
|
||||
'<input type="text" style="display: none;" />'+ // Second hidden input to prevent submit on Enter
|
||||
'</div>'
|
||||
));
|
||||
},
|
||||
create: createUI,
|
||||
loadFlowLibrary: loadFlowLibrary,
|
||||
|
||||
createBrowser:createBrowser,
|
||||
export: exportFlow
|
||||
}
|
||||
})();
|
||||
|
@ -22,6 +22,10 @@ $form-input-focus-color: rgba(85,150,230,0.8);
|
||||
$form-input-border-color: #ccc;
|
||||
$form-input-border-selected-color: #aaa;
|
||||
|
||||
$list-item-color: #666;
|
||||
$list-item-background-hover: #f3f3f3;
|
||||
$list-item-background-active: #efefef;
|
||||
$list-item-background-selected: #eee;
|
||||
|
||||
$node-selected-color: #ff7f0e;
|
||||
$port-selected-color: #ff7f0e;
|
||||
|
@ -48,3 +48,112 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
#clipboard-dialog-export-tab-clipboard {
|
||||
padding: 10px;
|
||||
textarea {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
font-family: monospace !important;
|
||||
font-size: 13px !important;
|
||||
height: 430px;
|
||||
line-height: 1.3em;
|
||||
padding: 6px 10px;
|
||||
background: #F3E7E7;
|
||||
color: #533;
|
||||
}
|
||||
}
|
||||
|
||||
#clipboard-dialog-export-tabs-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 120px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
background: white;
|
||||
|
||||
&>div {
|
||||
height: calc(100% - 20px)
|
||||
}
|
||||
}
|
||||
|
||||
#clipboard-dialog-export-tab-library {
|
||||
.form-row {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#clipboard-dialog-tab-library-name {
|
||||
width: calc(100% - 120px);
|
||||
}
|
||||
#clipboard-dialog-export-tab-library-browser {
|
||||
height: calc(100% - 40px);
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid $primary-border-color;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.red-ui-library-browser {
|
||||
height: 100%;
|
||||
|
||||
.red-ui-treeList-container {
|
||||
background: white;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
li {
|
||||
background: none;
|
||||
}
|
||||
label {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
.red-ui-editableList-border {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.red-ui-treeList-label input.red-ui-treeList-input {
|
||||
border-radius: 2px;
|
||||
margin-top: -6px;
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
#node-dialog-library-save-browser {
|
||||
height: calc(100% - 60px);
|
||||
border: 1px solid $primary-border-color;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#node-dialog-library-load-browser {
|
||||
height: 200px;
|
||||
border: 1px solid $primary-border-color;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#node-dialog-library-load-preview {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#node-dialog-library-load-preview-text {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
width: calc(50% - 5px);
|
||||
border: 1px solid $primary-border-color;
|
||||
}
|
||||
#node-dialog-library-load-preview-details {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
width: calc(50% - 5px);
|
||||
margin-right: 10px;
|
||||
border: 1px solid $primary-border-color;
|
||||
|
||||
.node-info-node-row:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
@ -36,17 +36,10 @@
|
||||
|
||||
}
|
||||
|
||||
@mixin workspace-button {
|
||||
@include disable-selection;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
@mixin reset-a-style {
|
||||
color: $workspace-button-color !important;
|
||||
background: $workspace-button-background;
|
||||
border: 1px solid $form-input-border-color;
|
||||
text-align: center;
|
||||
margin:0;
|
||||
text-decoration: none;
|
||||
cursor:pointer;
|
||||
|
||||
&.disabled, &:disabled {
|
||||
cursor: default;
|
||||
@ -67,6 +60,19 @@
|
||||
background: $workspace-button-background-active;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin workspace-button {
|
||||
@include disable-selection;
|
||||
@include reset-a-style;
|
||||
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
border: 1px solid $form-input-border-color;
|
||||
text-align: center;
|
||||
margin:0;
|
||||
cursor:pointer;
|
||||
|
||||
// &.selected:not(.disabled):not(:disabled) {
|
||||
// color: $workspace-button-color-selected !important;
|
||||
// background: $workspace-button-background-active;
|
||||
@ -150,12 +156,12 @@
|
||||
}
|
||||
&:not(.single) {
|
||||
color: $workspace-button-toggle-color !important;
|
||||
background:$workspace-button-background-active;
|
||||
background:$workspace-button-background;
|
||||
margin-bottom: 1px;
|
||||
|
||||
&.selected:not(.disabled):not(:disabled) {
|
||||
color: $workspace-button-toggle-color-selected !important;
|
||||
background: $workspace-button-background;
|
||||
background: $workspace-button-background-active;
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-color: $form-input-border-selected-color;
|
||||
margin-bottom: 0;
|
||||
|
@ -247,7 +247,7 @@
|
||||
z-index: 2;
|
||||
&.red-ui-tab-link-button {
|
||||
&:not(.active) {
|
||||
background: #eee;
|
||||
// background: #eee;
|
||||
}
|
||||
}
|
||||
&.red-ui-tab-link-button-menu {
|
||||
|
@ -72,22 +72,29 @@ label.red-ui-treeList-label {
|
||||
@include disable-selection;
|
||||
padding: 6px 0;
|
||||
display: block;
|
||||
color: $form-text-color;
|
||||
color: $list-item-color;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
margin: 0;
|
||||
|
||||
&:hover {
|
||||
background: #f9f9f9;
|
||||
color: $form-text-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
// &:hover {
|
||||
// background: $list-item-background-hover;
|
||||
// color: $list-item-color;
|
||||
// text-decoration: none;
|
||||
// }
|
||||
&:focus {
|
||||
background: $list-item-background-hover;
|
||||
outline: none;
|
||||
color: $form-text-color;
|
||||
color: $list-item-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
&.selected {
|
||||
background: $list-item-background-selected;
|
||||
outline: none;
|
||||
color: $list-item-color;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user