1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add subflow meta data edit pane

This commit is contained in:
Nick O'Leary 2020-11-19 14:28:50 +00:00
parent 814fc8bc69
commit de15a1c36f
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
6 changed files with 184 additions and 1 deletions

View File

@ -339,6 +339,16 @@
"deleteSubflow": "delete subflow", "deleteSubflow": "delete subflow",
"info": "Description", "info": "Description",
"category": "Category", "category": "Category",
"module": "Module",
"license": "License",
"licenseOther": "Other",
"version": "Version",
"versionPlaceholder": "x.y.z",
"keys": "Keywords",
"keysPlaceholder": "Comma-separated keywords",
"author": "Author",
"authorPlaceholder": "Your Name <email@example.com>",
"desc": "Description",
"env": { "env": {
"restore": "Restore to subflow default", "restore": "Restore to subflow default",
"remove": "Remove environment variable" "remove": "Remove environment variable"
@ -1079,6 +1089,7 @@
"editor-tab": { "editor-tab": {
"properties": "Properties", "properties": "Properties",
"envProperties": "Environment Variables", "envProperties": "Environment Variables",
"module": "Module Properties",
"description": "Description", "description": "Description",
"appearance": "Appearance", "appearance": "Appearance",
"preview": "UI Preview", "preview": "UI Preview",

View File

@ -339,6 +339,12 @@
"deleteSubflow": "サブフローを削除", "deleteSubflow": "サブフローを削除",
"info": "詳細", "info": "詳細",
"category": "カテゴリ", "category": "カテゴリ",
"module": "モジュール",
"license": "ライセンス",
"version": "バージョン",
"keys": "キーワード",
"author": "作者",
"desc": "説明",
"env": { "env": {
"restore": "デフォルト値に戻す", "restore": "デフォルト値に戻す",
"remove": "環境変数を削除" "remove": "環境変数を削除"

View File

@ -670,6 +670,7 @@ RED.nodes = (function() {
node.in = []; node.in = [];
node.out = []; node.out = [];
node.env = n.env; node.env = n.env;
node.meta = n.meta;
if (exportCreds) { if (exportCreds) {
var credentialSet = {}; var credentialSet = {};

View File

@ -2253,6 +2253,14 @@ RED.editor = (function() {
changed = true; changed = true;
} }
var newMeta = RED.subflow.exportSubflowModuleProperties(editing_node);
if (!isSameObj(editing_node.meta,newMeta)) {
changes.meta = editing_node.meta;
editing_node.meta = newMeta;
changed = true;
}
if (changed) { if (changed) {
var wasChanged = editing_node.changed; var wasChanged = editing_node.changed;
editing_node.changed = true; editing_node.changed = true;
@ -2359,6 +2367,16 @@ RED.editor = (function() {
}; };
editorTabs.addTab(nodePropertiesTab); editorTabs.addTab(nodePropertiesTab);
var moduleTab = {
id: "editor-tab-module",
label: RED._("editor-tab.module"),
name: RED._("editor-tab.module"),
content: $('<div>', {class:"red-ui-tray-content"}).appendTo(editorContent).hide(),
iconClass: "fa fa-cube",
};
editorTabs.addTab(moduleTab);
RED.subflow.buildModuleForm(moduleTab.content, editing_node);
var descriptionTab = { var descriptionTab = {
id: "editor-tab-description", id: "editor-tab-description",
label: RED._("editor-tab.description"), label: RED._("editor-tab.description"),

View File

@ -47,6 +47,33 @@ RED.subflow = (function() {
'</div>'+ '</div>'+
'</script>'; '</script>';
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
'<div class="form-row">'+
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.license"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
'</div>'+
'</form>';
function findAvailableSubflowIOPosition(subflow,isInput) { function findAvailableSubflowIOPosition(subflow,isInput) {
var pos = {x:50,y:30}; var pos = {x:50,y:30};
if (!isInput) { if (!isInput) {
@ -1893,6 +1920,118 @@ RED.subflow = (function() {
buildPropertiesList(list, node); buildPropertiesList(list, node);
} }
function setupInputValidation(input,validator) {
var errorTip;
var validateTimeout;
var validateFunction = function() {
if (validateTimeout) {
return;
}
validateTimeout = setTimeout(function() {
var error = validator(input.val());
// if (!error && errorTip) {
// errorTip.close();
// errorTip = null;
// } else if (error && !errorTip) {
// errorTip = RED.popover.create({
// tooltip: true,
// target:input,
// size: "small",
// direction: "bottom",
// content: error,
// }).open();
// }
input.toggleClass("input-error",!!error);
validateTimeout = null;
})
}
input.on("change keyup paste", validateFunction);
}
function buildModuleForm(container, node) {
$(_subflowModulePaneTemplate).appendTo(container);
var moduleProps = node.meta || {};
[
'module',
'version',
'author',
'desc',
'keywords',
'license'
].forEach(function(property) {
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
})
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue.length < 215;
isValid = isValid && !/^[._]/.test(newValue);
isValid = isValid && !/[A-Z]/.test(newValue);
if (newValue !== encodeURIComponent(newValue)) {
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
if (m) {
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
} else {
isValid = false;
}
}
return isValid?"":"Invalid module name"
})
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue === "" ||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
return isValid?"":"Invalid version number"
})
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
var typedLicenses = {
types: licenses.map(function(l) {
return {value:l,label:l,hasValue:false}
})
}
typedLicenses.types.push({
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
})
if (!moduleProps.license) {
typedLicenses.default = "none";
} else if (licenses.indexOf(moduleProps.license) > -1) {
typedLicenses.default = moduleProps.license;
} else {
typedLicenses.default = "_custom_";
}
$("#subflow-input-module-license").typedInput(typedLicenses)
}
function exportSubflowModuleProperties(node) {
var value;
var moduleProps = {};
[
'module',
'version',
'author',
'desc',
'keywords'
].forEach(function(property) {
value = $("#subflow-input-module-"+property).val().trim();
if (value) {
moduleProps[property] = value;
}
})
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
if (selectedLicenseType === '_custom_') {
value = $("#subflow-input-module-license").val();
if (value) {
moduleProps.license = value;
}
} else if (selectedLicenseType !== "none") {
moduleProps.license = selectedLicenseType;
}
return moduleProps;
}
return { return {
init: init, init: init,
createSubflow: createSubflow, createSubflow: createSubflow,
@ -1906,9 +2045,11 @@ RED.subflow = (function() {
buildEditForm: buildEditForm, buildEditForm: buildEditForm,
buildPropertiesForm: buildPropertiesForm, buildPropertiesForm: buildPropertiesForm,
buildModuleForm: buildModuleForm,
exportSubflowTemplateEnv: exportEnvList, exportSubflowTemplateEnv: exportEnvList,
exportSubflowInstanceEnv: exportSubflowInstanceEnv exportSubflowInstanceEnv: exportSubflowInstanceEnv,
exportSubflowModuleProperties: exportSubflowModuleProperties
} }
})(); })();

View File

@ -382,6 +382,12 @@ RED.sidebar.info = (function() {
var category = subflowNode.category||"subflows"; var category = subflowNode.category||"subflows";
$(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category})) $(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category}))
$('<tr class="node-info-subflow-row"><td>'+RED._("sidebar.info.instances")+"</td><td>"+subflowUserCount+'</td></tr>').appendTo(tableBody); $('<tr class="node-info-subflow-row"><td>'+RED._("sidebar.info.instances")+"</td><td>"+subflowUserCount+'</td></tr>').appendTo(tableBody);
if (subflowNode.meta) {
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.module")+'</td><td></td></tr>').appendTo(tableBody);
$(propRow.children()[1]).text(subflowNode.meta.module||"")
propRow = $('<tr class="red-ui-help-info-row"><td>'+RED._("subflow.version")+'</td><td></td></tr>').appendTo(tableBody);
$(propRow.children()[1]).text(subflowNode.meta.version||"")
}
} }
// var helpText = ""; // var helpText = "";