From 5218a3fbac0a21b8772a4de3b946e524da48c6b6 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 17 Oct 2017 10:14:50 +0100 Subject: [PATCH] Add custom project.toJSON to simplify state mangement --- editor/js/ui/projects.js | 15 +++-- red/api/editor/projects/index.js | 6 +- red/runtime/nodes/credentials.js | 5 +- .../localfilesystem/projects/Project.js | 62 ++++++++++++------- .../storage/localfilesystem/projects/index.js | 28 ++++++--- 5 files changed, 70 insertions(+), 46 deletions(-) diff --git a/editor/js/ui/projects.js b/editor/js/ui/projects.js index 4f5f1dd9f..73f8ee418 100644 --- a/editor/js/ui/projects.js +++ b/editor/js/ui/projects.js @@ -188,18 +188,15 @@ RED.projects = (function() { } } + RED.deploy.setDeployInflight(true); + RED.projects.settings.switchProject(projectData.name); + sendRequest({ url: "projects", type: "POST", responses: { 200: function(data) { - switchProject(projectData.name,function(err,data) { - if (err) { - console.log("unexpected_error",error) - } else { - dialog.dialog( "close" ); - } - }) + dialog.dialog( "close" ); }, 400: { 'project_exists': function(error) { @@ -217,7 +214,9 @@ RED.projects = (function() { } } } - },projectData) + },projectData).always(function() { + RED.deploy.setDeployInflight(false); + }) diff --git a/red/api/editor/projects/index.js b/red/api/editor/projects/index.js index d403c57f9..270278a76 100644 --- a/red/api/editor/projects/index.js +++ b/red/api/editor/projects/index.js @@ -49,10 +49,8 @@ module.exports = { app.post("/", function(req,res) { // Create project - runtime.storage.projects.createProject(req.body).then(function(name) { - runtime.storage.projects.getProject(name).then(function(data) { - res.json(data); - }); + runtime.storage.projects.createProject(req.body).then(function(data) { + res.json(data); }).catch(function(err) { console.log(err.stack); if (err.code) { diff --git a/red/runtime/nodes/credentials.js b/red/runtime/nodes/credentials.js index 57103ff4c..89caef1da 100644 --- a/red/runtime/nodes/credentials.js +++ b/red/runtime/nodes/credentials.js @@ -189,7 +189,7 @@ var api = module.exports = { if (projectKey) { // This is a project with a bad key. Mark it as invalid // TODO: this delves too deep into Project structure - activeProject.info.settings.credentialSecretInvalid = true; + activeProject.credentialSecretInvalid = true; return when.reject(error); } return when.reject(error); @@ -198,7 +198,8 @@ var api = module.exports = { credentialCache = credentials; } if (clearInvalidFlag) { - delete activeProject.info.settings.credentialSecretInvalid; + // TODO: this delves too deep into Project structure + delete activeProject.credentialSecretInvalid; } }); }, diff --git a/red/runtime/storage/localfilesystem/projects/Project.js b/red/runtime/storage/localfilesystem/projects/Project.js index 7517607fe..973d51205 100644 --- a/red/runtime/storage/localfilesystem/projects/Project.js +++ b/red/runtime/storage/localfilesystem/projects/Project.js @@ -33,10 +33,9 @@ function Project(name) { this.name = name; this.path = fspath.join(projectsDir,name); this.paths = {}; - this.info = { - name: name, - settings: {} - }; + + this.missingFiles = []; + this.credentialSecret = null; } Project.prototype.load = function () { @@ -49,32 +48,28 @@ Project.prototype.load = function () { } this.credentialSecret = projectSettings.credentialSecret; -// console.log(this.name,"credSec",this.credentialSecret ) - if (typeof projectSettings.credentialSecret === "string") { - this.info.settings.credentialsEncrypted = true; - } else { - this.info.settings.credentialsEncrypted = false; - } + + this.paths.flowFile = fspath.join(this.path,"flow.json"); + this.paths.credentialsFile = fspath.join(this.path,"flow_cred.json"); + var promises = []; return checkProjectFiles(project.name).then(function(missingFiles) { if (missingFiles.length > 0) { - project.info.missingFiles = missingFiles; + project.missingFiles = missingFiles; } if (missingFiles.indexOf('package.json') === -1) { project.paths['package.json'] = fspath.join(project.path,"package.json"); promises.push(fs.readFile(project.paths['package.json'],"utf8").then(function(content) { project.package = util.parseJSON(content); - project.info.summary = project.package.description||""; - project.info.dependencies = project.package.dependencies||{}; })); } if (missingFiles.indexOf('README.md') === -1) { project.paths['README.md'] = fspath.join(project.path,"README.md"); promises.push(fs.readFile(project.paths['README.md'],"utf8").then(function(content) { - project.info.description = content; + project.description = content; })); } else { - project.info.description = ""; + project.description = ""; } return when.settle(promises).then(function() { @@ -101,7 +96,7 @@ Project.prototype.update = function (data) { if (!isReset && // not a reset this.credentialSecret && // key already set - !this.info.settings.credentialSecretInvalid && // key not invalid + !this.credentialSecretInvalid && // key not invalid this.credentialSecret !== existingSecret) { // key doesn't match provided existing key var e = new Error("Cannot change credentialSecret without current key"); e.code = "missing_current_credential_key"; @@ -112,7 +107,7 @@ Project.prototype.update = function (data) { var globalProjectSettings = settings.get("projects"); globalProjectSettings.projects[this.name] = globalProjectSettings.projects[this.name]||{} globalProjectSettings.projects[this.name].credentialSecret = project.credentialSecret; - delete this.info.settings.credentialSecretInvalid; + delete this.credentialSecretInvalid; return settings.set("projects",globalProjectSettings); } @@ -121,21 +116,19 @@ Project.prototype.update = function (data) { filesToUpdate[this.paths['README.md']] = function() { return data.description; }; - this.info.description = data.description; + this.description = data.description; } if (data.hasOwnProperty('dependencies')) { filesToUpdate[this.paths['package.json']] = function() { return JSON.stringify(project.package,"",4) }; this.package.dependencies = data.dependencies; - this.info.dependencies = data.dependencies; } if (data.hasOwnProperty('summary')) { filesToUpdate[this.paths['package.json']] = function() { return JSON.stringify(project.package,"",4) }; this.package.description = data.summary; - this.info.summary = data.summary; } var files = Object.keys(filesToUpdate); @@ -168,18 +161,37 @@ Project.prototype.getCommit = function(sha) { } Project.prototype.getFlowFile = function() { - return fspath.join(this.path,"flow.json"); + return this.paths.flowFile; } Project.prototype.getFlowFileBackup = function() { return getBackupFilename(this.getFlowFile()); } Project.prototype.getCredentialsFile = function() { - return fspath.join(this.path,"flow_cred.json"); + return this.paths.credentialsFile; } Project.prototype.getCredentialsFileBackup = function() { return getBackupFilename(this.getCredentialsFile()); } + +Project.prototype.toJSON = function () { + + return { + name: this.name, + summary: this.package.description, + description: this.description, + dependencies: this.package.dependencies, + settings: { + credentialsEncrypted: (typeof this.credentialSecret === "string"), + credentialSecretInvalid: this.credentialSecretInvalid + }, + files: { + flowFile: this.paths.flowFile&&this.paths.flowFile.substring(this.path.length), + credentialsFile: this.paths.credentialsFile&&this.paths.credentialsFile.substring(this.path.length) + } + } +}; + function getBackupFilename(filename) { var ffName = fspath.basename(filename); var ffDir = fspath.dirname(filename); @@ -212,7 +224,11 @@ function createDefaultProject(project) { promises.push(util.writeFile(fspath.join(projectPath,file),defaultFileSet[file](project))); } } - return when.all(promises); + return when.all(promises).then(function() { + return gitTools.stageFile(projectPath,Object.keys(defaultFileSet)); + }).then(function() { + return gitTools.commit(projectPath,"Create project"); + }) }); } diff --git a/red/runtime/storage/localfilesystem/projects/index.js b/red/runtime/storage/localfilesystem/projects/index.js index a296b9744..782188b10 100644 --- a/red/runtime/storage/localfilesystem/projects/index.js +++ b/red/runtime/storage/localfilesystem/projects/index.js @@ -113,35 +113,43 @@ function loadProject(name) { } function getProject(name) { - if (!activeProject || activeProject.name !== name) { - //TODO: throw better err - throw new Error("Cannot get inactive project"); - } + checkActiveProject(name); //return when.resolve(activeProject.info); - return Projects.get(name).then(function(p) { - return p.info - }) + return Projects.get(name); } +function checkActiveProject(project) { + if (!activeProject || activeProject.name !== project) { + //TODO: throw better err + throw new Error("Cannot operate on inactive project"); + } +} function getFiles(project) { + checkActiveProject(project); return activeProject.getFiles(); } function stageFile(project,file) { + checkActiveProject(project); return activeProject.stageFile(file); } function unstageFile(project,file) { + checkActiveProject(project); return activeProject.unstageFile(file); } function commit(project,options) { + checkActiveProject(project); return activeProject.commit(options); } function getFileDiff(project,file,type) { + checkActiveProject(project); return activeProject.getFileDiff(file,type); } function getCommits(project,options) { + checkActiveProject(project); return activeProject.getCommits(options); } function getCommit(project,sha) { + checkActiveProject(project); return activeProject.getCommit(sha); } @@ -167,7 +175,9 @@ function reloadActiveProject() { } function createProject(metadata) { return Projects.create(metadata).then(function(p) { - return p.name; + return setActiveProject(p.name); + }).then(function() { + return getProject(metadata.name); }) } function setActiveProject(projectName) { @@ -198,7 +208,7 @@ function updateProject(project,data) { } function setCredentialSecret(data) { //existingSecret,secret) { var isReset = data.resetCredentialSecret; - var wasInvalid = activeProject.info.settings.credentialSecretInvalid; + var wasInvalid = activeProject.credentialSecretInvalid; return activeProject.update(data).then(function() { if (isReset || !wasInvalid) { if (isReset) {