| import moment from 'moment' |
|
|
| export const getUniqueNodeId = (nodeData, nodes) => { |
| |
| let totalSameNodes = 0 |
| for (let i = 0; i < nodes.length; i += 1) { |
| const node = nodes[i] |
| if (node.data.name === nodeData.name) { |
| totalSameNodes += 1 |
| } |
| } |
|
|
| |
| let nodeId = `${nodeData.name}_${totalSameNodes}` |
| for (let i = 0; i < nodes.length; i += 1) { |
| const node = nodes[i] |
| if (node.id === nodeId) { |
| totalSameNodes += 1 |
| nodeId = `${nodeData.name}_${totalSameNodes}` |
| } |
| } |
| return nodeId |
| } |
|
|
| export const initializeDefaultNodeData = (nodeParams) => { |
| const initialValues = {} |
|
|
| for (let i = 0; i < nodeParams.length; i += 1) { |
| const input = nodeParams[i] |
| initialValues[input.name] = input.default || '' |
| } |
|
|
| return initialValues |
| } |
|
|
| export const initNode = (nodeData, newNodeId) => { |
| const inputAnchors = [] |
| const inputParams = [] |
| const incoming = nodeData.inputs ? nodeData.inputs.length : 0 |
| const outgoing = 1 |
|
|
| const whitelistTypes = ['options', 'string', 'number', 'boolean', 'password', 'json', 'code', 'date', 'file', 'folder'] |
|
|
| for (let i = 0; i < incoming; i += 1) { |
| const newInput = { |
| ...nodeData.inputs[i], |
| id: `${newNodeId}-input-${nodeData.inputs[i].name}-${nodeData.inputs[i].type}` |
| } |
| if (whitelistTypes.includes(nodeData.inputs[i].type)) { |
| inputParams.push(newInput) |
| } else { |
| inputAnchors.push(newInput) |
| } |
| } |
|
|
| const outputAnchors = [] |
| for (let i = 0; i < outgoing; i += 1) { |
| if (nodeData.outputs && nodeData.outputs.length) { |
| const options = [] |
| for (let j = 0; j < nodeData.outputs.length; j += 1) { |
| let baseClasses = '' |
| let type = '' |
|
|
| const outputBaseClasses = nodeData.outputs[j].baseClasses ?? [] |
| if (outputBaseClasses.length > 1) { |
| baseClasses = outputBaseClasses.join('|') |
| type = outputBaseClasses.join(' | ') |
| } else if (outputBaseClasses.length === 1) { |
| baseClasses = outputBaseClasses[0] |
| type = outputBaseClasses[0] |
| } |
|
|
| const newOutputOption = { |
| id: `${newNodeId}-output-${nodeData.outputs[j].name}-${baseClasses}`, |
| name: nodeData.outputs[j].name, |
| label: nodeData.outputs[j].label, |
| type |
| } |
| options.push(newOutputOption) |
| } |
| const newOutput = { |
| name: 'output', |
| label: 'Output', |
| type: 'options', |
| options, |
| default: nodeData.outputs[0].name |
| } |
| outputAnchors.push(newOutput) |
| } else { |
| const newOutput = { |
| id: `${newNodeId}-output-${nodeData.name}-${nodeData.baseClasses.join('|')}`, |
| name: nodeData.name, |
| label: nodeData.type, |
| type: nodeData.baseClasses.join(' | ') |
| } |
| outputAnchors.push(newOutput) |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| if (nodeData.inputs) { |
| nodeData.inputAnchors = inputAnchors |
| nodeData.inputParams = inputParams |
| nodeData.inputs = initializeDefaultNodeData(nodeData.inputs) |
| } else { |
| nodeData.inputAnchors = [] |
| nodeData.inputParams = [] |
| nodeData.inputs = {} |
| } |
|
|
| if (nodeData.outputs) { |
| nodeData.outputs = initializeDefaultNodeData(outputAnchors) |
| } else { |
| nodeData.outputs = {} |
| } |
|
|
| nodeData.outputAnchors = outputAnchors |
| nodeData.id = newNodeId |
|
|
| return nodeData |
| } |
|
|
| export const getEdgeLabelName = (source) => { |
| const sourceSplit = source.split('-') |
| if (sourceSplit.length && sourceSplit[0].includes('ifElse')) { |
| const outputAnchorsIndex = sourceSplit[sourceSplit.length - 1] |
| return outputAnchorsIndex === '0' ? 'true' : 'false' |
| } |
| return '' |
| } |
|
|
| export const isValidConnection = (connection, reactFlowInstance) => { |
| const sourceHandle = connection.sourceHandle |
| const targetHandle = connection.targetHandle |
| const target = connection.target |
|
|
| |
| |
|
|
| const sourceTypes = sourceHandle.split('-')[sourceHandle.split('-').length - 1].split('|') |
| const targetTypes = targetHandle.split('-')[targetHandle.split('-').length - 1].split('|') |
|
|
| if (targetTypes.some((t) => sourceTypes.includes(t))) { |
| let targetNode = reactFlowInstance.getNode(target) |
|
|
| if (!targetNode) { |
| if (!reactFlowInstance.getEdges().find((e) => e.targetHandle === targetHandle)) { |
| return true |
| } |
| } else { |
| const targetNodeInputAnchor = |
| targetNode.data.inputAnchors.find((ancr) => ancr.id === targetHandle) || |
| targetNode.data.inputParams.find((ancr) => ancr.id === targetHandle) |
| if ( |
| (targetNodeInputAnchor && |
| !targetNodeInputAnchor?.list && |
| !reactFlowInstance.getEdges().find((e) => e.targetHandle === targetHandle)) || |
| targetNodeInputAnchor?.list |
| ) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
|
|
| export const convertDateStringToDateObject = (dateString) => { |
| if (dateString === undefined || !dateString) return undefined |
|
|
| const date = moment(dateString) |
| if (!date.isValid) return undefined |
|
|
| |
| return new Date(date.year(), date.month(), date.date(), date.hours(), date.minutes()) |
| } |
|
|
| export const getFileName = (fileBase64) => { |
| let fileNames = [] |
| if (fileBase64.startsWith('[') && fileBase64.endsWith(']')) { |
| const files = JSON.parse(fileBase64) |
| for (const file of files) { |
| const splitDataURI = file.split(',') |
| const filename = splitDataURI[splitDataURI.length - 1].split(':')[1] |
| fileNames.push(filename) |
| } |
| return fileNames.join(', ') |
| } else { |
| const splitDataURI = fileBase64.split(',') |
| const filename = splitDataURI[splitDataURI.length - 1].split(':')[1] |
| return filename |
| } |
| } |
|
|
| export const getFolderName = (base64ArrayStr) => { |
| try { |
| const base64Array = JSON.parse(base64ArrayStr) |
| const filenames = [] |
| for (let i = 0; i < base64Array.length; i += 1) { |
| const fileBase64 = base64Array[i] |
| const splitDataURI = fileBase64.split(',') |
| const filename = splitDataURI[splitDataURI.length - 1].split(':')[1] |
| filenames.push(filename) |
| } |
| return filenames.length ? filenames.join(',') : '' |
| } catch (e) { |
| return '' |
| } |
| } |
|
|
| export const generateExportFlowData = (flowData) => { |
| const nodes = flowData.nodes |
| const edges = flowData.edges |
|
|
| for (let i = 0; i < nodes.length; i += 1) { |
| nodes[i].selected = false |
| const node = nodes[i] |
|
|
| const newNodeData = { |
| id: node.data.id, |
| label: node.data.label, |
| name: node.data.name, |
| type: node.data.type, |
| baseClasses: node.data.baseClasses, |
| category: node.data.category, |
| description: node.data.description, |
| inputParams: node.data.inputParams, |
| inputAnchors: node.data.inputAnchors, |
| inputs: {}, |
| outputAnchors: node.data.outputAnchors, |
| outputs: node.data.outputs, |
| selected: false |
| } |
|
|
| |
| if (node.data.inputs && Object.keys(node.data.inputs).length) { |
| const nodeDataInputs = {} |
| for (const input in node.data.inputs) { |
| const inputParam = node.data.inputParams.find((inp) => inp.name === input) |
| if (inputParam && inputParam.type === 'password') continue |
| if (inputParam && inputParam.type === 'file') continue |
| if (inputParam && inputParam.type === 'folder') continue |
| nodeDataInputs[input] = node.data.inputs[input] |
| } |
| newNodeData.inputs = nodeDataInputs |
| } |
|
|
| nodes[i].data = newNodeData |
| } |
| const exportJson = { |
| nodes, |
| edges |
| } |
| return exportJson |
| } |
|
|
| export const getAvailableNodesForVariable = (nodes, edges, target, targetHandle) => { |
| |
| |
| const parentNodes = [] |
| const inputEdges = edges.filter((edg) => edg.target === target && edg.targetHandle === targetHandle) |
| if (inputEdges && inputEdges.length) { |
| for (let j = 0; j < inputEdges.length; j += 1) { |
| const node = nodes.find((nd) => nd.id === inputEdges[j].source) |
| parentNodes.push(node) |
| } |
| } |
| return parentNodes |
| } |
|
|
| export const rearrangeToolsOrdering = (newValues, sourceNodeId) => { |
| |
| newValues.push(`{{${sourceNodeId}.data.instance}}`) |
|
|
| const sortKey = (item) => { |
| if (item.includes('requestsGet') || item.includes('readFile')) { |
| return 0 |
| } else if (item.includes('requestsPost') || item.includes('writeFile')) { |
| return 1 |
| } else { |
| return 2 |
| } |
| } |
|
|
| newValues.sort((a, b) => sortKey(a) - sortKey(b)) |
| } |
|
|
| export const throttle = (func, limit) => { |
| let lastFunc |
| let lastRan |
|
|
| return (...args) => { |
| if (!lastRan) { |
| func(...args) |
| lastRan = Date.now() |
| } else { |
| clearTimeout(lastFunc) |
| lastFunc = setTimeout(() => { |
| if (Date.now() - lastRan >= limit) { |
| func(...args) |
| lastRan = Date.now() |
| } |
| }, limit - (Date.now() - lastRan)) |
| } |
| } |
| } |
|
|