diff options
Diffstat (limited to 'subprojects/frontend/src/table/RelationGrid.tsx')
-rw-r--r-- | subprojects/frontend/src/table/RelationGrid.tsx | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/subprojects/frontend/src/table/RelationGrid.tsx b/subprojects/frontend/src/table/RelationGrid.tsx new file mode 100644 index 00000000..004982c9 --- /dev/null +++ b/subprojects/frontend/src/table/RelationGrid.tsx | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | import Box from '@mui/material/Box'; | ||
8 | import { | ||
9 | DataGrid, | ||
10 | type GridRenderCellParams, | ||
11 | type GridColDef, | ||
12 | } from '@mui/x-data-grid'; | ||
13 | import { observer } from 'mobx-react-lite'; | ||
14 | import { useMemo } from 'react'; | ||
15 | |||
16 | import type GraphStore from '../graph/GraphStore'; | ||
17 | |||
18 | import TableToolbar from './TableToolbar'; | ||
19 | import ValueRenderer from './ValueRenderer'; | ||
20 | |||
21 | interface Row { | ||
22 | nodes: string[]; | ||
23 | value: string; | ||
24 | } | ||
25 | |||
26 | function RelationGrid({ graph }: { graph: GraphStore }): JSX.Element { | ||
27 | const { | ||
28 | selectedSymbol, | ||
29 | semantics: { nodes, partialInterpretation }, | ||
30 | } = graph; | ||
31 | const symbolName = selectedSymbol?.name; | ||
32 | const arity = selectedSymbol?.arity ?? 0; | ||
33 | |||
34 | const columns = useMemo<GridColDef<Row>[]>(() => { | ||
35 | const defs: GridColDef<Row>[] = []; | ||
36 | for (let i = 0; i < arity; i += 1) { | ||
37 | defs.push({ | ||
38 | field: `n${i}`, | ||
39 | headerName: String(i + 1), | ||
40 | valueGetter: (row) => row.row.nodes[i] ?? '', | ||
41 | flex: 1, | ||
42 | }); | ||
43 | } | ||
44 | defs.push({ | ||
45 | field: 'value', | ||
46 | headerName: 'Value', | ||
47 | flex: 1, | ||
48 | renderCell: ({ value }: GridRenderCellParams<Row, string>) => ( | ||
49 | <ValueRenderer value={value} /> | ||
50 | ), | ||
51 | }); | ||
52 | return defs; | ||
53 | }, [arity]); | ||
54 | |||
55 | const rows = useMemo<Row[]>(() => { | ||
56 | if (symbolName === undefined) { | ||
57 | return []; | ||
58 | } | ||
59 | const interpretation = partialInterpretation[symbolName] ?? []; | ||
60 | return interpretation.map((tuple) => { | ||
61 | const nodeNames: string[] = []; | ||
62 | for (let i = 0; i < arity; i += 1) { | ||
63 | const index = tuple[i]; | ||
64 | if (typeof index === 'number') { | ||
65 | const node = nodes[index]; | ||
66 | if (node !== undefined) { | ||
67 | nodeNames.push(node.name); | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | return { | ||
72 | nodes: nodeNames, | ||
73 | value: String(tuple[arity]), | ||
74 | }; | ||
75 | }); | ||
76 | }, [arity, nodes, partialInterpretation, symbolName]); | ||
77 | |||
78 | return ( | ||
79 | <Box | ||
80 | width="100%" | ||
81 | height="100%" | ||
82 | p={1} | ||
83 | sx={(theme) => ({ | ||
84 | '.MuiDataGrid-withBorderColor': { | ||
85 | borderColor: | ||
86 | theme.palette.mode === 'dark' | ||
87 | ? theme.palette.divider | ||
88 | : theme.palette.outer.border, | ||
89 | }, | ||
90 | })} | ||
91 | > | ||
92 | <DataGrid | ||
93 | slots={{ toolbar: TableToolbar }} | ||
94 | slotProps={{ | ||
95 | toolbar: { | ||
96 | graph, | ||
97 | }, | ||
98 | }} | ||
99 | density="compact" | ||
100 | rowSelection={false} | ||
101 | columns={columns} | ||
102 | rows={rows} | ||
103 | getRowId={(row) => row.nodes.join(',')} | ||
104 | /> | ||
105 | </Box> | ||
106 | ); | ||
107 | } | ||
108 | |||
109 | export default observer(RelationGrid); | ||