Skip to content

Commit 0bd5da3

Browse files
authored
291 url nav refactoring (#242)
* Refactoring . Build url navigation * test run url fixed
1 parent bc8db9b commit 0bd5da3

File tree

12 files changed

+152
-209
lines changed

12 files changed

+152
-209
lines changed

package-lock.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/_helpers/route.helpers.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import qs from "qs";
44
export const buildProjectPageUrl = (projectId: string) =>
55
`${routes.HOME}${projectId}`;
66

7-
export const buildTestRunLocation = (buildId: string, testRunId?: string) => ({
8-
search: testRunId
9-
? `buildId=${buildId}&testId=${testRunId}`
10-
: `buildId=${buildId}`,
7+
export const buildTestRunLocation = (buildId?: string, testRunId?: string) => ({
8+
search: buildId
9+
? testRunId
10+
? `buildId=${buildId}&testId=${testRunId}`
11+
: `buildId=${buildId}`
12+
: "",
1113
});
1214

1315
export interface QueryParams {

src/_test/stub.helper.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ const buildsServiceStub = {
3434
const testRunServiceStub = {
3535
getList: (testRuns: Array<TestRun>) =>
3636
cy.stub(testRunService, "getList").resolves(testRuns),
37+
getDetails: (testRun: TestRun) =>
38+
cy.stub(testRunService, "getDetails").resolves(testRun),
3739
};
3840

3941
const staticServiceStub = {

src/components/BuildList/index.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import {
2121
useBuildState,
2222
useBuildDispatch,
2323
deleteBuild,
24-
selectBuild,
25-
getBuildList,
2624
useProjectState,
2725
} from "../../contexts";
2826
import { BuildStatusChip } from "../BuildStatusChip";
@@ -34,6 +32,8 @@ import { Pagination } from "@material-ui/lab";
3432
import { Build } from "../../types";
3533
import { BaseModal } from "../BaseModal";
3634
import { buildsService } from "../../services";
35+
import { useHistory } from "react-router";
36+
import { buildTestRunLocation } from "../../_helpers/route.helpers";
3737

3838
const useStyles = makeStyles((theme: Theme) =>
3939
createStyles({
@@ -54,6 +54,7 @@ const useStyles = makeStyles((theme: Theme) =>
5454

5555
const BuildList: FunctionComponent = () => {
5656
const classes = useStyles();
57+
const history = useHistory();
5758
const { buildList, selectedBuild, loading, total, take } = useBuildState();
5859
const buildDispatch = useBuildDispatch();
5960
const { enqueueSnackbar } = useSnackbar();
@@ -85,23 +86,28 @@ const BuildList: FunctionComponent = () => {
8586
setEditDialogOpen(!editDialogOpen);
8687
};
8788

88-
React.useEffect(() => {
89-
if (!selectedBuild || selectedBuild.projectId !== selectedProjectId) {
90-
const buildId = buildList.length > 0 ? buildList[0].id : null;
91-
selectBuild(buildDispatch, buildId);
92-
}
93-
}, [buildDispatch, selectedBuild, buildList, selectedProjectId]);
89+
const selectBuildCalback = React.useCallback(
90+
(id?: string) => history.push(buildTestRunLocation(id)),
91+
[history]
92+
);
9493

95-
const getBuildListCalback: any = React.useCallback(
96-
(page: number) =>
97-
selectedProjectId &&
98-
getBuildList(buildDispatch, selectedProjectId, page).catch(
99-
(err: string) =>
100-
enqueueSnackbar(err, {
101-
variant: "error",
94+
const getBuildListCalback = React.useCallback(
95+
(page: number) => {
96+
if (selectedProjectId) {
97+
buildDispatch({ type: "request" });
98+
buildsService
99+
.getList(selectedProjectId, take, take * (page - 1))
100+
.then((payload) => {
101+
buildDispatch({ type: "get", payload });
102102
})
103-
),
104-
[buildDispatch, enqueueSnackbar, selectedProjectId]
103+
.catch((err: string) =>
104+
enqueueSnackbar(err, {
105+
variant: "error",
106+
})
107+
);
108+
}
109+
},
110+
[buildDispatch, enqueueSnackbar, selectedProjectId, take]
105111
);
106112

107113
React.useEffect(() => {
@@ -122,9 +128,7 @@ const BuildList: FunctionComponent = () => {
122128
<ListItem
123129
selected={selectedBuild?.id === build.id}
124130
button
125-
onClick={() => {
126-
selectBuild(buildDispatch, build.id);
127-
}}
131+
onClick={() => selectBuildCalback(build.id)}
128132
classes={{
129133
container: classes.listItem,
130134
}}
@@ -273,14 +277,17 @@ const BuildList: FunctionComponent = () => {
273277
}
274278
onSubmit={() => {
275279
deleteBuild(buildDispatch, menuBuild.id)
276-
.then((b) => {
280+
.then((build) => {
277281
toggleDeleteDialogOpen();
278282
enqueueSnackbar(
279283
`Build #${menuBuild.number || menuBuild.id} deleted`,
280284
{
281285
variant: "success",
282286
}
283287
);
288+
if (menuBuild.id === selectedBuild?.id) {
289+
selectBuildCalback();
290+
}
284291
})
285292
.catch((err) =>
286293
enqueueSnackbar(err, {

src/components/TestDetailsDialog/TestDetailsModal.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ const TestDetailsModal: React.FunctionComponent<{
8585
const [isDiffShown, setIsDiffShown] = useState(!!testRun.diffName);
8686
const [selectedRectId, setSelectedRectId] = React.useState<string>();
8787
const [ignoreAreas, setIgnoreAreas] = React.useState<IgnoreArea[]>([]);
88-
const [applyIgnoreDialogOpen, setApplyIgnoreDialogOpen] = React.useState(false);
88+
const [applyIgnoreDialogOpen, setApplyIgnoreDialogOpen] = React.useState(
89+
false
90+
);
8991

9092
const toggleApplyIgnoreDialogOpen = () => {
9193
setApplyIgnoreDialogOpen(!applyIgnoreDialogOpen);
@@ -101,7 +103,8 @@ const TestDetailsModal: React.FunctionComponent<{
101103
staticService.getImage(testRun.diffName)
102104
);
103105

104-
const applyIgnoreAreaText = 'Apply selected ignore area to all images in this build.';
106+
const applyIgnoreAreaText =
107+
"Apply selected ignore area to all images in this build.";
105108

106109
React.useEffect(() => {
107110
fitStageToScreen();
@@ -195,9 +198,9 @@ const TestDetailsModal: React.FunctionComponent<{
195198
const fitStageToScreen = () => {
196199
const scale = image
197200
? Math.min(
198-
stageWidth < image.width ? stageWidth / image.width : 1,
199-
stageHeigth < image.height ? stageHeigth / image.height : 1
200-
)
201+
stageWidth < image.width ? stageWidth / image.width : 1,
202+
stageHeigth < image.height ? stageHeigth / image.height : 1
203+
)
201204
: 1;
202205
setStageScale(scale);
203206
resetPositioin();
@@ -274,10 +277,10 @@ const TestDetailsModal: React.FunctionComponent<{
274277
)}
275278
{(testRun.status === TestStatus.unresolved ||
276279
testRun.status === TestStatus.new) && (
277-
<Grid item>
278-
<ApproveRejectButtons testRun={testRun} />
279-
</Grid>
280-
)}
280+
<Grid item>
281+
<ApproveRejectButtons testRun={testRun} />
282+
</Grid>
283+
)}
281284
<Grid item>
282285
<IconButton color="inherit" onClick={handleClose}>
283286
<Close />
@@ -492,7 +495,7 @@ const TestDetailsModal: React.FunctionComponent<{
492495
<BaseModal
493496
open={applyIgnoreDialogOpen}
494497
title={applyIgnoreAreaText}
495-
submitButtonText={'Yes'}
498+
submitButtonText={"Yes"}
496499
onCancel={toggleApplyIgnoreDialogOpen}
497500
content={
498501
<Typography>
@@ -502,8 +505,7 @@ const TestDetailsModal: React.FunctionComponent<{
502505
onSubmit={() => {
503506
toggleApplyIgnoreDialogOpen();
504507
applyIgnoreArea();
505-
}
506-
}
508+
}}
507509
/>
508510
</React.Fragment>
509511
);

src/components/TestDetailsDialog/index.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { Dialog, makeStyles, Typography } from "@material-ui/core";
22
import React from "react";
3-
import {
4-
selectTestRun,
5-
useTestRunDispatch,
6-
useTestRunState,
7-
} from "../../contexts";
3+
import { useHistory } from "react-router";
4+
import { useBuildState, useTestRunState } from "../../contexts";
5+
import { buildTestRunLocation } from "../../_helpers/route.helpers";
86
import { BaseModal } from "../BaseModal";
97
import { ArrowButtons } from "./ArrowButtons";
108
import TestDetailsModal from "./TestDetailsModal";
@@ -18,14 +16,14 @@ const useStyles = makeStyles((theme) => ({
1816
export const TestDetailsDialog: React.FunctionComponent = () => {
1917
const classes = useStyles();
2018
const {
21-
testRun,
19+
selectedTestRun,
2220
touched,
2321
testRuns: allTestRuns,
2422
filteredTestRunIds,
2523
sortedTestRunIds,
26-
selectedTestRunId,
2724
} = useTestRunState();
28-
const testRunDispatch = useTestRunDispatch();
25+
const { selectedBuild } = useBuildState();
26+
const history = useHistory();
2927
const [notSavedChangesModal, setNotSavedChangesModal] = React.useState(false);
3028
const [navigationTargetId, setNavigationTargetId] = React.useState<string>();
3129

@@ -46,8 +44,8 @@ export const TestDetailsDialog: React.FunctionComponent = () => {
4644
}, [allTestRuns, filteredTestRunIds, sortedTestRunIds]);
4745

4846
const selectedTestRunIndex = React.useMemo(
49-
() => testRuns.findIndex((t) => t.id === selectedTestRunId),
50-
[testRuns, selectedTestRunId]
47+
() => testRuns.findIndex((t) => t.id === selectedTestRun?.id),
48+
[testRuns, selectedTestRun?.id]
5149
);
5250

5351
const handleNavigation = React.useCallback(
@@ -56,20 +54,20 @@ export const TestDetailsDialog: React.FunctionComponent = () => {
5654
setNavigationTargetId(id);
5755
setNotSavedChangesModal(true);
5856
} else {
59-
selectTestRun(testRunDispatch, id);
57+
history.push(buildTestRunLocation(selectedBuild?.id, id));
6058
}
6159
},
62-
[testRunDispatch, touched]
60+
[touched, history, selectedBuild?.id]
6361
);
6462

65-
if (!testRun) {
63+
if (!selectedTestRun) {
6664
return null;
6765
}
6866

6967
return (
7068
<Dialog open={true} fullScreen className={classes.modal}>
7169
<TestDetailsModal
72-
testRun={testRun}
70+
testRun={selectedTestRun}
7371
touched={touched}
7472
handleClose={() => handleNavigation()}
7573
/>
@@ -87,7 +85,9 @@ export const TestDetailsDialog: React.FunctionComponent = () => {
8785
<Typography>{`Are you sure you want to discard changes?`}</Typography>
8886
}
8987
onSubmit={() => {
90-
selectTestRun(testRunDispatch, navigationTargetId);
88+
history.push(
89+
buildTestRunLocation(selectedBuild?.id, navigationTargetId)
90+
);
9191
setNotSavedChangesModal(false);
9292
}}
9393
/>

src/components/TestRunList/index.tsx

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import React from "react";
2-
import { Chip } from "@material-ui/core";
2+
import { Chip, Typography } from "@material-ui/core";
33
import TestStatusChip from "../TestStatusChip";
44
import {
55
useTestRunState,
66
useTestRunDispatch,
7-
getTestRunList,
87
useBuildState,
9-
selectTestRun,
108
} from "../../contexts";
119
import { useSnackbar } from "notistack";
1210
import {
@@ -26,6 +24,9 @@ import { DataGridCustomToolbar } from "./DataGridCustomToolbar";
2624
import { StatusFilterOperators } from "./StatusFilterOperators";
2725
import { TagFilterOperators } from "./TagFilterOperators";
2826
import { TestStatus } from "../../types";
27+
import { testRunService } from "../../services";
28+
import { useHistory } from "react-router";
29+
import { buildTestRunLocation } from "../../_helpers/route.helpers";
2930

3031
const columnsDef: GridColDef[] = [
3132
{ field: "id", hide: true, filterable: false },
@@ -97,8 +98,9 @@ const columnsDef: GridColDef[] = [
9798

9899
const TestRunList: React.FunctionComponent = () => {
99100
const { enqueueSnackbar } = useSnackbar();
100-
const { testRun, testRuns, loading } = useTestRunState();
101-
const { selectedBuildId } = useBuildState();
101+
const history = useHistory();
102+
const { selectedTestRun, testRuns, loading } = useTestRunState();
103+
const { selectedBuild } = useBuildState();
102104
const testRunDispatch = useTestRunDispatch();
103105

104106
const [sortModel, setSortModel] = React.useState<GridSortModel>([
@@ -108,24 +110,29 @@ const TestRunList: React.FunctionComponent = () => {
108110
},
109111
]);
110112

111-
const getTestRunListCallback = React.useCallback(
112-
() =>
113-
selectedBuildId &&
114-
getTestRunList(testRunDispatch, selectedBuildId).catch((err: string) =>
115-
enqueueSnackbar(err, {
116-
variant: "error",
117-
})
118-
),
119-
[testRunDispatch, enqueueSnackbar, selectedBuildId]
120-
);
113+
const getTestRunListCallback = React.useCallback(() => {
114+
testRunDispatch({ type: "request" });
115+
if (selectedBuild?.id) {
116+
testRunService
117+
.getList(selectedBuild.id)
118+
.then((payload) => testRunDispatch({ type: "get", payload }))
119+
.catch((err: string) =>
120+
enqueueSnackbar(err, {
121+
variant: "error",
122+
})
123+
);
124+
} else {
125+
testRunDispatch({ type: "get", payload: [] });
126+
}
127+
}, [testRunDispatch, enqueueSnackbar, selectedBuild?.id]);
121128

122129
React.useEffect(() => {
123130
getTestRunListCallback();
124131
}, [getTestRunListCallback]);
125132

126133
return (
127134
<React.Fragment>
128-
{selectedBuildId && (
135+
{selectedBuild ? (
129136
<DataGrid
130137
rows={testRuns}
131138
columns={columnsDef}
@@ -142,13 +149,15 @@ const TestRunList: React.FunctionComponent = () => {
142149
sortModel={sortModel}
143150
onSortModelChange={(model) => setSortModel(model)}
144151
onRowClick={(param: GridRowParams) => {
145-
selectTestRun(
146-
testRunDispatch,
147-
param.getValue(param.id, "id")?.toString()
152+
history.push(
153+
buildTestRunLocation(
154+
selectedBuild.id,
155+
param.getValue(param.id, "id")?.toString()
156+
)
148157
);
149158
}}
150159
onStateChange={(props: GridStateChangeParams) => {
151-
if (!testRun) {
160+
if (!selectedTestRun) {
152161
// only if testRun modal is not shown
153162
testRunDispatch({
154163
type: "filter",
@@ -161,6 +170,8 @@ const TestRunList: React.FunctionComponent = () => {
161170
}
162171
}}
163172
/>
173+
) : (
174+
<Typography variant="h5">Select build from list</Typography>
164175
)}
165176
</React.Fragment>
166177
);

0 commit comments

Comments
 (0)