Skip to content

Commit

Permalink
canvas handler suspense ;2A
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardoperra committed Oct 30, 2024
1 parent 929c3db commit a11d1a5
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 96 deletions.
135 changes: 71 additions & 64 deletions packages/app/src/components/Editor/Canvas/Canvas.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {EditorStore} from '#editor-store/editor.store';
import type {WorkflowStructureJob} from '#editor-store/editor.types';
import type {ElkExtendedEdge, ElkNode} from 'elkjs';
import {batch, createEffect, createSignal, onCleanup, onMount} from 'solid-js';
import {createResource, onCleanup, onMount, Suspense, untrack} from 'solid-js';
import {provideState} from 'statebuilder';
import {FlowRenderer} from '../Flow/engine/FlowRenderer';
import type {FlowConnection, FlowNodeMap} from '../Flow/engine/types';
Expand All @@ -24,6 +24,8 @@ function createNodes(jobs: WorkflowStructureJob[]) {
return acc;
}, {} as FlowNodeMap);

console.log('my jobs', jobs);

return import('elkjs').then(({default: ELK}) => {
const graph: ElkNode = {
id: 'root',
Expand Down Expand Up @@ -77,86 +79,91 @@ function createNodes(jobs: WorkflowStructureJob[]) {
return acc;
}, [] as ElkExtendedEdge[]),
};
return new ELK().layout(graph).then(layout => {
layout.children?.forEach(child => {
const node = mappedNodes[child.id];
if (node) {
node.position.x = child.x ?? 0;
node.position.y = child.y ?? 0;
}
});
return new ELK()
.layout(graph)
.then(layout => {
layout.children?.forEach(child => {
const node = mappedNodes[child.id];
if (node) {
node.position.x = child.x ?? 0;
node.position.y = child.y ?? 0;
}
});

const edges = jobs.reduce((acc, job) => {
const jobEdge: FlowConnection[] = (job.needs ?? []).reduce(
(acc, need) => {
const cJob = jobs.find(n => n.id.toString() === need.toString());
if (!cJob) {
return acc;
}
return [
...acc,
{
target: {
nodeId: job.id,
connectorId: `${job.id}-output`,
connectorType: 'output',
},
source: {
nodeId: need,
connectorId: `${need}-input`,
connectorType: 'input',
},
} satisfies FlowConnection,
];
},
[] as FlowConnection[],
);
const edges = jobs.reduce((acc, job) => {
const jobEdge: FlowConnection[] = (job.needs ?? []).reduce(
(acc, need) => {
const cJob = jobs.find(n => n.id.toString() === need.toString());
if (!cJob) {
return acc;
}
return [
...acc,
{
target: {
nodeId: job.id,
connectorId: `${job.id}-output`,
connectorType: 'output',
},
source: {
nodeId: need,
connectorId: `${need}-input`,
connectorType: 'input',
},
} satisfies FlowConnection,
];
},
[] as FlowConnection[],
);

return [...acc, ...jobEdge];
}, [] as FlowConnection[]);

return [...acc, ...jobEdge];
}, [] as FlowConnection[]);
console.log(mappedNodes);

return {
size: {
width: layout.width!,
height: layout.height!,
},
mappedNodes,
edges,
};
});
return {
size: {
width: layout.width!,
height: layout.height!,
},
mappedNodes,
edges,
};
})
.catch(console.error);
});
}

export function Canvas() {
export default function Canvas() {
const editor = provideState(EditorStore);

const [mappedNodes, setMappedNodes] = createSignal<FlowNodeMap>({});
const [connections, setConnections] = createSignal<FlowConnection[]>([]);
const [size, setSize] = createSignal({width: 0, height: 0});
const [data, {refetch}] = createResource(
() => editor.initialized(),
async () => {
const result = await createNodes(
untrack(() => editor().structure.jobs ?? []),
);
return result;
},
);

function updateNodes() {
createNodes(editor().structure.jobs).then(({size, edges, mappedNodes}) => {
batch(() => {
setSize(size);
setMappedNodes(mappedNodes);
setConnections(edges);
});
});
}
const mappedNodes = () => data.latest?.mappedNodes ?? {};
const connections = () => data.latest?.edges ?? [];
const size = () => data.latest?.size ?? {width: 0, height: 0};

onMount(() => {
const {unsubscribe} = editor
.watchCommand([editor.commands.updateJobNeeds])
.watchCommand([
editor.commands.updateJobNeeds,
editor.commands.addNewJob,
editor.commands.deleteJob,
])
.subscribe(() => {
updateNodes();
refetch();
});
onCleanup(() => unsubscribe());
});

createEffect(() => {
updateNodes();
});

return (
<div
class={styles.canvasContainer}
Expand Down
57 changes: 27 additions & 30 deletions packages/app/src/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@ import * as fallbackStyles from '~/ui/components/Fallback.css';
import {EditorHeader} from './Header/Header';
import {provideState} from 'statebuilder';
import {EditorUiStore} from './store/ui.store';
import {
createEffect,
For,
lazy,
Match,
Show,
Suspense,
Switch,
useContext,
} from 'solid-js';
import {For, lazy, Match, Show, Suspense, Switch, useContext} from 'solid-js';
import {YamlEditor} from './YamlEditor/YamlEditor';
import {EditorStatusBar} from './StatusBar/StatusBar';
import Resizable from '@corvu/resizable';
Expand All @@ -25,11 +16,10 @@ import {YamlMergeView} from './YamlEditor/MergeView';
import {DiagnosticPanel} from './DiagnosticPanel/DiagnosticPanel';
import {EditorRepositoryHeaderName} from './Header/RepositoryHeaderName';
import {EditorContext} from './editor.context';
import {OverlayLoader} from '~/ui/components/Loader/Loader';

const Canvas = lazy(() =>
Promise.all([import('elkjs'), import('./Canvas/Canvas')]).then(([, m]) => ({
default: m.Canvas,
})),
Promise.all([import('elkjs'), import('./Canvas/Canvas')]).then(([, m]) => m),
);

export interface EditorProps {
Expand Down Expand Up @@ -127,8 +117,11 @@ export function Editor(props: EditorProps) {
position={'left'}
/>

<Resizable.Panel initialSize={0.58}>
<Suspense>
<Resizable.Panel
initialSize={0.58}
style={{position: 'relative'}}
>
<Suspense fallback={<OverlayLoader />}>
<Canvas />
</Suspense>
</Resizable.Panel>
Expand All @@ -153,18 +146,20 @@ export function Editor(props: EditorProps) {
{rightPanel => (
<>
<EditorSidebar position={'right'}>
<Switch>
<Match
when={rightPanel() === 'properties'}
>
<Show
fallback={<PropertiesPanelEditor />}
when={editor.selectedJob()}
<Suspense>
<Switch>
<Match
when={rightPanel() === 'properties'}
>
<JobPanelEditor />
</Show>
</Match>
</Switch>
<Show
fallback={<PropertiesPanelEditor />}
when={editor.selectedJob()}
>
<JobPanelEditor />
</Show>
</Match>
</Switch>
</Suspense>
</EditorSidebar>
</>
)}
Expand All @@ -187,22 +182,24 @@ export function Editor(props: EditorProps) {
collapsible
class={styles.resizablePanel}
>
<DiagnosticPanel />
<Suspense>
<DiagnosticPanel />
</Suspense>
</Resizable.Panel>
</>
);
}}
</Resizable>
</div>
<EditorStatusBar />
<Suspense>
<EditorStatusBar />
</Suspense>
</div>
);
}

function YamlEditorFallback() {
const editor = useContext(EditorContext);

createEffect(() => console.log(editor?.source.split('\n')));
return (
<div
style={{
Expand Down
7 changes: 5 additions & 2 deletions packages/app/src/ui/components/Loader/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ export function Loader() {
return <span class={styles.loader}></span>;
}

export function OverlayLoader() {
export interface OverlayLoaderProps {
relative?: boolean;
}
export function OverlayLoader(props: OverlayLoaderProps) {
return (
<div class={styles.overlay}>
<div class={styles.overlay} data-relative={props.relative}>
<Loader />
</div>
);
Expand Down

0 comments on commit a11d1a5

Please sign in to comment.