Better handling of empty projects and lifecycle

This commit is contained in:
Nick O'Leary 2018-01-09 15:06:05 +00:00
parent 8a6488b067
commit 13356047dc
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
9 changed files with 96 additions and 40 deletions

View File

@ -118,6 +118,7 @@
text: "Setup project files", text: "Setup project files",
click: function() { click: function() {
persistentNotifications[notificationId].close(); persistentNotifications[notificationId].close();
delete persistentNotifications[notificationId];
RED.projects.showFilesPrompt(); RED.projects.showFilesPrompt();
} }
} }
@ -128,11 +129,13 @@
text: "No thanks", text: "No thanks",
click: function() { click: function() {
persistentNotifications[notificationId].close(); persistentNotifications[notificationId].close();
delete persistentNotifications[notificationId];
} }
}, { }, {
text: "Create default project files", text: "Create default project files",
click: function() { click: function() {
persistentNotifications[notificationId].close(); persistentNotifications[notificationId].close();
delete persistentNotifications[notificationId];
RED.projects.createDefaultFileSet(); RED.projects.createDefaultFileSet();
} }
} }
@ -142,7 +145,7 @@
if (!persistentNotifications.hasOwnProperty(notificationId)) { if (!persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId] = RED.notify(text,options); persistentNotifications[notificationId] = RED.notify(text,options);
} else { } else {
persistentNotifications[notificationId].update(text,msg.timeout); persistentNotifications[notificationId].update(text,options);
} }
} else if (persistentNotifications.hasOwnProperty(notificationId)) { } else if (persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId].close(); persistentNotifications[notificationId].close();

View File

@ -85,18 +85,34 @@ RED.notify = (function() {
n.update = (function() { n.update = (function() {
var nn = n; var nn = n;
return function(msg,timeout) { return function(msg,options) {
if (typeof msg === "string") { if (typeof msg === "string") {
nn.innerHTML = msg; nn.innerHTML = msg;
} else { } else {
$(nn).empty().append(msg); $(nn).empty().append(msg);
} }
var timeout;
if (typeof options === 'number') {
timeout = options;
} else if (options !== undefined) {
timeout = options.timeout;
if (options.buttons) {
var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(nn)
options.buttons.forEach(function(buttonDef) {
var b = $('<button>').html(buttonDef.text).click(buttonDef.click).appendTo(buttonSet);
if (buttonDef.class) {
b.addClass(buttonDef.class);
}
})
}
}
if (timeout !== undefined && timeout > 0) { if (timeout !== undefined && timeout > 0) {
window.clearTimeout(nn.timeoutid); window.clearTimeout(nn.timeoutid);
nn.timeoutid = window.setTimeout(nn.close,timeout); nn.timeoutid = window.setTimeout(nn.close,timeout);
} else { } else {
window.clearTimeout(nn.timeoutid); window.clearTimeout(nn.timeoutid);
} }
} }
})(); })();

View File

@ -1067,7 +1067,7 @@ RED.projects = (function() {
'open': (function() { 'open': (function() {
var selectedProject; var selectedProject;
return { return {
title: "Open a project", // TODO: NLS title: "Select a project to open", // TODO: NLS
content: function() { content: function() {
return createProjectList({ return createProjectList({
canSelectActive: false, canSelectActive: false,
@ -1111,6 +1111,7 @@ RED.projects = (function() {
'delete': (function() { 'delete': (function() {
var selectedProject; var selectedProject;
return { return {
title: "Select a project to delete", // TODO: NLS
content: function() { content: function() {
return createProjectList({ return createProjectList({
canSelectActive: false, canSelectActive: false,

View File

@ -55,7 +55,7 @@ RED.sidebar.info = (function() {
}); });
nodeSection.expand(); nodeSection.expand();
infoSection = sections.add({ infoSection = sections.add({
title: RED._("sidebar.info.help"), title: RED._("sidebar.info.nodeHelp"),
collapsible: true collapsible: true
}); });
infoSection.expand(); infoSection.expand();

View File

@ -34,6 +34,10 @@
border-left-width: 16px; border-left-width: 16px;
overflow: hidden; overflow: hidden;
} }
.notification p:first-child {
font-size: 1.1em;
font-weight: 500;
}
.notification a { .notification a {
text-decoration: none; text-decoration: none;
&:hover { &:hover {

View File

@ -214,8 +214,8 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: #f3f3f3; background: #f3f3f3;
border-left-color: #aaa; // border-left-color: #aaa;
border-right-color: #aaa; // border-right-color: #aaa;
} }
} }
i { i {

View File

@ -85,9 +85,9 @@
"nodeActionDisabled": "node actions disabled within subflow", "nodeActionDisabled": "node actions disabled within subflow",
"missing-types": "Flows stopped due to missing node types. Check logs for details.", "missing-types": "Flows stopped due to missing node types. Check logs for details.",
"restartRequired": "Node-RED must be restarted to enable upgraded modules", "restartRequired": "Node-RED must be restarted to enable upgraded modules",
"credentials_load_failed": "Flows stopped due to missing or invalid credentialSecret", "credentials_load_failed": "<p>Flows stopped due to missing or invalid credentialSecret.</p>",
"missing_flow_file": "Could not find the project flow file", "missing_flow_file": "<p>Project flow file not found.</p><p>The project is not configured with a flow file.</p>",
"project_empty": "<p>The project repository is empty.</p><p>Do you want to create a default set of project files?<br/>Otherwise, you will have to manually add files to the project outside of the editor.</p>" "project_empty": "<p>The project is empty.</p><p>Do you want to create a default set of project files?<br/>Otherwise, you will have to manually add files to the project outside of the editor.</p>"
}, },
"error": "<strong>Error</strong>: __message__", "error": "<strong>Error</strong>: __message__",

View File

@ -155,7 +155,8 @@ Project.prototype.loadRemotes = function() {
return gitTools.getRemotes(project.path).then(function(remotes) { return gitTools.getRemotes(project.path).then(function(remotes) {
project.remotes = remotes; project.remotes = remotes;
}).then(function() { }).then(function() {
return project.loadBranches(); project.branches = {};
return project.status();
}).then(function() { }).then(function() {
var allRemotes = Object.keys(project.remotes); var allRemotes = Object.keys(project.remotes);
var match = ""; var match = "";
@ -189,15 +190,6 @@ Project.prototype.parseRemoteBranch = function (remoteBranch) {
}; };
Project.prototype.loadBranches = function() {
var project = this;
return gitTools.getBranchInfo(project.path).then(function(branches) {
project.branches = branches;
project.empty = project.branches.empty;
delete project.branches.empty;
});
}
Project.prototype.isEmpty = function () { Project.prototype.isEmpty = function () {
return this.empty; return this.empty;
}; };
@ -439,6 +431,37 @@ Project.prototype.status = function(user) {
code: fetchError.code code: fetchError.code
} }
} }
if (result.commits.total === 0 && Object.keys(result.files).length === 0) {
if (!self.empty) {
runtime.events.emit("runtime-event",{
id:"runtime-state",
payload:{
type:"warning",
error:"project_empty",
text:"notification.warnings.project_empty"},
retain:true
}
);
}
self.empty = true;
} else {
if (self.empty) {
if (self.paths.flowFile) {
runtime.events.emit("runtime-event",{id:"runtime-state",retain:true});
} else {
runtime.events.emit("runtime-event",{
id:"runtime-state",
payload:{
type:"warning",
error:"missing_flow_file",
text:"notification.warnings.missing_flow_file"},
retain:true
}
);
}
}
delete self.empty;
}
return result; return result;
}).catch(function(err) { }).catch(function(err) {
if (/ambiguous argument/.test(err.message)) { if (/ambiguous argument/.test(err.message)) {

View File

@ -117,25 +117,28 @@ function parseFilenames(name) {
} }
return result; return result;
} }
function getBranchInfo(localRepo) { // function getBranchInfo(localRepo) {
return runGitCommand(["status","--porcelain","-b"],localRepo).then(function(output) { // return runGitCommand(["status","--porcelain","-b"],localRepo).then(function(output) {
var lines = output.split("\n"); // var lines = output.split("\n");
var unknownDirs = []; // var unknownDirs = [];
var branchLineRE = /^## (No commits yet on )?(.+?)($|\.\.\.(.+?)($| \[(ahead (\d+))?.*?(behind (\d+))?\]))/m; // var branchLineRE = /^## (No commits yet on )?(.+?)($|\.\.\.(.+?)($| \[(ahead (\d+))?.*?(behind (\d+))?\]))/m;
var m = branchLineRE.exec(output); // console.log(output);
var result = {}; //commits:{}}; // console.log(lines);
if (m) { // var m = branchLineRE.exec(output);
if (m[1]) { // console.log(m);
result.empty = true; // var result = {}; //commits:{}};
} // if (m) {
result.local = m[2]; // if (m[1]) {
if (m[4]) { // result.empty = true;
result.remote = m[4]; // }
} // result.local = m[2];
} // if (m[4]) {
return result; // result.remote = m[4];
}); // }
} // }
// return result;
// });
// }
function getStatus(localRepo) { function getStatus(localRepo) {
// parseFilename('"test with space"'); // parseFilename('"test with space"');
// parseFilename('"test with space" -> knownFile.txt'); // parseFilename('"test with space" -> knownFile.txt');
@ -147,6 +150,12 @@ function getStatus(localRepo) {
} }
return runGitCommand(['rev-list', 'HEAD', '--count'],localRepo).then(function(count) { return runGitCommand(['rev-list', 'HEAD', '--count'],localRepo).then(function(count) {
result.commits.total = parseInt(count); result.commits.total = parseInt(count);
}).catch(function(err) {
if (/ambiguous argument/.test(err.message)) {
result.commits.total = 0;
} else {
throw err;
}
}).then(function() { }).then(function() {
return runGitCommand(["ls-files","--cached","--others","--exclude-standard"],localRepo).then(function(output) { return runGitCommand(["ls-files","--cached","--others","--exclude-standard"],localRepo).then(function(output) {
var lines = output.split("\n"); var lines = output.split("\n");
@ -174,7 +183,7 @@ function getStatus(localRepo) {
return runGitCommand(["status","--porcelain","-b"],localRepo).then(function(output) { return runGitCommand(["status","--porcelain","-b"],localRepo).then(function(output) {
var lines = output.split("\n"); var lines = output.split("\n");
var unknownDirs = []; var unknownDirs = [];
var branchLineRE = /^## (.+?)(?:$|\.\.\.(.+?)(?:$| \[(?:(?:ahead (\d+)(?:,\s*)?)?(?:behind (\d+))?|(gone))\]))/; var branchLineRE = /^## (?:No commits yet on )?(.+?)(?:$|\.\.\.(.+?)(?:$| \[(?:(?:ahead (\d+)(?:,\s*)?)?(?:behind (\d+))?|(gone))\]))/;
lines.forEach(function(line) { lines.forEach(function(line) {
if (line==="") { if (line==="") {
return; return;
@ -566,7 +575,7 @@ module.exports = {
}) })
}, },
getBranches: getBranches, getBranches: getBranches,
getBranchInfo: getBranchInfo, // getBranchInfo: getBranchInfo,
checkoutBranch: function(cwd, branchName, isCreate) { checkoutBranch: function(cwd, branchName, isCreate) {
var args = ['checkout']; var args = ['checkout'];
if (isCreate) { if (isCreate) {