mirror of
https://github.com/fluxscape/fluxscape.git
synced 2026-01-11 23:02:55 +01:00
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
622 lines
16 KiB
JavaScript
622 lines
16 KiB
JavaScript
'use strict';
|
|
|
|
function formatDynamicPorts(nodeMetadata) {
|
|
const dynamicports = [];
|
|
|
|
for (const dp of nodeMetadata.dynamicports) {
|
|
if (dp.ports || dp.template || dp.port || dp.channelPort) {
|
|
//same format as editor expects, no need to transform it
|
|
dynamicports.push(dp);
|
|
} else if (dp.inputs || dp.outputs) {
|
|
//inputs and outputs is just list of names
|
|
//need to pull the metadata from the inputs/outputs since they
|
|
//won't be registered by the editor (it's either a regular port
|
|
// or a dynamic port, can't register both)
|
|
const ports = [];
|
|
|
|
if (dp.inputs) {
|
|
for (const inputName of dp.inputs) {
|
|
ports.push(formatPort(inputName, nodeMetadata.inputs[inputName], 'input'));
|
|
}
|
|
}
|
|
|
|
if (dp.outputs) {
|
|
for (const outputName of dp.outputs) {
|
|
ports.push(formatPort(outputName, nodeMetadata.outputs[outputName], 'output'));
|
|
}
|
|
}
|
|
|
|
const dynamicPortGroup = {
|
|
name: dp.name || 'conditionalports/basic',
|
|
condition: dp.condition,
|
|
ports
|
|
};
|
|
|
|
dynamicports.push(dynamicPortGroup);
|
|
}
|
|
}
|
|
|
|
return dynamicports;
|
|
}
|
|
|
|
function formatPort(portName, portData, plugType) {
|
|
var port = {
|
|
name: portName,
|
|
type: portData.type,
|
|
plug: plugType
|
|
};
|
|
if (portData.group) {
|
|
port.group = portData.group;
|
|
}
|
|
if (portData.displayName) {
|
|
port.displayName = portData.displayName;
|
|
}
|
|
if (portData.description) {
|
|
port.description = portData.description;
|
|
}
|
|
if (portData.editorName) {
|
|
port.editorName = portData.editorName;
|
|
}
|
|
if (portData.default !== undefined) {
|
|
port.default = portData.default;
|
|
}
|
|
if (portData.hasOwnProperty('index')) {
|
|
port.index = portData.index;
|
|
}
|
|
if (portData.tooltip) {
|
|
port.tooltip = portData.tooltip;
|
|
}
|
|
if (portData.tab) {
|
|
port.tab = portData.tab;
|
|
}
|
|
if (portData.popout) {
|
|
port.popout = portData.popout;
|
|
}
|
|
if (portData.allowVisualStates) {
|
|
port.allowVisualStates = portData.allowVisualStates;
|
|
}
|
|
return port;
|
|
}
|
|
|
|
function generateNodeLibrary(nodeRegister) {
|
|
var obj = {
|
|
//note: needs to include ALL types
|
|
typecasts: [
|
|
{
|
|
from: 'string',
|
|
to: ['number', 'boolean', 'image', 'color', 'enum', 'textStyle', 'dimension', 'array', 'object']
|
|
},
|
|
{
|
|
from: 'boolean',
|
|
to: ['number', 'string', 'signal']
|
|
},
|
|
{
|
|
from: 'number',
|
|
to: ['boolean', 'string', 'dimension']
|
|
},
|
|
{
|
|
from: 'date',
|
|
to: ['string']
|
|
},
|
|
{
|
|
from: 'signal',
|
|
to: ['boolean', 'number']
|
|
},
|
|
{
|
|
from: 'image',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'cloudfile',
|
|
to: ['string', 'image']
|
|
},
|
|
{
|
|
from: 'color',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'enum',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'object',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'domelement',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'reference',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'font',
|
|
to: []
|
|
},
|
|
{
|
|
from: 'textStyle',
|
|
to: ['string']
|
|
},
|
|
{
|
|
// Collection is deprecated but supported via typecasts
|
|
from: 'collection',
|
|
to: ['array']
|
|
},
|
|
{
|
|
from: 'array',
|
|
to: ['collection']
|
|
}
|
|
],
|
|
dynamicports: [
|
|
{
|
|
type: 'conditionalports',
|
|
name: 'basic'
|
|
},
|
|
{
|
|
type: 'expand',
|
|
name: 'basic'
|
|
}
|
|
],
|
|
colors: {
|
|
nodes: {
|
|
component: {
|
|
base: '#643D8B',
|
|
baseHighlighted: '#79559b',
|
|
header: '#4E2877',
|
|
headerHighlighted: '#643d8b',
|
|
outline: '#4E2877',
|
|
outlineHighlighted: '#b58900',
|
|
text: '#dbd0e4'
|
|
},
|
|
visual: {
|
|
base: '#315272',
|
|
baseHighlighted: '#4d6784',
|
|
header: '#173E5D',
|
|
headerHighlighted: '#315272',
|
|
outline: '#173E5D',
|
|
outlineHighlighted: '#b58900',
|
|
text: '#cfd5de'
|
|
},
|
|
data: {
|
|
base: '#465524',
|
|
baseHighlighted: '#5b6a37',
|
|
header: '#314110',
|
|
headerHighlighted: '#465524',
|
|
outline: '#314110',
|
|
outlineHighlighted: '#b58900',
|
|
text: '#d2d6c5'
|
|
},
|
|
javascript: {
|
|
base: '#7E3660',
|
|
baseHighlighted: '#944e74',
|
|
header: '#67214B',
|
|
headerHighlighted: '#7e3660',
|
|
outline: '#67214B',
|
|
outlineHighlighted: '#d57bab',
|
|
text: '#e4cfd9'
|
|
},
|
|
default: {
|
|
base: '#4C4F59',
|
|
baseHighlighted: '#62656e',
|
|
header: '#373B45',
|
|
headerHighlighted: '#4c4f59',
|
|
outline: '#373B45',
|
|
outlineHighlighted: '#b58900',
|
|
text: '#d3d4d6'
|
|
}
|
|
},
|
|
connections: {
|
|
signal: {
|
|
normal: '#006f82',
|
|
highlighted: '#7ec2cf',
|
|
pulsing: '#ffffff'
|
|
},
|
|
default: {
|
|
normal: '#875d00',
|
|
highlighted: '#e5ae32',
|
|
pulsing: '#ffffff'
|
|
}
|
|
}
|
|
},
|
|
nodetypes: [
|
|
{
|
|
name: 'Component Children',
|
|
shortDesc: 'This node is a placeholder for where children of this component will be inserted.',
|
|
docs: 'https://docs.noodl.net/nodes/component-utilities/component-children',
|
|
color: 'component',
|
|
allowAsChild: true,
|
|
category: 'Visual',
|
|
haveComponentChildren: ['Visual']
|
|
}
|
|
]
|
|
};
|
|
|
|
var nodeTypes = Object.keys(nodeRegister._constructors);
|
|
|
|
nodeTypes.forEach(function (type) {
|
|
var nodeMetadata = nodeRegister._constructors[type].metadata;
|
|
|
|
var nodeObj = {
|
|
name: type,
|
|
searchTags: nodeMetadata.searchTags
|
|
};
|
|
obj.nodetypes.push(nodeObj);
|
|
|
|
if (nodeMetadata.version) {
|
|
nodeObj.version = nodeMetadata.version;
|
|
}
|
|
if (nodeMetadata.displayNodeName) {
|
|
nodeObj.displayNodeName = nodeMetadata.displayNodeName;
|
|
}
|
|
if (nodeMetadata.nodeDoubleClickAction) {
|
|
nodeObj.nodeDoubleClickAction = nodeMetadata.nodeDoubleClickAction;
|
|
}
|
|
if (nodeMetadata.shortDesc) {
|
|
nodeObj.shortDesc = nodeMetadata.shortDesc;
|
|
}
|
|
if (nodeMetadata.module) {
|
|
nodeObj.module = nodeMetadata.module;
|
|
}
|
|
if (nodeMetadata.deprecated) {
|
|
nodeObj.deprecated = true;
|
|
}
|
|
if (nodeMetadata.haveComponentPorts) {
|
|
nodeObj.haveComponentPorts = true;
|
|
}
|
|
if (nodeMetadata.category === 'Visual') {
|
|
nodeObj.allowAsChild = true;
|
|
nodeObj.allowAsExportRoot = true;
|
|
nodeObj.color = 'visual';
|
|
}
|
|
|
|
if (nodeMetadata.allowAsExportRoot !== undefined) {
|
|
nodeObj.allowAsExportRoot = nodeMetadata.allowAsExportRoot;
|
|
}
|
|
|
|
if (nodeMetadata.allowChildren) {
|
|
nodeObj.allowChildrenWithCategory = ['Visual'];
|
|
nodeObj.color = 'visual';
|
|
}
|
|
if (nodeMetadata.allowChildrenWithCategory) {
|
|
nodeObj.allowChildrenWithCategory = nodeMetadata.allowChildrenWithCategory;
|
|
}
|
|
if (nodeMetadata.singleton) {
|
|
nodeObj.singleton = true;
|
|
}
|
|
if (nodeMetadata.allowAsChild) {
|
|
nodeObj.allowAsChild = true;
|
|
}
|
|
if (nodeMetadata.docs) {
|
|
nodeObj.docs = nodeMetadata.docs;
|
|
}
|
|
if (nodeMetadata.shortDocs) {
|
|
nodeObj.shortDocs = nodeMetadata.shortDocs;
|
|
} else if (nodeMetadata.docs && nodeMetadata.docs.indexOf('https://docs.noodl.net') === 0) {
|
|
nodeObj.shortDocs = nodeMetadata.docs.replace('/#', '') + '-short.md';
|
|
}
|
|
nodeObj.category = nodeMetadata.category;
|
|
|
|
if (nodeMetadata.panels) {
|
|
nodeObj.panels = nodeMetadata.panels;
|
|
}
|
|
if (nodeMetadata.usePortAsLabel) {
|
|
nodeObj.usePortAsLabel = nodeMetadata.usePortAsLabel;
|
|
nodeObj.portLabelTruncationMode = nodeMetadata.portLabelTruncationMode;
|
|
}
|
|
if (nodeMetadata.color) {
|
|
nodeObj.color = nodeMetadata.color;
|
|
}
|
|
if (nodeMetadata.dynamicports) {
|
|
nodeObj.dynamicports = formatDynamicPorts(nodeMetadata);
|
|
}
|
|
if (nodeMetadata.exportDynamicPorts) {
|
|
nodeObj.exportDynamicPorts = nodeMetadata.exportDynamicPorts;
|
|
}
|
|
if (nodeMetadata.visualStates) {
|
|
nodeObj.visualStates = nodeMetadata.visualStates;
|
|
}
|
|
if (nodeMetadata.useVariants) {
|
|
nodeObj.useVariants = nodeMetadata.useVariants;
|
|
}
|
|
if (nodeMetadata.connectionPanel) {
|
|
nodeObj.connectionPanel = nodeMetadata.connectionPanel;
|
|
}
|
|
nodeObj.ports = [];
|
|
|
|
var dynamicports = nodeObj.dynamicports || [];
|
|
var selectorNames = {};
|
|
var conditionalPortNames = {};
|
|
|
|
//flag conditional ports so they don't get added from the normal ports, making them appear twice in the export
|
|
/* dynamicports.filter(d=> d.name === 'conditionalports/basic')
|
|
.forEach(d=> {
|
|
d.ports.forEach(port=> {
|
|
conditionalPortNames[port.plug + '/' + port.name] = true;
|
|
});
|
|
});*/
|
|
|
|
//same for channel ports
|
|
dynamicports
|
|
.filter((d) => d.channelPort !== undefined)
|
|
.forEach((port) => {
|
|
conditionalPortNames[port.channelPort.plug + '/' + port.channelPort.name] = true;
|
|
});
|
|
|
|
if (dynamicports.length) {
|
|
nodeObj.dynamicports = dynamicports;
|
|
}
|
|
|
|
Object.keys(nodeMetadata.inputs).forEach(function (inputName) {
|
|
if (
|
|
selectorNames.hasOwnProperty('input/' + inputName) ||
|
|
conditionalPortNames.hasOwnProperty('input/' + inputName)
|
|
) {
|
|
//this is a selector or dynamic port. It's already been registered
|
|
return;
|
|
}
|
|
var port = nodeMetadata.inputs[inputName];
|
|
if (port.exportToEditor === false) {
|
|
return;
|
|
}
|
|
|
|
nodeObj.ports.push(formatPort(inputName, port, 'input'));
|
|
});
|
|
|
|
function exportOutput(name, output) {
|
|
var port = {
|
|
name: name,
|
|
type: output.type,
|
|
plug: 'output'
|
|
};
|
|
if (output.group) {
|
|
port.group = output.group;
|
|
}
|
|
if (output.displayName) {
|
|
port.displayName = output.displayName;
|
|
}
|
|
if (output.editorName) {
|
|
port.editorName = output.editorName;
|
|
}
|
|
if (output.hasOwnProperty('index')) {
|
|
port.index = output.index;
|
|
}
|
|
nodeObj.ports.push(port);
|
|
}
|
|
|
|
Object.keys(nodeMetadata.outputs).forEach(function (prop) {
|
|
if (selectorNames.hasOwnProperty('output/' + prop) || conditionalPortNames.hasOwnProperty('output/' + prop)) {
|
|
//this is a selector or dynamic port. It's already been registered
|
|
return;
|
|
}
|
|
|
|
var output = nodeMetadata.outputs[prop];
|
|
exportOutput(prop, output);
|
|
});
|
|
});
|
|
|
|
const coreNodes = [
|
|
{
|
|
name: 'UI Elements',
|
|
description: 'Buttons, inputs, containers, media',
|
|
type: 'visual',
|
|
subCategories: [
|
|
{
|
|
name: 'Basic Elements',
|
|
items: ['Group', 'net.noodl.visual.columns', 'Text', 'Image', 'Video', 'Circle', 'net.noodl.visual.icon']
|
|
},
|
|
{
|
|
name: 'UI Controls',
|
|
items: [
|
|
'net.noodl.controls.button',
|
|
'net.noodl.controls.checkbox',
|
|
'net.noodl.controls.options',
|
|
'net.noodl.controls.radiobutton',
|
|
'Radio Button Group',
|
|
'net.noodl.controls.range',
|
|
'net.noodl.controls.textinput'
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Navigation & Popups',
|
|
description: 'Page routing, navigation, popups',
|
|
type: 'logic',
|
|
subCategories: [
|
|
{
|
|
name: 'Navigation',
|
|
items: ['Router', 'RouterNavigate', 'PageInputs', 'net.noodl.externallink', 'PageStackNavigateToPath']
|
|
},
|
|
{
|
|
name: 'Component Stack',
|
|
items: ['Page Stack', 'PageStackNavigate', 'PageStackNavigateBack']
|
|
},
|
|
{
|
|
name: 'Popups',
|
|
items: ['NavigationShowPopup', 'NavigationClosePopup']
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Logic & Utilities',
|
|
description: 'Logic, events, string manipulation',
|
|
type: 'logic',
|
|
subCategories: [
|
|
{
|
|
name: 'General Utils',
|
|
items: [
|
|
'States',
|
|
'Value Changed',
|
|
'Timer',
|
|
'Color Blend',
|
|
'Number Remapper',
|
|
'Counter',
|
|
'Drag',
|
|
'net.noodl.animatetovalue'
|
|
]
|
|
},
|
|
{
|
|
name: 'Logic',
|
|
items: ['Boolean To String', 'Switch', 'And', 'Or', 'Condition', 'Inverter']
|
|
},
|
|
{
|
|
name: 'Events',
|
|
items: ['Event Sender', 'Event Receiver']
|
|
},
|
|
{
|
|
name: 'String Manipulation',
|
|
items: ['Substring', 'String Mapper', 'String Format', 'Date To String', 'Unique Id']
|
|
},
|
|
{
|
|
name: 'System',
|
|
items: ['Screen Resolution', 'Open File Picker']
|
|
},
|
|
{
|
|
name: 'Variables',
|
|
items: ['String', 'Boolean', 'Color', 'Number']
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Component Utilities',
|
|
description: 'Component inputs, outputs & object',
|
|
type: 'component',
|
|
subCategories: [
|
|
{
|
|
name: '',
|
|
items: [
|
|
'Component Inputs',
|
|
'Component Outputs',
|
|
'Component Children',
|
|
'net.noodl.ComponentObject',
|
|
'net.noodl.ParentComponentObject',
|
|
'net.noodl.SetComponentObjectProperties',
|
|
'net.noodl.SetParentComponentObjectProperties'
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Read & Write Data',
|
|
description: 'Arrays, objects, cloud data',
|
|
type: 'data',
|
|
subCategories: [
|
|
{
|
|
name: '',
|
|
items: [
|
|
'RunTasks',
|
|
'For Each',
|
|
'For Each Actions',
|
|
'Model2',
|
|
'SetModelProperties',
|
|
'NewModel',
|
|
'Set Variable',
|
|
'Variable2'
|
|
]
|
|
},
|
|
{
|
|
name: 'Array',
|
|
items: [
|
|
'Collection2',
|
|
'CollectionNew',
|
|
'CollectionRemove',
|
|
'CollectionClear',
|
|
'CollectionInsert',
|
|
'Filter Collection',
|
|
'Map Collection',
|
|
'Static Data'
|
|
]
|
|
},
|
|
{
|
|
name: 'Cloud Data',
|
|
items: [
|
|
'DbModel2',
|
|
'NewDbModelProperties',
|
|
'FilterDBModels',
|
|
'SetDbModelProperties',
|
|
'DbCollection2',
|
|
'DeleteDbModelProperties',
|
|
'AddDbModelRelation',
|
|
'RemoveDbModelRelation',
|
|
'Cloud File',
|
|
'Upload File',
|
|
'CloudFunction2',
|
|
'DbConfig'
|
|
]
|
|
},
|
|
{
|
|
name: 'User',
|
|
items: [
|
|
'net.noodl.user.LogIn',
|
|
'net.noodl.user.LogOut',
|
|
'net.noodl.user.SignUp',
|
|
'net.noodl.user.User',
|
|
'net.noodl.user.SetUserProperties',
|
|
'net.noodl.user.VerifyEmail',
|
|
'net.noodl.user.SendEmailVerification',
|
|
'net.noodl.user.ResetPassword',
|
|
'net.noodl.user.RequestPasswordReset'
|
|
]
|
|
},
|
|
{
|
|
name: 'External Data',
|
|
items: ['REST2']
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Custom Code',
|
|
description: 'Custom JavaScript and CSS',
|
|
type: 'javascript',
|
|
subCategories: [
|
|
{
|
|
name: '',
|
|
items: ['Expression', 'JavaScriptFunction', 'Javascript2', 'CSS Definition']
|
|
}
|
|
]
|
|
},
|
|
{
|
|
name: 'Cloud Functions',
|
|
description: 'Nodes to be used in cloud functions',
|
|
type: 'data',
|
|
subCategories: [
|
|
{
|
|
name: '',
|
|
items: ['noodl.cloud.request', 'noodl.cloud.response']
|
|
},
|
|
{
|
|
name: 'Cloud Data',
|
|
items: ['noodl.cloud.aggregate']
|
|
}
|
|
]
|
|
}
|
|
];
|
|
|
|
obj.nodeIndex = {
|
|
coreNodes
|
|
};
|
|
|
|
const moduleNodes = [];
|
|
|
|
nodeTypes.forEach((type) => {
|
|
const nodeMetadata = nodeRegister._constructors[type].metadata;
|
|
if (nodeMetadata.module) {
|
|
moduleNodes.push(type);
|
|
}
|
|
});
|
|
|
|
if (moduleNodes.length) {
|
|
obj.nodeIndex.moduleNodes = [
|
|
{
|
|
name: '',
|
|
items: moduleNodes
|
|
}
|
|
];
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
module.exports = generateNodeLibrary;
|