// imports import dynamic from 'next/dynamic'; import { ErrorBoundary } from 'react-error-boundary'; import React, { useMemo } from 'react'; // locals import Image from '../components/Image'; import Input from '../components/Input'; import Button from '../components/Button'; import Loading from '../components/Loading'; import NodeBase from '../components/Node/Base'; import ApiSignal from './Api'; import NodeChoose from '../components/Node/Choose'; import ButtonIcon from '../components/Button/Icon'; import Signal, { effect } from '../signal'; import { current as TeamSignal } from './Teams'; // components import NodeComponents from '../components/Node/Components/index'; // dynamic editor const Editor = dynamic(() => import('@monaco-editor/react'), { loading: () =>
, }); // refreshing export let refreshing = false; // uuid import shortid from 'short-unique-id'; const uid = new shortid({ length : 10, dictionary : 'hex', }); // create signal const NodesSignal = new Signal.State({}); export const ComponentsSignal = new Signal.State({}); // refresh export const refresh = async () => { // refreshing if (refreshing) return; // refreshing refreshing = true; // try try { // nodes const { nodes } = await ApiSignal.get().Node.list({ team : TeamSignal.get()?.id, limit : 1000, }); // set nodes NodesSignal.set(nodes.reduce((accum, node) => { // set to accum accum[node.id] = node; // return accum return accum; }, {})); // set components signal ComponentsSignal.set([ ...(Object.keys(NodesSignal.get()) || []), 'choose', ].reduce((accum, key) => { // if choose if (key === 'choose') { // set accum accum[key] = (props = {}) => { // choose node return ( ); }; } else { // set accum accum[key] = (props = {}) => { // item const inputs = Object.values([ ...(NodesSignal.get()[key].inputs || []), ...(props.data?.inputs || []), ].reduce((accum, input) => { // set accum accum[input.id] = input; // return accum return accum; }, {})); const outputs = Object.values([ ...(NodesSignal.get()[key].outputs || []), ...(props.data?.outputs || []), ].reduce((accum, output) => { // set accum accum[output.id] = output; // return accum return accum; }, {})); // string const ChildComponent = useMemo(() => { // component const actualComponent = `(props) => { const { inputs, outputs, onInputs, onOutputs, variant } = props; const { uid, Editor, Image, Input, Button, ButtonIcon, Loading, item, node, spec, output, input, onSpec } = props; const { ${Object.keys(NodeComponents).join(', ')} } = props.Components; ${NodesSignal.get()[key].display} }`; // try/catch try { // create react element from string return new Function('React', 'return ' + actualComponent)(React); } catch (e) { // log console.log(e); // return error return () =>
Error
; } }, [NodesSignal.get()[key].display]); // element const NodeElement = useMemo(() => { // return new component return (renderProps = {}) => { // return jsx return ( error
}> { // message if (renderProps.variant === 'message') return; // check diff if (JSON.stringify(renderProps.data?.spec?.[key] || '') === JSON.stringify(value)) return; // on change renderProps.data.onChange('spec', { ...(renderProps.data?.spec || {}), [key] : value, }); }} onInputs={(newInputs) => { // message if (renderProps.variant === 'message') return; // on change renderProps.data.onChange('inputs', [...newInputs]); }} onOutputs={(newOutputs) => { // message if (renderProps.variant === 'message') return; // on change renderProps.data.onChange('outputs', [...newOutputs]); }} Components={NodeComponents} // other elements uid={uid} Input={Input} Image={Image} Editor={Editor} Button={Button} Loading={Loading} ButtonIcon={ButtonIcon} /> ); }; }, [props.id]); // choose node return ( ); }; } // return accum return accum; }, {})); } catch (e) { // log console.log(e); } finally { // refreshing refreshing = false; } }; // create effect effect(() => { // check user id if (!ApiSignal.get()) return; if (!TeamSignal.get()?.id) return; if (typeof window === 'undefined') return; // refresh refresh(); }); // export default export default NodesSignal;