Files
fluxscape/packages/noodl-runtime/src/nodelibraryexport.js
Michael Cartner b9c60b07dc Initial commit
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>
2024-01-26 11:52:55 +01:00

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;