/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.projects = (function() {
var dialog;
var dialogBody;
var activeProject;
var screens = {};
function initScreens() {
screens = {
'welcome': {
content: function() {
var container = $('
');
var buttons = $('').appendTo(container);
var createNew = $('').appendTo(buttons);
createNew.click(function(e) {
e.preventDefault();
show('create');
});
var openExisting = $('').appendTo(buttons);
openExisting.click(function(e) {
e.preventDefault();
show('open')
});
return container;
},
buttons: [
]
},
'create': (function() {
var projectNameInput;
var projectSummaryInput;
var projectFlowFileInput;
var projectSecretInput;
var projectSecretSelect;
var copyProject;
var projectRepoInput;
var emptyProjectCredentialInput;
return {
title: "Create a new project", // TODO: NLS
content: function() {
var container = $('');
var row;
var validateForm = function() {
var projectName = projectNameInput.val();
var valid = true;
if (!/^[a-zA-Z0-9\-_]+$/.test(projectName)) {
if (projectNameInputChanged) {
projectNameInput.addClass("input-error");
}
valid = false;
} else {
projectNameInput.removeClass("input-error");
}
var projectType = $(".projects-dialog-screen-create-type.selected").data('type');
if (projectType === 'copy') {
if (!copyProject) {
valid = false;
}
} else if (projectType === 'clone') {
var repo = projectRepoInput.val();
if (repo.trim() === '') {
// TODO: could do more url regex checking...
if (projectRepoChanged) {
projectRepoInput.addClass("input-error");
}
valid = false;
} else {
projectRepoInput.removeClass("input-error");
}
} else if (projectType === 'empty') {
projectFlowFileInput.toggleClass("input-error",projectFlowFileInput.val()==='')
valid = valid && projectFlowFileInput.val()!=='';
var encryptionState = $("input[name=projects-encryption-type]:checked").val();
if (encryptionState === 'enabled') {
var encryptionKeyType = $("input[name=projects-encryption-key]:checked").val();
if (encryptionKeyType === 'custom') {
valid = valid && emptyProjectCredentialInput.val()!==''
}
}
}
$("#projects-dialog-create").prop('disabled',!valid).toggleClass('disabled ui-button-disabled ui-state-disabled',!valid);
}
row = $('').appendTo(container);
var createAsEmpty = $('').appendTo(row);
var createAsCopy = $('').appendTo(row);
var createAsClone = $('').appendTo(row);
row.find(".projects-dialog-screen-create-type").click(function(evt) {
evt.preventDefault();
$(".projects-dialog-screen-create-type").removeClass('selected');
$(this).addClass('selected');
$(".projects-dialog-screen-create-row").hide();
$(".projects-dialog-screen-create-row-"+$(this).data('type')).show();
validateForm();
})
row = $('').appendTo(container);
$('').appendTo(row);
projectNameInput = $('').appendTo(row);
var projectNameInputChanged = false;
projectNameInput.on("change keyup paste",function() { projectNameInputChanged = true; validateForm(); });
$('').appendTo(row);
// Empty Project
row = $('').appendTo(container);
$('').appendTo(row);
projectSummaryInput = $('').appendTo(row);
$('').appendTo(row);
row = $('').appendTo(container);
$('').appendTo(row);
projectFlowFileInput = $('').val("flow.json")
.on("change keyup paste",validateForm)
.appendTo(row);
$('').appendTo(row);
row = $('').appendTo(container);
$('').appendTo(row);
var credentialsBox = $('
').appendTo(row);
var credentialsRightBox = $('
').appendTo(credentialsBox);
var credentialsLeftBox = $('
',{class:"palette-module-header"}).appendTo(row);
if (entry.label) {
row.parent().addClass("palette-module-section");
headerRow.text(entry.label);
if (entry.index === 1) {
var addButton = $('').appendTo(headerRow).click(function(evt) {
evt.preventDefault();
var deps = $.extend(true, {}, activeProject.dependencies);
for (var m in modulesInUse) {
if (modulesInUse.hasOwnProperty(m) && !modulesInUse[m].known) {
deps[m] = modulesInUse[m].version;
}
}
editDependenciesFunc(deps);
});
} else if (entry.index === 3) {
var removeButton = $('').appendTo(headerRow).click(function(evt) {
evt.preventDefault();
var deps = $.extend(true, {}, activeProject.dependencies);
for (var m in modulesInUse) {
if (modulesInUse.hasOwnProperty(m) && modulesInUse[m].known && modulesInUse[m].count === 0) {
delete deps[m];
}
}
editDependenciesFunc(deps);
});
}
} else {
headerRow.toggleClass("palette-module-unused",entry.count === 0);
entry.element = headerRow;
var titleRow = $('').appendTo(headerRow);
var icon = $('').appendTo(titleRow);
entry.icon = icon;
$('').html(entry.module).appendTo(titleRow);
var metaRow = $('
').appendTo(headerRow);
var versionSpan = $('').html(entry.version).appendTo(metaRow);
if (!entry.known) {
headerRow.addClass("palette-module-unknown");
} else if (entry.known && entry.count === 0) {
}
}
},
sort: function(A,B) {
if (A.index && B.index) {
return A.index - B.index;
}
var Acategory = A.index?A.index:(A.known?(A.count>0?0:4):2);
var Bcategory = B.index?B.index:(B.known?(B.count>0?0:4):2);
if (Acategory === Bcategory) {
return A.module.localeCompare(B.module);
} else {
return Acategory - Bcategory;
}
}
});
sidebarSectionsDeps.container.css("border-bottom","none");
// sidebarSectionsSettings = sidebarSections.add({
// title: RED._("sidebar.project.settings")
// });
// sidebarSectionsSettings.container.css("border-bottom","none");
RED.sidebar.addTab({
id: "project",
label: RED._("sidebar.project.label"),
name: RED._("sidebar.project.name"),
content: sidebarContent,
onchange: function() {
setTimeout(function() {
sidebarSections.resize();
},10);
}
});
RED.events.on('nodes:add', function(n) {
if (!/^subflow:/.test(n.type)) {
var module = RED.nodes.registry.getNodeSetForType(n.type).module;
if (module !== 'node-red') {
if (!modulesInUse.hasOwnProperty(module)) {
modulesInUse[module] = {
module: module,
version: RED.nodes.registry.getModule(module).version,
count: 0,
known: false
}
}
modulesInUse[module].count++;
if (modulesInUse[module].count === 1 && !modulesInUse[module].known) {
sidebarSectionsDepsList.editableList('addItem',modulesInUse[module]);
} else {
sidebarSectionsDepsList.editableList('sort');
if (modulesInUse[module].element) {
modulesInUse[module].element.removeClass("palette-module-unused");
}
}
}
}
})
RED.events.on('nodes:remove', function(n) {
if (!/^subflow:/.test(n.type)) {
var module = RED.nodes.registry.getNodeSetForType(n.type).module;
if (module !== 'node-red' && modulesInUse.hasOwnProperty(module)) {
modulesInUse[module].count--;
if (modulesInUse[module].count === 0) {
if (!modulesInUse[module].known) {
sidebarSectionsDepsList.editableList('removeItem',modulesInUse[module]);
delete modulesInUse[module];
} else {
// TODO: a known dependency is now unused by the flow
sidebarSectionsDepsList.editableList('sort');
modulesInUse[module].element.addClass("palette-module-unused");
}
}
}
}
})
}
function showSidebar() {
RED.sidebar.show("project");
}
function addSpinnerOverlay(container) {
var spinner = $('').appendTo(container);
return spinner;
}
function updateProjectSummary() {
sidebarSectionsInfo.empty();
if (activeProject) {
var table = $('
').appendTo(sidebarSectionsInfo);
var tableBody = $('').appendTo(table);
var propRow;
propRow = $('
Project
').appendTo(tableBody);
$(propRow.children()[1]).html(' '+(activeProject.name||""))
}
}
function updateProjectDescription() {
sidebarSectionsDesc.content.empty();
if (activeProject) {
var div = $('').appendTo(sidebarSectionsDesc.content);
var desc = marked(activeProject.description||"");
var description = addTargetToExternalLinks($('
'+desc+'
')).appendTo(div);
description.find(".bidiAware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "" );
}
}
function updateProjectDependencies() {
if (activeProject) {
sidebarSectionsDepsList.editableList('empty');
sidebarSectionsDepsList.editableList('addItem',{index:1, label:"Unknown Dependencies"});
sidebarSectionsDepsList.editableList('addItem',{index:3, label:"Unused dependencies"});
var dependencies = activeProject.dependencies||{};
var moduleList = Object.keys(dependencies);
if (moduleList.length > 0) {
moduleList.sort();
moduleList.forEach(function(module) {
if (modulesInUse.hasOwnProperty(module)) {
// TODO: this module is used by not currently 'known'
modulesInUse[module].known = true;
} else {
modulesInUse[module] = {module:module,version:dependencies[module], known: true, count:0};
}
})
}
for (var module in modulesInUse) {
if (modulesInUse.hasOwnProperty(module)) {
var m = modulesInUse[module];
if (!dependencies.hasOwnProperty(module) && m.count === 0) {
delete modulesInUse[module];
} else {
sidebarSectionsDepsList.editableList('addItem',modulesInUse[module]);
}
}
}
}
}
// function getUsedModules() {
// var inuseModules = {};
// var inuseTypes = {};
// var getNodeModule = function(node) {
// if (inuseTypes[node.type]) {
// return;
// }
// inuseTypes[node.type] = true;
// inuseModules[RED.nodes.registry.getNodeSetForType(node.type).module] = true;
// }
// RED.nodes.eachNode(getNodeModule);
// RED.nodes.eachConfig(getNodeModule);
// console.log(Object.keys(inuseModules));
// }
// TODO: DRY - tab-info.js
function addTargetToExternalLinks(el) {
$(el).find("a").each(function(el) {
var href = $(this).attr('href');
if (/^https?:/.test(href)) {
$(this).attr('target','_blank');
}
});
return el;
}
*/
function refresh() {
$.getJSON("projects",function(data) {
if (data.active) {
$.getJSON("projects/"+data.active, function(project) {
activeProject = project;
// updateProjectSummary();
// updateProjectDescription();
// updateProjectDependencies();
RED.sidebar.info.refresh();
});
}
});
}
return {
init: init,
showStartup: function() {
show('welcome');
},
newProject: function() {
show('create')
},
selectProject: function() {
show('open')
},
showCredentialsPrompt: function() { //TODO: rename this function
RED.projects.settings.show('settings');
},
showFilesPrompt: function() { //TODO: rename this function
RED.projects.settings.show('settings');
},
// showSidebar: showSidebar,
refresh: refresh,
editProject: function() {
RED.projects.settings.show();
},
getActiveProject: function() {
return activeProject;
}
}
})();