From 6bb6134aa44b4ab05a15e237aa4b83e1372bb3df Mon Sep 17 00:00:00 2001 From: Pavlo Strunkin Date: Sat, 12 Aug 2023 18:40:34 +0300 Subject: [PATCH] Fix navigation after filter/sort --- src/components/TestDetailsDialog/index.tsx | 47 +++++++++------------- src/components/TestRunList/index.tsx | 39 +++++++++++++----- src/contexts/testRun.context.tsx | 32 +++++---------- 3 files changed, 58 insertions(+), 60 deletions(-) diff --git a/src/components/TestDetailsDialog/index.tsx b/src/components/TestDetailsDialog/index.tsx index 376a2abd..61d2703b 100644 --- a/src/components/TestDetailsDialog/index.tsx +++ b/src/components/TestDetailsDialog/index.tsx @@ -1,5 +1,4 @@ import { Dialog, Typography } from "@mui/material"; -import { styled } from '@mui/material/styles'; import React from "react"; import { useNavigate } from "react-router"; import { useBuildState, useTestRunState } from "../../contexts"; @@ -7,27 +6,21 @@ import { buildTestRunLocation } from "../../_helpers/route.helpers"; import { BaseModal } from "../BaseModal"; import TestDetailsModal from "./TestDetailsModal"; import { TestRun } from "../../types"; +import { makeStyles } from "@mui/styles"; -const PREFIX = 'TestDetailsDialog'; - -const classes = { - modal: `${PREFIX}-modal` -}; - -const StyledDialog = styled(Dialog)(() => ({ - [`&.${classes.modal}`]: { +const useStyles = makeStyles(() => ({ + modal: { margin: "20px 10px 10px 10px", - } + }, })); export const TestDetailsDialog: React.FunctionComponent = () => { - + const classes = useStyles(); const { selectedTestRun, touched, testRuns: allTestRuns, - filteredTestRunIds, - sortedTestRunIds, + filteredSortedTestRunIds, } = useTestRunState(); const { selectedBuild } = useBuildState(); const navigate = useNavigate(); @@ -35,20 +28,16 @@ export const TestDetailsDialog: React.FunctionComponent = () => { const [navigationTargetId, setNavigationTargetId] = React.useState(); const testRuns = React.useMemo(() => { - const filtered = filteredTestRunIds - ? allTestRuns.filter((tr) => filteredTestRunIds.includes(tr.id)) - : allTestRuns; - - const sorted = sortedTestRunIds - ? filtered - .slice() - .sort( - (a, b) => - sortedTestRunIds.indexOf(a.id) - sortedTestRunIds.indexOf(b.id), - ) - : filtered; - return sorted; - }, [allTestRuns, filteredTestRunIds, sortedTestRunIds]); + if(filteredSortedTestRunIds) { + return allTestRuns + .filter((tr) => filteredSortedTestRunIds.includes(tr.id)) + .sort( + (a, b) => + filteredSortedTestRunIds.indexOf(a.id) - filteredSortedTestRunIds.indexOf(b.id), + ) + } + return allTestRuns; + }, [allTestRuns, filteredSortedTestRunIds]); const selectedTestRunIndex = React.useMemo( () => testRuns.findIndex((t) => t.id === selectedTestRun?.id), @@ -82,7 +71,7 @@ export const TestDetailsDialog: React.FunctionComponent = () => { } return ( - + { setNotSavedChangesModal(false); }} /> - + ); }; diff --git a/src/components/TestRunList/index.tsx b/src/components/TestRunList/index.tsx index 3f3e8d58..2a28820c 100644 --- a/src/components/TestRunList/index.tsx +++ b/src/components/TestRunList/index.tsx @@ -17,6 +17,7 @@ import { GridRenderCellParams, GridSortDirection, GridSortModel, + gridFilteredSortedRowIdsSelector, } from "@mui/x-data-grid"; import { DataGridCustomToolbar } from "./DataGridCustomToolbar"; import { StatusFilterOperators } from "./StatusFilterOperators"; @@ -52,7 +53,7 @@ const columnsDef: GridColDef[] = [ return tags.reduce( (prev, curr) => prev.concat(curr ? `${curr};` : ""), - "", + "" ); }, renderCell: (params: GridCellParams) => ( @@ -71,7 +72,7 @@ const columnsDef: GridColDef[] = [ margin: "1px", }} /> - ), + ) )} ), @@ -96,7 +97,7 @@ const TestRunList: React.FunctionComponent = () => { const apiRef = useGridApiRef(); const { enqueueSnackbar } = useSnackbar(); const navigate = useNavigate(); - const { testRuns, loading } = useTestRunState(); + const { selectedTestRun, testRuns, loading } = useTestRunState(); const { selectedBuild } = useBuildState(); const testRunDispatch = useTestRunDispatch(); @@ -123,12 +124,12 @@ const TestRunList: React.FunctionComponent = () => { testRunDispatch({ type: "get", payload, - }), + }) ) .catch((err: string) => enqueueSnackbar(err, { variant: "error", - }), + }) ); } else { testRunDispatch({ @@ -142,6 +143,29 @@ const TestRunList: React.FunctionComponent = () => { getTestRunListCallback(); }, [getTestRunListCallback]); + // workaround https://github.com/mui/mui-x/issues/1106 + React.useEffect(() => { + let unsubscribe: () => void; + const handleStateChange = () => { + unsubscribe?.(); + if (!selectedTestRun) { + testRunDispatch({ + type: "filterSort", + payload: gridFilteredSortedRowIdsSelector(apiRef), + }); + } + unsubscribe?.(); + }; + return apiRef.current.subscribeEvent?.( + "stateChange", + () => + (unsubscribe = apiRef.current.subscribeEvent( + "stateChange", + handleStateChange + )) + ); + }, [apiRef, apiRef.current.instanceId]); + if (selectedBuild) { return ( @@ -168,10 +192,7 @@ const TestRunList: React.FunctionComponent = () => { onSortModelChange={(model) => setSortModel(model)} onRowClick={(param: GridRowParams) => { navigate( - buildTestRunLocation( - selectedBuild.id, - param.row["id"].toString(), - ), + buildTestRunLocation(selectedBuild.id, param.row["id"].toString()) ); }} /> diff --git a/src/contexts/testRun.context.tsx b/src/contexts/testRun.context.tsx index 49881734..6724a519 100644 --- a/src/contexts/testRun.context.tsx +++ b/src/contexts/testRun.context.tsx @@ -3,6 +3,7 @@ import { TestRun } from "../types"; import { useLocation } from "react-router-dom"; import { getQueryParams } from "../_helpers/route.helpers"; import { testRunService } from "../services"; +import { GridRowId } from "@mui/x-data-grid"; interface IRequestAction { type: "request"; @@ -43,14 +44,9 @@ interface IRejectAction { payload: TestRun; } -interface IFilterAction { - type: "filter"; - payload?: string[] | number[]; -} - -interface ISortAction { - type: "sort"; - payload?: string[] | number[]; +interface IFilterSortAction { + type: "filterSort"; + payload?: GridRowId[]; } interface ITouchedAction { @@ -66,15 +62,13 @@ type IAction = | IUpdateAction | IApproveAction | IRejectAction - | IFilterAction - | ISortAction + | IFilterSortAction | ITouchedAction | ISelectAction; type Dispatch = (action: IAction) => void; type State = { selectedTestRun?: TestRun; - sortedTestRunIds?: string[] | number[]; - filteredTestRunIds?: string[] | number[]; + filteredSortedTestRunIds?: GridRowId[]; testRuns: TestRun[]; touched: boolean; loading: boolean; @@ -85,7 +79,7 @@ type TestRunProviderProps = { const TestRunStateContext = React.createContext(undefined); const TestRunDispatchContext = React.createContext( - undefined, + undefined ); const initialState: State = { @@ -103,16 +97,10 @@ function testRunReducer(state: State, action: IAction): State { selectedTestRun: action.payload, }; - case "filter": - return { - ...state, - filteredTestRunIds: action.payload, - }; - - case "sort": + case "filterSort": return { ...state, - sortedTestRunIds: action.payload, + filteredSortedTestRunIds: action.payload, }; case "request": @@ -142,7 +130,7 @@ function testRunReducer(state: State, action: IAction): State { ...state.testRuns, ...action.payload.filter( // remove duplicates - (i) => !state.testRuns.find((tr) => tr.id === i.id), + (i) => !state.testRuns.find((tr) => tr.id === i.id) ), ], };