Skip to content

Commit f6bb761

Browse files
committed
systems tree Test using react flow
1 parent f445361 commit f6bb761

File tree

7 files changed

+779
-6
lines changed

7 files changed

+779
-6
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
"@uppy/react": "^4.0.2",
2929
"@uppy/xhr-upload": "^4.2.0",
3030
"@vitejs/plugin-react": "^4.3.0",
31+
"@xyflow/react": "^12.4.2",
3132
"axios": "^1.7.2",
3233
"blob-polyfill": "^9.0.20240710",
3334
"browserslist": "^4.23.0",
3435
"browserslist-to-esbuild": "^2.1.1",
36+
"dagre": "^0.8.5",
3537
"date-fns": "4.1.0",
3638
"history": "^5.3.0",
3739
"loglevel": "^1.9.1",
@@ -86,6 +88,9 @@
8688
"@testing-library/jest-dom": "6.6.3",
8789
"@testing-library/react": "16.1.0",
8890
"@testing-library/user-event": "14.5.2",
91+
"@types/d3": "^7",
92+
"@types/d3-hierarchy": "^3",
93+
"@types/dagre": "^0",
8994
"@types/eslint-plugin-jsx-a11y": "6.10.0",
9095
"@types/eslint__js": "8.42.3",
9196
"@types/react-router-dom": "5.3.3",

src/App.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import SystemsLayout, {
6464
SystemsLayoutErrorComponent,
6565
systemsLayoutLoader,
6666
} from './systems/systemsLayout.component';
67+
import SystemsTree from './systems/systemsTree.component';
6768
import ViewTabs from './view/viewTabs.component';
6869

6970
export const paths = {
@@ -81,6 +82,8 @@ export const paths = {
8182
item: '/catalogue/:catalogue_category_id/items/:catalogue_item_id/items/:item_id',
8283
systems: '/systems',
8384
system: '/systems/:system_id',
85+
systemTree: '/systems/:system_id/tree',
86+
systemRootTree: '/systems/tree',
8487
manufacturers: '/manufacturers',
8588
manufacturer: '/manufacturers/:manufacturer_id',
8689
};
@@ -216,6 +219,15 @@ const routeObject: RouteObject[] = [
216219
Component: Systems,
217220
loader: systemsLayoutLoader(queryClient),
218221
},
222+
{
223+
path: 'tree',
224+
Component: SystemsTree,
225+
},
226+
{
227+
path: paths.systemTree,
228+
Component: SystemsTree,
229+
loader: systemsLayoutLoader(queryClient),
230+
},
219231
{
220232
path: '*',
221233
Component: SystemsErrorComponent,

src/api/systems.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,34 @@ export const useGetSystem = (
8787
return useQuery(getSystemQuery(id));
8888
};
8989

90+
export interface SystemTree extends System {
91+
subsystems?: SystemTree[];
92+
}
93+
94+
const getSystemTree = async (parent_id?: string): Promise<SystemTree[]> => {
95+
// Fetch the systems at the current level
96+
const systems = await getSystems(parent_id || 'null');
97+
98+
// Fetch subsystems for each system recursively
99+
const systemsWithTree = await Promise.all(
100+
systems.map(async (system) => {
101+
const subsystems = await getSystemTree(system.id); // Fetch subsystems
102+
return { ...system, subsystems }; // Attach subsystems
103+
})
104+
);
105+
106+
return systemsWithTree;
107+
};
108+
109+
export const useGetSystemsTree = (
110+
parent_id?: string | null
111+
): UseQueryResult<SystemTree[], AxiosError> => {
112+
return useQuery({
113+
queryKey: ['SystemsTree', parent_id],
114+
queryFn: () => getSystemTree(parent_id ?? ''),
115+
});
116+
};
117+
90118
const getSystemsBreadcrumbs = async (id: string): Promise<BreadcrumbsInfo> => {
91119
return imsApi.get(`/v1/systems/${id}/breadcrumbs`, {}).then((response) => {
92120
return response.data;

src/common/baseLayoutHeader.component.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@ export interface BaseLayoutHeaderProps {
1414
function BaseLayoutHeader(props: BaseLayoutHeaderProps) {
1515
const { breadcrumbsInfo, children, homeLocation } = props;
1616
const navigate = useNavigate();
17+
18+
// Check if we are in Tree View or Normal View by looking for '/tree' in the URL
19+
const isTreeView = location.pathname.includes('tree');
1720
const onChangeNode = React.useCallback(
1821
(id: string | null) => {
19-
navigate(`/${RoutesHomeLocation[homeLocation]}${id ? `/${id}` : ''}`);
22+
navigate(
23+
`/${RoutesHomeLocation[homeLocation]}${id ? `/${id}` : ''}${isTreeView && !id && homeLocation == 'Systems' ? '/tree' : ''}`
24+
);
2025
},
21-
[homeLocation, navigate]
26+
[homeLocation, isTreeView, navigate]
2227
);
2328
return (
2429
<Box height="100%" width="100%">

src/systems/systemsLayout.component.tsx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
import AccountTreeIcon from '@mui/icons-material/AccountTree';
2+
import ViewModuleIcon from '@mui/icons-material/ViewModule';
3+
import { ToggleButton, ToggleButtonGroup } from '@mui/material';
14
import type { QueryClient } from '@tanstack/react-query';
2-
import { Outlet, useParams, type LoaderFunctionArgs } from 'react-router-dom';
5+
import {
6+
Outlet,
7+
useLocation,
8+
useNavigate,
9+
useParams,
10+
type LoaderFunctionArgs,
11+
} from 'react-router-dom';
312
import { getSystemQuery, useGetSystemsBreadcrumbs } from '../api/systems';
413
import BaseLayoutHeader from '../common/baseLayoutHeader.component';
514
import PageNotFoundComponent from '../common/pageNotFound/pageNotFound.component';
@@ -29,15 +38,58 @@ export const systemsLayoutLoader =
2938
};
3039

3140
function SystemsLayout() {
41+
const location = useLocation();
3242
const { system_id: systemId } = useParams();
3343

3444
const { data: systemsBreadcrumbs } = useGetSystemsBreadcrumbs(systemId);
45+
const navigate = useNavigate();
3546

47+
// Check if we are in Tree View or Normal View by looking for '/tree' in the URL
48+
const isTreeView = location.pathname.includes('tree');
49+
50+
// Handle the view change using the toggle button
51+
const handleViewChange = (
52+
_event: React.MouseEvent<HTMLElement>,
53+
newView: string
54+
) => {
55+
if (newView === 'tree') {
56+
// Navigate to Tree View
57+
navigate(`/systems${systemId ? `/${systemId}` : ''}/tree`);
58+
} else {
59+
// Navigate to Normal View
60+
navigate(`/systems${systemId ? `/${systemId}` : ''}`);
61+
}
62+
};
3663
return (
3764
<BaseLayoutHeader
3865
homeLocation="Systems"
39-
breadcrumbsInfo={systemsBreadcrumbs}
66+
breadcrumbsInfo={{
67+
...systemsBreadcrumbs,
68+
full_trail: systemsBreadcrumbs?.full_trail ?? true,
69+
trail:
70+
systemsBreadcrumbs?.trail.map(([id, name]) => [
71+
isTreeView ? id + '/tree' : id,
72+
name,
73+
]) ?? [],
74+
}}
4075
>
76+
<ToggleButtonGroup
77+
value={isTreeView ? 'tree' : 'normal'}
78+
exclusive
79+
onChange={handleViewChange}
80+
aria-label="view mode toggle"
81+
size="small"
82+
sx={{ margin: 1 }}
83+
>
84+
<ToggleButton value="normal" aria-label="normal view">
85+
<ViewModuleIcon sx={{ marginRight: 1 }} fontSize="small" />
86+
Normal View
87+
</ToggleButton>
88+
<ToggleButton value="tree" aria-label="tree view">
89+
<AccountTreeIcon sx={{ marginRight: 1 }} fontSize="small" />
90+
Tree View
91+
</ToggleButton>
92+
</ToggleButtonGroup>
4193
<Outlet />
4294
</BaseLayoutHeader>
4395
);

0 commit comments

Comments
 (0)