Skip to content

Commit 430a61a

Browse files
committed
ellipsis long labels, increase node width, add comment on why it is hard to support auto sized nodes
Signed-off-by: Teo Koon Peng <[email protected]>
1 parent eb5fa9d commit 430a61a

File tree

7 files changed

+35
-45
lines changed

7 files changed

+35
-45
lines changed

diagram-editor/frontend/add-operation.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ function createNodeChange(
111111
data: {
112112
namespace: joinNamespaces(namespace, scopeId),
113113
},
114-
width: LAYOUT_OPTIONS.nodeWidth,
115-
height: LAYOUT_OPTIONS.nodeHeight,
116114
parentId: scopeId,
117115
},
118116
},
@@ -128,8 +126,6 @@ function createNodeChange(
128126
data: {
129127
namespace: joinNamespaces(namespace, scopeId),
130128
},
131-
width: LAYOUT_OPTIONS.nodeWidth,
132-
height: LAYOUT_OPTIONS.nodeHeight,
133129
parentId: scopeId,
134130
},
135131
},
@@ -174,8 +170,7 @@ function createNodeChange(
174170
opId: uuidv4(),
175171
op,
176172
},
177-
width: LAYOUT_OPTIONS.nodeWidth,
178-
height: LAYOUT_OPTIONS.nodeHeight,
173+
179174
parentId,
180175
},
181176
},

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

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Button, type ButtonProps, Paper } from '@mui/material';
1+
import { Box, Button, type ButtonProps, Paper } from '@mui/material';
22
import { Handle, type NodeProps, Position } from '@xyflow/react';
33
import React from 'react';
4+
import { LAYOUT_OPTIONS } from '../utils/layout';
45

56
export interface BaseNodeProps extends NodeProps {
67
color?: ButtonProps['color'];
@@ -18,8 +19,6 @@ function BaseNode({
1819
selected,
1920
sourcePosition = Position.Bottom,
2021
targetPosition = Position.Top,
21-
width,
22-
height,
2322
}: BaseNodeProps) {
2423
const icon =
2524
typeof materialIconOrSymbol === 'string' ? (
@@ -28,7 +27,7 @@ function BaseNode({
2827
materialIconOrSymbol
2928
);
3029
return (
31-
<Paper sx={{ minWidth: 100 }}>
30+
<Paper>
3231
{(variant === 'input' || variant === 'inputOutput') && (
3332
<Handle
3433
type="target"
@@ -37,17 +36,28 @@ function BaseNode({
3736
/>
3837
)}
3938
<Button
39+
title={label}
4040
color={color}
4141
fullWidth
4242
startIcon={icon}
4343
variant={selected ? 'contained' : 'outlined'}
4444
sx={{
4545
textTransform: 'none',
46-
width,
47-
height,
46+
width: LAYOUT_OPTIONS.nodeWidth,
47+
height: LAYOUT_OPTIONS.nodeHeight,
4848
}}
4949
>
50-
{label}
50+
<Box
51+
component="span"
52+
sx={{
53+
minWidth: 0,
54+
overflow: 'hidden',
55+
textOverflow: 'ellipsis',
56+
whiteSpace: 'nowrap',
57+
}}
58+
>
59+
{label}
60+
</Box>
5161
</Button>
5262
{(variant === 'output' || variant === 'inputOutput') && (
5363
<Handle

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { Button, Paper } from '@mui/material';
22
import type { NodeProps } from '@xyflow/react';
33
import { Handle, Position } from '@xyflow/react';
4+
import { LAYOUT_OPTIONS } from '../utils/layout';
45
import type { BuiltinNode } from '.';
56

67
function StartNode({
78
isConnectable,
89
sourcePosition = Position.Bottom,
9-
width,
10-
height,
1110
}: NodeProps<BuiltinNode>) {
1211
return (
1312
<Paper sx={{ minWidth: 100 }}>
@@ -16,8 +15,8 @@ function StartNode({
1615
variant="outlined"
1716
disabled
1817
sx={{
19-
width,
20-
height,
18+
width: LAYOUT_OPTIONS.nodeWidth,
19+
height: LAYOUT_OPTIONS.nodeHeight,
2120
}}
2221
>
2322
Start

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { Button, Paper } from '@mui/material';
22
import { Handle, type NodeProps, Position } from '@xyflow/react';
3+
import { LAYOUT_OPTIONS } from '../utils/layout';
34
import type { BuiltinNode } from '.';
45

56
function TerminateNode({
67
isConnectable,
78
targetPosition = Position.Top,
8-
width,
9-
height,
109
}: NodeProps<BuiltinNode>) {
1110
return (
1211
<Paper>
@@ -20,8 +19,8 @@ function TerminateNode({
2019
variant="outlined"
2120
disabled
2221
sx={{
23-
width,
24-
height,
22+
width: LAYOUT_OPTIONS.nodeWidth,
23+
height: LAYOUT_OPTIONS.nodeHeight,
2524
}}
2625
>
2726
Terminate

diagram-editor/frontend/utils/auto-layout.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ export function autoLayout(
2424
const dagreGraph = new dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
2525
dagreGraph.setGraph({
2626
rankdir: 'TB',
27-
marginx: options.nodeWidth / 2,
28-
marginy: options.nodeHeight / 2,
27+
ranksep: options.nodeHeight,
2928
});
3029

3130
const scopeChildrens: Record<string, DiagramEditorNode[]> = {};
@@ -43,6 +42,15 @@ export function autoLayout(
4342
// exclude scope node from auto layout
4443
if (!isScopeNode(node)) {
4544
dagreGraph.setNode(node.id, {
45+
// dagre requires the node dimensions to be known, the easy solution is to only use
46+
// fixed size nodes. The complex alternative is to delay auto layout until ReactFlow
47+
// finishes measuring the nodes, this is complex because
48+
// 1. There is no hook for when ReactFlow finishes measurements
49+
// 2. ReactFlow does not delay updating the DOM until the measurements are complete.
50+
// 2.1. This means that when loading a new diagram, there will be a short period where the layout is not yet computed.
51+
// 3. Measurements of a node may change multiple times before it "stabilizes".
52+
// 3.1. This means that even if all nodes have measurements, they may not be final measurements.
53+
// If the measurements change after the layout is computed, the layout will be wrong.
4654
width: options.nodeWidth,
4755
height: options.nodeHeight,
4856
});

diagram-editor/frontend/utils/layout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface LayoutOptions {
1010
}
1111

1212
export const LAYOUT_OPTIONS: LayoutOptions = {
13-
nodeWidth: 125,
13+
nodeWidth: 200,
1414
nodeHeight: 50,
1515
scopePadding: {
1616
leftRight: 75,

diagram-editor/frontend/utils/load-diagram.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
import type { Diagram, DiagramOperation, SectionTemplate } from '../types/api';
1111
import { getSchema } from './ajv';
1212
import { exportDiagram } from './export-diagram';
13-
import { LAYOUT_OPTIONS } from './layout';
1413
import { joinNamespaces, ROOT_NAMESPACE } from './namespace';
1514
import { buildEdges, isBuiltin } from './operation';
1615

@@ -47,17 +46,13 @@ export function loadEmpty(): Graph {
4746
position: { x: 0, y: 0 },
4847
selectable: false,
4948
data: { namespace: ROOT_NAMESPACE },
50-
width: LAYOUT_OPTIONS.nodeWidth,
51-
height: LAYOUT_OPTIONS.nodeHeight,
5249
},
5350
{
5451
id: joinNamespaces(ROOT_NAMESPACE, TERMINATE_ID),
5552
type: 'terminate',
5653
position: { x: 0, y: 400 },
5754
selectable: false,
5855
data: { namespace: ROOT_NAMESPACE },
59-
width: LAYOUT_OPTIONS.nodeWidth,
60-
height: LAYOUT_OPTIONS.nodeHeight,
6156
},
6257
],
6358
edges: [],
@@ -103,17 +98,13 @@ function buildGraph(diagram: Diagram): Graph {
10398
position: { x: 0, y: 0 },
10499
data: { namespace: joinNamespaces(namespace, opId) },
105100
parentId: id,
106-
width: LAYOUT_OPTIONS.nodeWidth,
107-
height: LAYOUT_OPTIONS.nodeHeight,
108101
});
109102
nodes.push({
110103
id: joinNamespaces(namespace, opId, TERMINATE_ID),
111104
type: 'terminate',
112105
position: { x: 0, y: 0 },
113106
data: { namespace: joinNamespaces(namespace, opId) },
114107
parentId: id,
115-
width: LAYOUT_OPTIONS.nodeWidth,
116-
height: LAYOUT_OPTIONS.nodeHeight,
117108
});
118109

119110
for (const [innerOpId, innerOp] of Object.entries(op.ops)) {
@@ -131,8 +122,6 @@ function buildGraph(diagram: Diagram): Graph {
131122
position: { x: 0, y: 0 },
132123
data: { namespace, opId, op },
133124
parentId,
134-
width: LAYOUT_OPTIONS.nodeWidth,
135-
height: LAYOUT_OPTIONS.nodeHeight,
136125
});
137126
}
138127
}
@@ -185,8 +174,6 @@ export function loadTemplate(template: SectionTemplate): Graph {
185174
remappedId: input,
186175
targetId: input,
187176
},
188-
width: LAYOUT_OPTIONS.nodeWidth,
189-
height: LAYOUT_OPTIONS.nodeHeight,
190177
});
191178
}
192179
} else {
@@ -200,8 +187,6 @@ export function loadTemplate(template: SectionTemplate): Graph {
200187
remappedId,
201188
targetId,
202189
},
203-
width: LAYOUT_OPTIONS.nodeWidth,
204-
height: LAYOUT_OPTIONS.nodeHeight,
205190
});
206191
}
207192
}
@@ -219,8 +204,6 @@ export function loadTemplate(template: SectionTemplate): Graph {
219204
remappedId: buffer,
220205
targetId: buffer,
221206
},
222-
width: LAYOUT_OPTIONS.nodeWidth,
223-
height: LAYOUT_OPTIONS.nodeHeight,
224207
});
225208
}
226209
} else {
@@ -234,8 +217,6 @@ export function loadTemplate(template: SectionTemplate): Graph {
234217
remappedId,
235218
targetId,
236219
},
237-
width: LAYOUT_OPTIONS.nodeWidth,
238-
height: LAYOUT_OPTIONS.nodeHeight,
239220
});
240221
}
241222
}
@@ -252,8 +233,6 @@ export function loadTemplate(template: SectionTemplate): Graph {
252233
remappedId: output,
253234
targetId: output,
254235
},
255-
width: LAYOUT_OPTIONS.nodeWidth,
256-
height: LAYOUT_OPTIONS.nodeHeight,
257236
});
258237
}
259238
}

0 commit comments

Comments
 (0)