Allow a project to be located below the root of repo

This commit is contained in:
Nick O'Leary
2019-02-15 21:53:27 +00:00
parent 0748dff355
commit e05ff01d57
7 changed files with 286 additions and 113 deletions

View File

@@ -135,7 +135,12 @@
"updated": "Project '__project__' updated",
"pull": "Project '__project__' reloaded",
"revert": "Project '__project__' reverted",
"merge-complete": "Git merge completed"
"merge-complete": "Git merge completed",
"setupCredentials": "Setup credentials",
"setupProjectFiles": "Setup project files",
"no": "No thanks",
"createDefault": "Create default project files",
"mergeConflict": "Show merge conflicts"
},
"label": {
"manage-project-dep": "Manage project dependencies",
@@ -544,14 +549,19 @@
"removeFromProject": "remove from project",
"addToProject": "add to project",
"files": "Files",
"package": "Package",
"flow": "Flow",
"credentials": "Credentials",
"package":"Package",
"packageCreate":"File will be created when changes are saved",
"fileNotExist":"File does not exist",
"selectFile": "Select File",
"invalidEncryptionKey": "Invalid encryption key",
"encryptionEnabled": "Encryption enabled",
"encryptionDisabled": "Encryption disabled",
"setTheEncryptionKey": "Set the encryption key:",
"resetTheEncryptionKey": "Reset the encryption key:",
"changeTheEncryptionKey": "Change the encryption key:",
"setTheEncryptionKey": "Set the encryption key",
"resetTheEncryptionKey": "Reset the encryption key",
"changeTheEncryptionKey": "Change the encryption key",
"currentKey": "Current key",
"newKey": "New key",
"credentialsAlert": "This will delete all existing credentials",

View File

@@ -211,7 +211,7 @@ var RED = (function() {
}
]
} else if (msg.error === "missing-types") {
text+="<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
text+="<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
if (!!RED.projects.getActiveProject()) {
options.buttons = [
{
@@ -239,7 +239,7 @@ var RED = (function() {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Setup credentials",
text: RED._("notification.project.setupCredentials"),
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.showCredentialsPrompt();
@@ -250,7 +250,7 @@ var RED = (function() {
} else {
options.buttons = [
{
text: "Close",
text: RED._("common.label.close"),
click: function() {
persistentNotifications[notificationId].hideNotification();
}
@@ -261,7 +261,7 @@ var RED = (function() {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Setup project files",
text: RED._("notification.project.setupProjectFiles"),
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.showFilesPrompt();
@@ -273,10 +273,10 @@ var RED = (function() {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Create default package file",
text: RED._("notification.project.setupProjectFiles"),
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.createDefaultPackageFile();
RED.projects.showFilesPrompt();
}
}
]
@@ -285,13 +285,13 @@ var RED = (function() {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "No thanks",
text: RED._("notification.project.no"),
click: function() {
persistentNotifications[notificationId].hideNotification();
}
},
{
text: "Create default project files",
text: RED._("notification.project.createDefault"),
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.projects.createDefaultFileSet();
@@ -305,7 +305,7 @@ var RED = (function() {
if (RED.user.hasPermission("projects.write")) {
options.buttons = [
{
text: "Show merge conflicts",
text: RED._("notification.project.mergeConflict"),
click: function() {
persistentNotifications[notificationId].hideNotification();
RED.sidebar.versionControl.showLocalChanges();

View File

@@ -526,7 +526,7 @@ RED.projects.settings = (function() {
}
function showProjectFileListing(row,activeProject,current,filter,done) {
function showProjectFileListing(row,activeProject,current,selectFilter,done) {
var dialog;
var dialogBody;
var filesList;
@@ -569,14 +569,15 @@ RED.projects.settings = (function() {
})
return result;
}
var files = sortFiles("",files,"");
createFileSubList(container,files.children,current,filter,done,"height: 175px");
var files = sortFiles("",files,"")
createFileSubList(container,files.children,current,selectFilter,done,"height: 175px");
spinner.remove();
});
return container;
}
function createFileSubList(container, files, current, filter, onselect, style) {
function createFileSubList(container, files, current, selectFilter, onselect, style) {
style = style || "";
var list = $('<ol>',{class:"projects-dialog-file-list", style:style}).appendTo(container).editableList({
addButton: false,
@@ -592,7 +593,7 @@ RED.projects.settings = (function() {
} else {
children.hide();
}
createFileSubList(children,entry.children,current,filter,onselect);
createFileSubList(children,entry.children,current,selectFilter,onselect);
header.addClass("selectable");
header.click(function(e) {
if ($(this).hasClass("expanded")) {
@@ -618,7 +619,7 @@ RED.projects.settings = (function() {
header.addClass("projects-dialog-file-list-entry-file-type-git");
}
$('<span class="projects-dialog-file-list-entry-file"> <i class="fa '+fileIcon+'"></i></span>').appendTo(header);
if (filter.test(entry.name)) {
if (selectFilter(entry)) {
header.addClass("selectable");
if (entry.path === current) {
header.addClass("selected");
@@ -626,7 +627,7 @@ RED.projects.settings = (function() {
header.click(function(e) {
$(".projects-dialog-file-list-entry.selected").removeClass("selected");
$(this).addClass("selected");
onselect(entry.path);
onselect(entry.path,true);
})
header.dblclick(function(e) {
e.preventDefault();
@@ -730,18 +731,27 @@ RED.projects.settings = (function() {
var title = $('<h3></h3>').text(RED._("sidebar.project.projectSettings.files")).appendTo(pane);
var filesContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
if (RED.user.hasPermission("projects.write")) {
var editFilesButton = $('<button class="editor-button editor-button-small" style="float: right;">' + RED._('sidebar.project.projectSettings.edit') + '</button>')
var editFilesButton = $('<button type="button" id="project-settings-tab-settings-file-edit" class="editor-button editor-button-small" style="float: right;">' + RED._('sidebar.project.projectSettings.edit') + '</button>')
.appendTo(title)
.click(function(evt) {
evt.preventDefault();
formButtons.show();
editFilesButton.hide();
// packageFileLabelText.hide();
if (!activeProject.files.package) {
packageFileSubLabel.find(".projects-edit-form-sublabel-text").text(RED._("sidebar.project.projectSettings.packageCreate"));
packageFileSubLabel.show();
}
packageFileInputSearch.show();
// packageFileInputCreate.show();
flowFileLabelText.hide();
flowFileInput.show();
flowFileInputSearch.show();
credFileLabel.hide();
credFileInput.show();
flowFileInput.focus();
flowFileInputResize();
// credentialStateLabel.parent().hide();
credentialStateLabel.addClass("uneditable-input");
$(".user-settings-row-credentials").show();
@@ -752,14 +762,76 @@ RED.projects.settings = (function() {
}
var row;
// Flow files
row = $('<div class="user-settings-row"></div>').appendTo(filesContainer);
$('<label for=""></label>').text(RED._("sidebar.project.projectSettings.package")).appendTo(row);
var packageFileLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row);
var packageFileLabelPrefixText = $('<span style="display:inline-block; padding: 6px 0 6px 6px">').text("/").appendTo(packageFileLabel);
var packageFileLabelText = $('<span style="display:inline-block; padding: 6px 6px 6px 0">').text(activeProject.files.package||"package.json").appendTo(packageFileLabel);
var packageFileInput = $('<input type="hidden">').val(activeProject.files.package||"package.json").appendTo(packageFileLabel);
var packageFileInputSearch = $('<button type="button" class="editor-button toggle single" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; width: 36px; height: 34px; position: absolute; top: -1px; right: -1px;"><i class="fa fa-folder-open-o"></i></button>')
.hide()
.appendTo(packageFileLabel)
.click(function(e) {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
packageFileLabel.find('.project-file-listing-container').slideUp(200,function() {
$(this).remove();
packageFileLabel.css('height','');
});
packageFileLabel.css('color','');
} else {
$(this).addClass('selected');
packageFileLabel.css('color','inherit');
var fileList = showProjectFileListing(packageFileLabel,activeProject,packageFileInput.val(),
function(entry) { return entry.children || /package\.json$/.test(entry.path); },
function(result,close) {
if (result) {
packageFileInput.val(result);
packageFileLabelText.text(result);
var rootDir = result.substring(0,result.length - 12);
flowFileLabelPrefixText.text("/"+rootDir);
credFileLabelPrefixText.text("/"+rootDir);
flowFileInputResize();
packageFileSubLabel.hide();
}
if (close) {
$(packageFileInputSearch).click();
}
checkFiles();
});
packageFileLabel.css('height','auto');
setTimeout(function() {
fileList.slideDown(200);
},50);
}
})
RED.popover.tooltip(packageFileInputSearch,RED._("sidebar.project.projectSettings.selectFile"));
var packageFileSubLabel = $('<label style="margin-left: 110px" class="projects-edit-form-sublabel"><small><span class="form-warning"><i class="fa fa-warning"></i> <span class="projects-edit-form-sublabel-text"></span></small></label>').appendTo(row).hide();
if (!activeProject.files.package) {
packageFileSubLabel.find(".projects-edit-form-sublabel-text").text(RED._("sidebar.project.projectSettings.fileNotExist"));
packageFileSubLabel.show();
}
var projectPackage = "/"+(activeProject.files.package||"package.json");
var projectRoot = projectPackage.substring(0,projectPackage.length - 12);
// Flow files
row = $('<div class="user-settings-row"></div>').appendTo(filesContainer);
$('<label for=""></label>').text(RED._("sidebar.project.projectSettings.flow")).appendTo(row);
var flowFileLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row);
var flowFileLabelText = $('<span style="display:inline-block; padding: 6px">').text(activeProject.files.flow).appendTo(flowFileLabel);
var flowFileInput = $('<input id="" type="text" style="margin-bottom: 0;width: 100%; border: none;">').val(activeProject.files.flow).hide().appendTo(flowFileLabel);
var flowFileInputSearch = $('<button class="editor-button" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; width: 36px; height: 34px; position: absolute; top: -1px; right: -1px;"><i class="fa fa-folder-open-o"></i></button>')
var flowFileLabelPrefixText = $('<span style="display:inline-block; padding: 6px 0 6px 6px">').text(projectRoot).appendTo(flowFileLabel);
var flowFileLabelText = $('<span style="display:inline-block; padding: 6px 6px 6px 0">').text(activeProject.files.flow||"flows.json").appendTo(flowFileLabel);
var flowFileInputResize = function() {
flowFileInput.css({
"width": "calc(100% - "+(flowFileInputSearch.width() + flowFileLabelPrefixText.width())+"px)"
});
}
var flowFileInput = $('<input type="text" style="padding-left:1px; margin-top: -2px; margin-bottom: 0;border: none;">').val(activeProject.files.flow||"flows.json").hide().appendTo(flowFileLabel);
var flowFileInputSearch = $('<button type="button" class="editor-button toggle single" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; width: 36px; height: 34px; position: absolute; top: -1px; right: -1px;"><i class="fa fa-folder-open-o"></i></button>')
.hide()
.appendTo(flowFileLabel)
.click(function(e) {
@@ -773,15 +845,24 @@ RED.projects.settings = (function() {
} else {
$(this).addClass('selected');
flowFileLabel.css('color','inherit');
var fileList = showProjectFileListing(flowFileLabel,activeProject,flowFileInput.val(), /.*\.json$/,function(result,isDblClick) {
if (result) {
flowFileInput.val(result);
}
if (isDblClick) {
$(flowFileInputSearch).click();
}
checkFiles();
});
var packageFile = packageFileInput.val();
var packagePrefix = packageFile.substring(0,packageFile.length - 12);
var re = new RegExp("^"+packagePrefix+".*\.json$");
var fileList = showProjectFileListing(flowFileLabel,
activeProject,
flowFileInput.val(),
function(entry) { return !/package.json$/.test(entry.path) && re.test(entry.path) && !/_cred\.json$/.test(entry.path) },
function(result,isDblClick) {
if (result) {
flowFileInput.val(result.substring(packagePrefix.length));
}
if (isDblClick) {
$(flowFileInputSearch).click();
}
checkFiles();
}
);
flowFileLabel.css('height','auto');
setTimeout(function() {
fileList.slideDown(200);
@@ -789,26 +870,32 @@ RED.projects.settings = (function() {
}
})
RED.popover.tooltip(flowFileInputSearch,RED._("sidebar.project.projectSettings.selectFile"));
row = $('<div class="user-settings-row"></div>').appendTo(filesContainer);
$('<label for=""></label>').text(RED._("sidebar.project.projectSettings.credentials")).appendTo(row);
var credFileLabel = $('<div class="uneditable-input">').text(activeProject.files.credentials).appendTo(row);
var credFileInput = $('<div class="uneditable-input">').text(activeProject.files.credentials).hide().insertAfter(credFileLabel);
var credFileLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row);
var credFileLabelPrefixText = $('<span style="display:inline-block;padding: 6px 0 6px 6px">').text(projectRoot).appendTo(credFileLabel);
var credFileLabelText = $('<span style="display:inline-block; padding: 6px 6px 6px 0">').text(activeProject.files.credentials||"flows_cred.json").appendTo(credFileLabel);
var credFileInput = $('<input type="hidden">').val(activeProject.files.credentials||"flows_cred.json").insertAfter(credFileLabel);
var checkFiles = function() {
var saveDisabled;
var currentFlowValue = flowFileInput.val();
var m = /^(.+?)(\.[^.]*)?$/.exec(currentFlowValue);
if (m) {
credFileInput.text(m[1]+"_cred"+(m[2]||".json"));
credFileLabelText.text(m[1]+"_cred"+(m[2]||".json"));
} else if (currentFlowValue === "") {
credFileInput.text("");
credFileLabelText.text("");
}
credFileInput.val(credFileLabelText.text());
var isFlowInvalid = currentFlowValue==="" ||
/\.\./.test(currentFlowValue) ||
/\/$/.test(currentFlowValue);
saveDisabled = isFlowInvalid || credFileInput.text()==="";
saveDisabled = isFlowInvalid || credFileLabelText.text()==="";
if (credentialSecretExistingInput.is(":visible")) {
credentialSecretExistingInput.toggleClass("input-error", credentialSecretExistingInput.val() === "");
@@ -821,19 +908,22 @@ RED.projects.settings = (function() {
flowFileInput.toggleClass("input-error", isFlowInvalid);
credFileInput.toggleClass("input-error",credFileInput.text()==="");
// credFileInput.toggleClass("input-error",credFileInput.text()==="");
saveButton.toggleClass('disabled',saveDisabled);
saveButton.prop('disabled',saveDisabled);
}
flowFileInput.on("change keyup paste",checkFiles);
if (!activeProject.files.flow) {
$('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(flowFileLabelText);
}
if (!activeProject.files.credentials) {
$('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(credFileLabel);
}
// if (!activeProject.files.package) {
// $('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(packageFileLabelText);
// }
// if (!activeProject.files.flow) {
// $('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(flowFileLabelText);
// }
// if (!activeProject.files.credentials) {
// $('<span class="form-warning"><i class="fa fa-warning"></i> Missing</span>').appendTo(credFileLabel);
// }
row = $('<div class="user-settings-row"></div>').appendTo(filesContainer);
@@ -844,7 +934,7 @@ RED.projects.settings = (function() {
credentialStateLabel.css('color','#666');
credentialSecretButtons.css('vertical-align','top');
var credentialSecretResetButton = $('<button class="editor-button" style="vertical-align: top; width: 36px; margin-bottom: 10px"><i class="fa fa-trash-o"></i></button>')
var credentialSecretResetButton = $('<button type="button" class="editor-button" style="vertical-align: top; width: 36px; margin-bottom: 10px"><i class="fa fa-trash-o"></i></button>')
.appendTo(credentialSecretButtons)
.click(function(e) {
e.preventDefault();
@@ -866,7 +956,9 @@ RED.projects.settings = (function() {
}
checkFiles();
});
var credentialSecretEditButton = $('<button class="editor-button" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; vertical-align: top; width: 36px; margin-bottom: 10px"><i class="fa fa-pencil"></i></button>')
RED.popover.tooltip(credentialSecretResetButton,RED._("sidebar.project.projectSettings.resetTheEncryptionKey"));
var credentialSecretEditButton = $('<button type="button" class="editor-button" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; vertical-align: top; width: 36px; margin-bottom: 10px"><i class="fa fa-pencil"></i></button>')
.appendTo(credentialSecretButtons)
.click(function(e) {
e.preventDefault();
@@ -896,6 +988,7 @@ RED.projects.settings = (function() {
checkFiles();
})
RED.popover.tooltip(credentialSecretEditButton,RED._("sidebar.project.projectSettings.changeTheEncryptionKey"));
row = $('<div class="user-settings-row user-settings-row-credentials"></div>').hide().appendTo(filesContainer);
@@ -930,11 +1023,13 @@ RED.projects.settings = (function() {
var hideEditForm = function() {
editFilesButton.show();
formButtons.hide();
// packageFileLabelText.show();
packageFileInputSearch.hide();
// packageFileInputCreate.hide();
flowFileLabelText.show();
flowFileInput.hide();
flowFileInputSearch.hide();
credFileLabel.show();
credFileInput.hide();
// credentialStateLabel.parent().show();
credentialStateLabel.removeClass("uneditable-input");
credentialStateLabel.css('height','');
@@ -954,13 +1049,26 @@ RED.projects.settings = (function() {
}
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin-right:0;"></span>').hide().appendTo(filesContainer);
$('<button class="editor-button">' + RED._("common.label.cancel") + '</button>')
$('<button type="button" class="editor-button">' + RED._("common.label.cancel") + '</button>')
.appendTo(formButtons)
.click(function(evt) {
evt.preventDefault();
var projectPackage = "/"+(activeProject.files.package||"package.json");
var projectRoot = projectPackage.substring(0,projectPackage.length - 12);
flowFileLabelPrefixText.text(projectRoot);
credFileLabelPrefixText.text(projectRoot);
packageFileLabelText.text(activeProject.files.package||"package.json");
if (!activeProject.files.package) {
packageFileSubLabel.find(".projects-edit-form-sublabel-text").text(RED._("sidebar.project.projectSettings.fileNotExist"));
packageFileSubLabel.show();
} else {
packageFileSubLabel.hide();
}
flowFileInput.val(flowFileLabelText.text());
credFileLabelText.text(activeProject.files.credentials||"flows_cred.json");
hideEditForm();
});
var saveButton = $('<button class="editor-button">' + RED._("common.label.save") + '</button>')
var saveButton = $('<button type="button" class="editor-button">' + RED._("common.label.save") + '</button>')
.appendTo(formButtons)
.click(function(evt) {
evt.preventDefault();
@@ -972,13 +1080,15 @@ RED.projects.settings = (function() {
return;
}
flowFileLabelText.text(flowFileInput.val());
credFileLabel.text(credFileInput.text());
credFileLabelText.text(credFileInput.val());
packageFileSubLabel.hide();
hideEditForm();
}
var payload = {
files: {
flow: flowFileInput.val(),
credentials: credFileInput.text()
credentials: credFileInput.val(),
package: packageFileInput.val()
}
}
@@ -992,7 +1102,8 @@ RED.projects.settings = (function() {
}
}
// console.log(JSON.stringify(payload,null,4));
console.log(payload);
return;
RED.deploy.setDeployInflight(true);
utils.sendRequest({
url: "projects/"+activeProject.name,

View File

@@ -2061,7 +2061,6 @@ RED.projects = (function() {
console.log(xhr);
console.log(textStatus);
console.log(err);
console.log(stack);
}).always(function() {
var delta = Date.now() - start;
delta = Math.max(0,500-delta);
@@ -2389,6 +2388,9 @@ RED.projects = (function() {
return;
}
RED.projects.settings.show('settings');
setTimeout(function() {
$("#project-settings-tab-settings-file-edit").click();
},200)
},
showProjectDependencies: function() {
RED.projects.settings.show('deps');

View File

@@ -967,6 +967,7 @@ RED.utils = (function() {
addSpinnerOverlay: addSpinnerOverlay,
decodeObject: decodeObject,
parseContextKey: parseContextKey,
createIconElement: createIconElement
createIconElement: createIconElement,
sanitize: sanitize
}
})();

View File

@@ -60,7 +60,7 @@
.project-settings-tab-pane {
& * .projects-edit-form-sublabel {
margin-right: 50px;
margin-top: -10px;
margin-top: -10px !important;
margin-bottom: 5px;
}
}