Skip to content

Commit 403bd70

Browse files
committed
successfully export template
Signed-off-by: Teo Koon Peng <[email protected]>
1 parent 95b2969 commit 403bd70

File tree

7 files changed

+274
-260
lines changed

7 files changed

+274
-260
lines changed

diagram-editor/frontend/add-operation.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
type XYPosition,
66
} from '@xyflow/react';
77
import React from 'react';
8+
import { v4 as uuidv4 } from 'uuid';
89
import { EditorMode, useEditorMode } from './editor-mode';
910
import type { DiagramEditorNode } from './nodes';
1011
import {
@@ -54,7 +55,7 @@ function createSectionInputChange(
5455
): NodeAddChange<SectionInputNode> {
5556
return {
5657
type: 'add',
57-
item: createSectionInputNode(targetId, position),
58+
item: createSectionInputNode(targetId, targetId, position),
5859
};
5960
}
6061

@@ -74,7 +75,7 @@ function createSectionBufferChange(
7475
): NodeAddChange<SectionBufferNode> {
7576
return {
7677
type: 'add',
77-
item: createSectionBufferNode(targetId, position),
78+
item: createSectionBufferNode(targetId, targetId, position),
7879
};
7980
}
8081

@@ -85,15 +86,25 @@ function createNodeChange(
8586
op: DiagramOperation,
8687
): NodeAddChange<DiagramEditorNode>[] {
8788
if (op.type === 'scope') {
88-
return createScopeNode(namespace, parentId, newNodePosition, op).map(
89-
(node) => ({ type: 'add', item: node }),
90-
);
89+
return createScopeNode(
90+
namespace,
91+
parentId,
92+
newNodePosition,
93+
op,
94+
uuidv4(),
95+
).map((node) => ({ type: 'add', item: node }));
9196
}
9297

9398
return [
9499
{
95100
type: 'add',
96-
item: createOperationNode(namespace, parentId, newNodePosition, op),
101+
item: createOperationNode(
102+
namespace,
103+
parentId,
104+
newNodePosition,
105+
op,
106+
uuidv4(),
107+
),
97108
},
98109
];
99110
}

diagram-editor/frontend/node-manager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ export class NodeManager {
117117
if (isOperationNode(target)) {
118118
return target.data.opId;
119119
}
120+
if (target.type === 'sectionOutput') {
121+
return target.data.outputId;
122+
}
120123
throw new Error('unknown node type');
121124
}
122125
// TODO: For section edges, return a `{ [target.data.opId]: edge.data.input }`

diagram-editor/frontend/nodes/section-node.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function SectionInputNodeComp(props: NodeProps<SectionInputNode>) {
6060
{...props}
6161
color="secondary"
6262
icon={<SectionInputIcon />}
63-
label={props.data.remappedId}
63+
label="Section Input"
6464
variant="output"
6565
/>
6666
);
@@ -72,7 +72,7 @@ export function SectionOutputNodeComp(props: NodeProps<SectionOutputNode>) {
7272
{...props}
7373
color="secondary"
7474
icon={<SectionOutputIcon />}
75-
label="Output"
75+
label="Section Output"
7676
variant="input"
7777
/>
7878
);
@@ -84,7 +84,7 @@ export function SectionBufferNodeComp(props: NodeProps<SectionBufferNode>) {
8484
{...props}
8585
color="secondary"
8686
icon={<SectionBufferIcon />}
87-
label={props.data.remappedId}
87+
label="Section Buffer"
8888
variant="output"
8989
/>
9090
);

diagram-editor/frontend/utils/create-node.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,57 @@
11
import type { XYPosition } from '@xyflow/react';
22
import { v4 as uuidv4 } from 'uuid';
3-
import type {
4-
DiagramEditorNode,
5-
OperationNode,
6-
SectionBufferNode,
7-
SectionInputNode,
8-
SectionOutputNode,
3+
import {
4+
type DiagramEditorNode,
5+
type OperationNode,
6+
type SectionBufferNode,
7+
type SectionInputNode,
8+
type SectionOutputNode,
9+
START_ID,
10+
TERMINATE_ID,
911
} from '../nodes';
10-
import type { DiagramOperation } from '../types/api';
12+
import type { DiagramOperation, NextOperation } from '../types/api';
1113
import { calculateScopeBounds, LAYOUT_OPTIONS } from './layout';
1214
import { joinNamespaces } from './namespace';
1315

16+
export function createStartNode(
17+
namespace: string,
18+
position: XYPosition,
19+
): DiagramEditorNode {
20+
return {
21+
id: joinNamespaces(namespace, START_ID),
22+
type: 'start',
23+
position,
24+
selectable: false,
25+
data: { namespace },
26+
};
27+
}
28+
29+
export function createTerminateNode(
30+
namespace: string,
31+
position: XYPosition,
32+
): DiagramEditorNode {
33+
return {
34+
id: joinNamespaces(namespace, TERMINATE_ID),
35+
type: 'terminate',
36+
position,
37+
selectable: false,
38+
data: { namespace },
39+
};
40+
}
41+
1442
/**
1543
* Create a section input node. For simplicity, remapping the input is not supported, `targetId`
1644
* must point to the id of an operation in the template.
1745
*/
1846
export function createSectionInputNode(
19-
targetId: string,
47+
remappedId: string,
48+
targetId: NextOperation,
2049
position: XYPosition,
2150
): SectionInputNode {
2251
return {
2352
id: uuidv4(),
2453
type: 'sectionInput',
25-
data: { remappedId: targetId, targetId },
54+
data: { remappedId, targetId },
2655
position,
2756
};
2857
}
@@ -44,13 +73,14 @@ export function createSectionOutputNode(
4473
* must point to the id of a `buffer` operation in the template.
4574
*/
4675
export function createSectionBufferNode(
47-
targetId: string,
76+
remappedId: string,
77+
targetId: NextOperation,
4878
position: XYPosition,
4979
): SectionBufferNode {
5080
return {
5181
id: uuidv4(),
5282
type: 'sectionBuffer',
53-
data: { remappedId: targetId, targetId },
83+
data: { remappedId, targetId },
5484
position,
5585
};
5686
}
@@ -60,14 +90,15 @@ export function createOperationNode(
6090
parentId: string | undefined,
6191
position: XYPosition,
6292
op: Exclude<DiagramOperation, { type: 'scope' }>,
93+
opId: string,
6394
): OperationNode {
6495
return {
6596
id: uuidv4(),
6697
type: op.type,
6798
position,
6899
data: {
69100
namespace,
70-
opId: uuidv4(),
101+
opId,
71102
op,
72103
},
73104
...(parentId && { parentId }),
@@ -79,11 +110,12 @@ export function createScopeNode(
79110
parentId: string | undefined,
80111
position: XYPosition,
81112
op: DiagramOperation & { type: 'scope' },
82-
): DiagramEditorNode[] {
113+
opId: string,
114+
): [OperationNode<'scope'>, ...DiagramEditorNode[]] {
83115
const scopeId = uuidv4();
84116
const children: DiagramEditorNode[] = [
85117
{
86-
id: uuidv4(),
118+
id: joinNamespaces(namespace, opId, START_ID),
87119
type: 'start',
88120
position: {
89121
x: LAYOUT_OPTIONS.scopePadding.leftRight,
@@ -95,7 +127,7 @@ export function createScopeNode(
95127
parentId: scopeId,
96128
},
97129
{
98-
id: uuidv4(),
130+
id: joinNamespaces(namespace, opId, TERMINATE_ID),
99131
type: 'terminate',
100132
position: {
101133
x: LAYOUT_OPTIONS.scopePadding.leftRight,
@@ -120,7 +152,7 @@ export function createScopeNode(
120152
},
121153
data: {
122154
namespace,
123-
opId: uuidv4(),
155+
opId,
124156
op,
125157
},
126158
width: scopeBounds.width,

diagram-editor/frontend/utils/export-diagram.test.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import { v4 as uuidv4 } from 'uuid';
2+
import type { DiagramEditorEdge } from '../edges';
13
import { NodeManager } from '../node-manager';
2-
import { START_ID } from '../nodes';
4+
import { type DiagramEditorNode, START_ID } from '../nodes';
35
import {
46
createOperationNode,
57
createSectionBufferNode,
@@ -51,34 +53,63 @@ test('export diagram with scope', () => {
5153
});
5254

5355
test('export diagram with templates', () => {
54-
const nodes = [
55-
createSectionInputNode('test_input', { x: 0, y: 0 }),
56+
const nodes: DiagramEditorNode[] = [
57+
createSectionInputNode('test_input', { builti: 'dispose' }, { x: 0, y: 0 }),
5658
createSectionOutputNode('test_output', { x: 0, y: 0 }),
57-
createSectionBufferNode('test_buffer', { x: 0, y: 0 }),
59+
createSectionBufferNode(
60+
'test_buffer',
61+
{ builtin: 'dispose' },
62+
{ x: 0, y: 0 },
63+
),
5864
createOperationNode(
5965
ROOT_NAMESPACE,
6066
undefined,
6167
{ x: 0, y: 0 },
62-
{ type: 'node', builder: 'test', next: 'test_output' },
68+
{ type: 'node', builder: 'test_builder', next: { builtin: 'dispose' } },
69+
'test_op_node',
6370
),
6471
createOperationNode(
6572
ROOT_NAMESPACE,
6673
undefined,
6774
{ x: 0, y: 0 },
6875
{ type: 'buffer' },
76+
'test_op_buffer',
6977
),
7078
];
71-
const template = exportTemplate(new NodeManager(nodes), []);
79+
const edges: DiagramEditorEdge[] = [
80+
{
81+
id: uuidv4(),
82+
type: 'default',
83+
source: nodes[0].id,
84+
target: nodes[3].id,
85+
data: {},
86+
},
87+
{
88+
id: uuidv4(),
89+
type: 'default',
90+
source: nodes[2].id,
91+
target: nodes[4].id,
92+
data: {},
93+
},
94+
{
95+
id: uuidv4(),
96+
type: 'default',
97+
source: nodes[3].id,
98+
target: nodes[1].id,
99+
data: {},
100+
},
101+
];
102+
const template = exportTemplate(new NodeManager(nodes), edges);
72103

73104
if (typeof template.inputs !== 'object' || Array.isArray(template.inputs)) {
74105
throw new Error('expected template inputs to be a mapping');
75106
}
76-
expect(template.inputs.test_input).toBe('test_input');
107+
expect(template.inputs.test_input).toBe('test_op_node');
77108

78109
expect(template.outputs?.[0]).toBe('test_output');
79110

80111
if (typeof template.buffers !== 'object' || Array.isArray(template.buffers)) {
81112
throw new Error('expected template buffers to be a mapping');
82113
}
83-
expect(template.buffers.test_buffer).toBe('test_buffer');
114+
expect(template.buffers.test_buffer).toBe('test_op_buffer');
84115
});

0 commit comments

Comments
 (0)