Skip to content

Commit 34cd566

Browse files
Circuit table hierarchical and flat list views (#354)
* Removed the component of search bar and filter options * Created the switch component * Added the flatten hierarchical logic --------- Co-authored-by: Loris Olivier <53363974+loris-maru@users.noreply.github.com>
1 parent eb7f6b3 commit 34cd566

File tree

8 files changed

+185
-22
lines changed

8 files changed

+185
-22
lines changed

src/components/explore-section/Circuit/global/Columns.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const columns = (
2020
calculateSubcircuitsForParent: (row: CircuitSchemaProps) => number,
2121
handleExpandRow: (row: CircuitSchemaProps, index: number) => void,
2222
isCircuitDetailPage: boolean,
23-
handleOpenDownloadModal: (record: CircuitSchemaProps) => void
23+
handleOpenDownloadModal: (record: CircuitSchemaProps) => void,
24+
toggle: 'hierarchical' | 'flat'
2425
): ResizableColumnType[] => {
2526
return [
2627
{
@@ -75,7 +76,7 @@ const columns = (
7576
disabled={!record.hasSubcircuits}
7677
>
7778
<div className="relative mr-6 block whitespace-nowrap">{subcircuitCount}</div>
78-
{record.subcircuits?.length !== 0 && (
79+
{record.subcircuits?.length !== 0 && toggle === 'hierarchical' && (
7980
<ChevronRight
8081
fill="#003A8C"
8182
className={classNames(
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { FlatListViewIcon, HierarchicalViewIcon } from '@/components/icons';
2+
import { classNames } from '@/util/utils';
3+
4+
export default function ViewToggle({
5+
toggle,
6+
setToggle,
7+
}: {
8+
toggle: 'hierarchical' | 'flat';
9+
setToggle: (toggle: 'hierarchical' | 'flat') => void;
10+
}) {
11+
const handleViewChange = () => {
12+
const newView = toggle === 'hierarchical' ? 'flat' : 'hierarchical';
13+
setToggle(newView);
14+
};
15+
16+
return (
17+
<div className="relative flex flex-row items-center gap-x-4">
18+
<div className="text-base font-medium text-primary-9">View:</div>
19+
<div className="relative flex flex-row items-center gap-x-2">
20+
<div>
21+
<HierarchicalViewIcon
22+
iconColor={toggle === 'hierarchical' ? '#002766' : '#AAA'}
23+
className="h-4 w-4"
24+
/>
25+
</div>
26+
<button
27+
type="button"
28+
className="relative h-6 w-12 rounded-xl border border-solid border-gray-200"
29+
onClick={handleViewChange}
30+
aria-label="Toggle view"
31+
id="toggle-view"
32+
>
33+
<div
34+
className={classNames(
35+
'absolute top-px h-5 w-5 rounded-full bg-primary-9 transition-transform duration-300 ease-in-out',
36+
toggle === 'hierarchical' ? 'translate-x-[2px]' : 'translate-x-[21px]'
37+
)}
38+
/>
39+
</button>
40+
<div>
41+
<FlatListViewIcon
42+
iconColor={toggle === 'flat' ? '#002766' : '#AAA'}
43+
className="h-4 w-4"
44+
/>
45+
</div>
46+
</div>
47+
</div>
48+
);
49+
}

src/components/explore-section/Circuit/global/circuit-table.tsx

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import { Table } from 'antd';
22
import { usePathname } from 'next/navigation';
3-
import { Key, useCallback, useEffect, useState } from 'react';
3+
import { Key, useCallback, useEffect, useMemo, useState } from 'react';
44
import { CircuitSchemaProps, NumericFilterOptions } from '../type';
55
import calculateSubcircuitsForParent from '../utils/calculate-subcircuits-for-parent';
66
import { circuitMatchFilter } from '../utils/circuits-match-filter';
77
import collectExpandableKeys from '../utils/collectExpandableKeys';
8+
import { flattenCircuits } from '../utils/flatten-circuits';
89

910
import columns from './Columns';
1011
import DownloadContainer from './download/download-container';
1112
import SubcircuitTable from './subcircuit-table';
1213

1314
import NumericFilters from './numeric-filter';
1415
import SearchBar from './search-bar';
16+
import ViewToggle from './ViewToggle';
1517

1618
import { classNames } from '@/util/utils';
1719
import styles from './exploreCircuitTable.module.scss';
@@ -34,6 +36,34 @@ export default function CircuitTable({
3436
const [minValue, setMinValue] = useState<number | undefined>(undefined);
3537
const [maxValue, setMaxValue] = useState<number | undefined>(undefined);
3638

39+
// VIEWS
40+
const [toggle, setToggle] = useState<'hierarchical' | 'flat'>('hierarchical');
41+
42+
// DATA
43+
const cleanedData = useMemo(
44+
() =>
45+
data.map((circuit: CircuitSchemaProps) => ({
46+
...circuit,
47+
neurons:
48+
typeof circuit.numberOfNeurons === 'number' && !Number.isNaN(circuit.numberOfNeurons)
49+
? circuit.numberOfNeurons
50+
: 0,
51+
})),
52+
[data]
53+
);
54+
55+
const flattenedData = useMemo(() => flattenCircuits(cleanedData), [cleanedData]);
56+
const tableData = toggle === 'hierarchical' ? cleanedData : flattenedData;
57+
58+
useEffect(() => {
59+
if (toggle === 'hierarchical' && (numericFilter || searchQuery)) {
60+
const expandableKeys = collectExpandableKeys(cleanedData);
61+
setExpandedRowKeys(expandableKeys);
62+
} else {
63+
setExpandedRowKeys([]);
64+
}
65+
}, [numericFilter, minValue, maxValue, searchQuery, cleanedData, toggle]);
66+
3767
useEffect(() => {
3868
if (numericFilter) {
3969
const expandableKeys = collectExpandableKeys(data);
@@ -81,7 +111,8 @@ export default function CircuitTable({
81111
calculateSubcircuitsForParent,
82112
handleRowExpandClick,
83113
isCircuitDetailPage,
84-
handleOpenDownloadModal
114+
handleOpenDownloadModal,
115+
toggle
85116
)}
86117
circuit={circuit}
87118
expandedRowKeys={expandedRowKeys}
@@ -102,6 +133,7 @@ export default function CircuitTable({
102133
minValue,
103134
maxValue,
104135
searchQuery,
136+
toggle,
105137
]
106138
);
107139

@@ -110,36 +142,46 @@ export default function CircuitTable({
110142
{hasSearch && (
111143
<div className="relative mb-8 flex w-full flex-row justify-between px-8">
112144
<SearchBar searchQuery={searchQuery} onSearchChange={setSearchQuery} />
113-
<NumericFilters
114-
filter={numericFilter}
115-
minValue={minValue}
116-
maxValue={maxValue}
117-
onFilterChange={setNumericFilter}
118-
onMinChange={setMinValue}
119-
onMaxChange={setMaxValue}
120-
/>
145+
146+
<div className="relative flex flex-row items-center gap-x-8">
147+
<ViewToggle toggle={toggle} setToggle={setToggle} />
148+
<NumericFilters
149+
filter={numericFilter}
150+
minValue={minValue}
151+
maxValue={maxValue}
152+
onFilterChange={setNumericFilter}
153+
onMinChange={setMinValue}
154+
onMaxChange={setMaxValue}
155+
/>
156+
</div>
121157
</div>
122158
)}
123159
<div className="relative w-full overflow-x-scroll">
124160
<div className="tableAndButton">
125161
<Table
126162
className={styles.circuitTable}
127-
dataSource={data}
163+
dataSource={tableData}
128164
columns={columns(
129165
expandedRowKeys,
130166
calculateSubcircuitsForParent,
131167
handleRowExpandClick,
132168
isCircuitDetailPage,
133-
handleOpenDownloadModal
169+
handleOpenDownloadModal,
170+
toggle
134171
)}
135172
pagination={false}
136-
expandable={{
137-
expandedRowRender: renderSubcircuits,
138-
expandedRowKeys,
139-
onExpand: handleExpandRow,
140-
expandIcon: () => null,
141-
rowExpandable: (record) => !!record.subcircuits && record.subcircuits.length > 0,
142-
}}
173+
expandable={
174+
toggle === 'hierarchical'
175+
? {
176+
expandedRowRender: renderSubcircuits,
177+
expandedRowKeys,
178+
onExpand: handleExpandRow,
179+
expandIcon: () => null,
180+
rowExpandable: (record) =>
181+
!!record.subcircuits && record.subcircuits.length > 0,
182+
}
183+
: undefined
184+
}
143185
rowClassName={(record) =>
144186
circuitMatchFilter(record, numericFilter, minValue, maxValue, searchQuery)
145187
? styles.matchingRow

src/components/explore-section/Circuit/global/numeric-filter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export default function NumericFilters({
6363
};
6464

6565
return (
66-
<div className="mb-4">
66+
<div className="flex flex-row items-center">
6767
{filter && (
6868
<button
6969
className="mr-8 text-sm text-gray-500 hover:text-gray-700"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { CircuitSchemaProps } from '../type';
2+
3+
export function flattenCircuits(circuits: CircuitSchemaProps[]): CircuitSchemaProps[] {
4+
const flat: CircuitSchemaProps[] = [];
5+
6+
function flatten(circuit: CircuitSchemaProps, depth: number = 0) {
7+
flat.push(circuit);
8+
if (circuit.subcircuits && circuit.subcircuits.length > 0) {
9+
circuit.subcircuits.forEach((subCircuit) => flatten(subCircuit, depth + 1));
10+
}
11+
}
12+
13+
circuits.forEach((circuit) => flatten(circuit));
14+
return flat;
15+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export default function FlatListViewIcon({
2+
iconColor,
3+
className,
4+
}: {
5+
iconColor: string;
6+
className?: string;
7+
}) {
8+
return (
9+
<svg
10+
width="19"
11+
height="13"
12+
viewBox="0 0 19 13"
13+
fill="none"
14+
xmlns="http://www.w3.org/2000/svg"
15+
className={className}
16+
>
17+
<path d="M19 0V1H0V0H19Z" fill={iconColor} />
18+
<path d="M19 6V7H0V6H19Z" fill={iconColor} />
19+
<path d="M19 12V13H0V12H19Z" fill={iconColor} />
20+
</svg>
21+
);
22+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export default function HierarchicalViewIcon({
2+
iconColor,
3+
className,
4+
}: {
5+
iconColor: string;
6+
className?: string;
7+
}) {
8+
return (
9+
<svg
10+
width="19"
11+
height="14"
12+
viewBox="0 0 19 14"
13+
fill="none"
14+
xmlns="http://www.w3.org/2000/svg"
15+
className={className}
16+
>
17+
<path d="M19 0V1H0V0H19Z" fill={iconColor} />
18+
<path d="M19 6V7H5V6H19Z" fill={iconColor} />
19+
<path d="M19 12V13H5V12H19Z" fill={iconColor} />
20+
<path
21+
d="M3 6.5C3 7.32843 2.32843 8 1.5 8C0.671573 8 0 7.32843 0 6.5C0 5.67157 0.671573 5 1.5 5C2.32843 5 3 5.67157 3 6.5Z"
22+
fill={iconColor}
23+
/>
24+
<path
25+
d="M3 12.5C3 13.3284 2.32843 14 1.5 14C0.671573 14 0 13.3284 0 12.5C0 11.6716 0.671573 11 1.5 11C2.32843 11 3 11.6716 3 12.5Z"
26+
fill={iconColor}
27+
/>
28+
</svg>
29+
);
30+
}

src/components/icons/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import DownloadIcon from './DownloadIcon';
1919
import EyeIcon from './EyeIcon';
2020
import EyeTargetIcon from './EyeTarget';
2121
import FileIcon from './File';
22+
import FlatListViewIcon from './FlatListViewIcon';
2223
import GripDotsVerticalIcon from './GripDotsVerticalIcon';
24+
import HierarchicalViewIcon from './HierarchicalViewIcon';
2325
import HomeIcon from './Home';
2426
import HomeFillIcon from './HomeFillIcon';
2527
import InformationIcon from './InformationIcon';
@@ -63,7 +65,9 @@ export {
6365
EyeIcon,
6466
EyeTargetIcon,
6567
FileIcon,
68+
FlatListViewIcon,
6669
GripDotsVerticalIcon,
70+
HierarchicalViewIcon,
6771
HomeFillIcon,
6872
HomeIcon,
6973
InformationIcon,

0 commit comments

Comments
 (0)