Skip to content

Commit 9d208cd

Browse files
authored
Merge pull request #347 from aldbr/main_FEAT_split-data-table
feat: move FilterToolbar from DataTable to JobMonitor + remove filters from URL
2 parents 51d243c + 2e9618e commit 9d208cd

File tree

12 files changed

+535
-483
lines changed

12 files changed

+535
-483
lines changed

packages/diracx-web-components/src/components/JobMonitor/JobDataTable.tsx

Lines changed: 49 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,7 @@
11
"use client";
22

3-
import { useCallback, useEffect, useMemo, useState } from "react";
3+
import { useCallback, useMemo, useState } from "react";
44
import Box from "@mui/material/Box";
5-
import {
6-
blue,
7-
orange,
8-
grey,
9-
green,
10-
red,
11-
lightBlue,
12-
purple,
13-
teal,
14-
blueGrey,
15-
lime,
16-
amber,
17-
} from "@mui/material/colors";
185
import {
196
Alert,
207
AlertColor,
@@ -23,25 +10,22 @@ import {
2310
Backdrop,
2411
CircularProgress,
2512
Snackbar,
26-
lighten,
27-
darken,
28-
useTheme,
2913
} from "@mui/material";
3014
import { useOidcAccessToken } from "@axa-fr/react-oidc";
3115
import { Delete, Clear, Replay } from "@mui/icons-material";
3216
import {
33-
createColumnHelper,
34-
ColumnPinningState,
35-
RowSelectionState,
3617
useReactTable,
3718
getCoreRowModel,
19+
ColumnDef,
20+
ColumnPinningState,
21+
RowSelectionState,
3822
VisibilityState,
23+
PaginationState,
3924
} from "@tanstack/react-table";
4025
import { useOIDCContext } from "../../hooks/oidcConfiguration";
4126
import { DataTable, MenuItem } from "../shared/DataTable";
4227
import { Job, JobHistory, SearchBody } from "../../types";
4328
import { useDiracxUrl } from "../../hooks/utils";
44-
import { useApplicationId } from "../../hooks/application";
4529
import { JobHistoryDialog } from "./JobHistoryDialog";
4630

4731
import {
@@ -54,17 +38,52 @@ import {
5438
} from "./JobDataService";
5539

5640
/**
57-
* The data grid for the jobs
41+
* Job Data Table props
42+
* @property {number} searchBody - the search body to send along with the request
43+
* @property {function} setSearchBody - the function to call when the search body changes
5844
*/
59-
export function JobDataTable() {
60-
const theme = useTheme();
61-
62-
// Id of the application
63-
const appId = useApplicationId();
64-
65-
// Load the initial state from local storage
66-
const initialState = sessionStorage.getItem(`${appId}_State`);
45+
interface JobDataTableProps {
46+
/** The search body to send along with the request */
47+
searchBody: SearchBody;
48+
/** The function to call when the search body changes */
49+
setSearchBody: React.Dispatch<React.SetStateAction<SearchBody>>;
50+
/** Columns */
51+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
52+
columns: ColumnDef<Job, any>[];
53+
/** Pagination */
54+
pagination: PaginationState;
55+
/** Set pagination */
56+
setPagination: React.Dispatch<React.SetStateAction<PaginationState>>;
57+
/** Row selection */
58+
rowSelection: RowSelectionState;
59+
/** Set row selection */
60+
setRowSelection: React.Dispatch<React.SetStateAction<RowSelectionState>>;
61+
/** Column Visibility */
62+
columnVisibility: VisibilityState;
63+
/** Set column visibility */
64+
setColumnVisibility: React.Dispatch<React.SetStateAction<VisibilityState>>;
65+
/** Column Pinning */
66+
columnPinning: ColumnPinningState;
67+
/** Set column pinning */
68+
setColumnPinning: React.Dispatch<React.SetStateAction<ColumnPinningState>>;
69+
}
6770

71+
/**
72+
* The data grid for the jobs
73+
*/
74+
export function JobDataTable({
75+
searchBody,
76+
setSearchBody,
77+
columns,
78+
pagination,
79+
setPagination,
80+
rowSelection,
81+
setRowSelection,
82+
columnVisibility,
83+
setColumnVisibility,
84+
columnPinning,
85+
setColumnPinning,
86+
}: JobDataTableProps) {
6887
// Authentication
6988
const { configuration } = useOIDCContext();
7089
const { accessToken } = useOidcAccessToken(configuration?.scope);
@@ -79,191 +98,13 @@ export function JobDataTable() {
7998
severity: "success",
8099
});
81100

82-
const parsedInitialState =
83-
typeof initialState === "string" ? JSON.parse(initialState) : null;
84-
85-
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(
86-
parsedInitialState
87-
? parsedInitialState.columnVisibility
88-
: {
89-
JobGroup: false,
90-
JobType: false,
91-
Owner: false,
92-
OwnerGroup: false,
93-
VO: false,
94-
StartExecTime: false,
95-
EndExecTime: false,
96-
UserPriority: false,
97-
},
98-
);
99-
const [columnPinning, setColumnPinning] = useState<ColumnPinningState>(
100-
parsedInitialState
101-
? parsedInitialState.columnPinning
102-
: {
103-
left: ["JobID"], // Pin JobID column by default
104-
},
105-
);
106-
const [rowSelection, setRowSelection] = useState<RowSelectionState>(
107-
parsedInitialState ? parsedInitialState.rowSelection : {},
108-
);
109-
const [pagination, setPagination] = useState(
110-
parsedInitialState
111-
? parsedInitialState.pagination
112-
: {
113-
pageIndex: 0,
114-
pageSize: 25,
115-
},
116-
);
117-
118-
// State for search body
119-
const [searchBody, setSearchBody] = useState<SearchBody>({
120-
sort: [{ parameter: "JobID", direction: "desc" }],
121-
});
122-
123101
// State for selected job
124102
const [selectedJobId, setSelectedJobId] = useState<number | null>(null);
125103

126104
// State for job history
127105
const [isHistoryDialogOpen, setIsHistoryDialogOpen] = useState(false);
128106
const [jobHistoryData, setJobHistoryData] = useState<JobHistory[]>([]);
129107

130-
// Save the state of the table in local storage
131-
useEffect(() => {
132-
const state = {
133-
columnVisibility: { ...columnVisibility },
134-
columnPinning: {
135-
left: [...(columnPinning.left || [])],
136-
right: [...(columnPinning.right || [])],
137-
},
138-
rowSelection: { ...rowSelection },
139-
pagination: {
140-
pageIndex: pagination.pageIndex,
141-
pageSize: pagination.pageSize,
142-
},
143-
};
144-
145-
sessionStorage.setItem(`${appId}_State`, JSON.stringify(state));
146-
}, [columnVisibility, columnPinning, rowSelection, pagination]);
147-
148-
// Status colors
149-
const statusColors: Record<string, string> = useMemo(
150-
() => ({
151-
Submitting: purple[500],
152-
Received: blueGrey[500],
153-
Checking: teal[500],
154-
Staging: lightBlue[500],
155-
Waiting: amber[600],
156-
Matched: blue[300],
157-
Running: blue[900],
158-
Rescheduled: lime[700],
159-
Completing: orange[500],
160-
Completed: green[300],
161-
Done: green[500],
162-
Failed: red[500],
163-
Stalled: amber[900],
164-
Killed: red[900],
165-
Deleted: grey[500],
166-
}),
167-
[],
168-
);
169-
170-
/**
171-
* Renders the status cell with colors
172-
*/
173-
const renderStatusCell = useCallback(
174-
(status: string) => {
175-
return (
176-
<Box
177-
sx={{
178-
display: "inline-block",
179-
borderRadius: "10px",
180-
padding: "3px 10px",
181-
backgroundColor:
182-
theme.palette.mode === "light"
183-
? lighten(statusColors[status] ?? "default", 0.1)
184-
: darken(statusColors[status] ?? "default", 0.3),
185-
color: "white",
186-
fontWeight: "bold",
187-
}}
188-
>
189-
{status}
190-
</Box>
191-
);
192-
},
193-
[theme, statusColors],
194-
);
195-
196-
const columnHelper = useMemo(() => createColumnHelper<Job>(), []);
197-
198-
/**
199-
* The head cells for the data grid (desktop version)
200-
*/
201-
const columns = useMemo(
202-
() => [
203-
columnHelper.accessor("JobID", {
204-
header: "ID",
205-
meta: { type: "number" },
206-
}),
207-
columnHelper.accessor("Status", {
208-
header: "Status",
209-
cell: (info) => renderStatusCell(info.getValue()),
210-
meta: { type: "category", values: Object.keys(statusColors).sort() },
211-
}),
212-
columnHelper.accessor("MinorStatus", {
213-
header: "Minor Status",
214-
}),
215-
columnHelper.accessor("ApplicationStatus", {
216-
header: "Application Status",
217-
}),
218-
columnHelper.accessor("Site", {
219-
header: "Site",
220-
}),
221-
columnHelper.accessor("JobName", {
222-
header: "Name",
223-
}),
224-
columnHelper.accessor("JobGroup", {
225-
header: "Job Group",
226-
}),
227-
columnHelper.accessor("JobType", {
228-
header: "Type",
229-
}),
230-
columnHelper.accessor("LastUpdateTime", {
231-
header: "Last Update Time",
232-
meta: { type: "date" },
233-
}),
234-
columnHelper.accessor("HeartBeatTime", {
235-
header: "Last Sign of Life",
236-
meta: { type: "date" },
237-
}),
238-
columnHelper.accessor("SubmissionTime", {
239-
header: "Submission Time",
240-
meta: { type: "date" },
241-
}),
242-
columnHelper.accessor("Owner", {
243-
header: "Owner",
244-
}),
245-
columnHelper.accessor("OwnerGroup", {
246-
header: "Owner Group",
247-
}),
248-
columnHelper.accessor("VO", {
249-
header: "VO",
250-
}),
251-
columnHelper.accessor("StartExecTime", {
252-
header: "Start Execution Time",
253-
meta: { type: "date" },
254-
}),
255-
columnHelper.accessor("EndExecTime", {
256-
header: "End Execution Time",
257-
meta: { type: "date" },
258-
}),
259-
columnHelper.accessor("UserPriority", {
260-
header: "User Priority",
261-
meta: { type: "number" },
262-
}),
263-
],
264-
[columnHelper, renderStatusCell, statusColors],
265-
);
266-
267108
/**
268109
* Fetches the jobs from the /api/jobs/search endpoint
269110
*/

0 commit comments

Comments
 (0)