Skip to content

Commit 0bbe173

Browse files
♻️ - refactor: migrate detail edit to BaseListView
1 parent 8a142aa commit 0bbe173

File tree

8 files changed

+281
-191
lines changed

8 files changed

+281
-191
lines changed

frontend/src/lib/zaakSelection/zaakSelection.test.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Replace with the correct path
21
import { Zaak } from "../../types";
32
import {
43
addToZaakSelection,
@@ -74,6 +73,23 @@ describe("Zaak Selection Functions", () => {
7473
expect(filteredSelection[mockZaak2]).toBeUndefined();
7574
});
7675

76+
it("should return explicitly unselected items when calling `getFilteredZaakSelection` with `selectedOnly=false`", async () => {
77+
const detail = { status: "open" };
78+
await addToZaakSelection(mockKey, [mockZaak1], detail);
79+
await addToZaakSelection(mockKey, [mockZaak2], { status: "closed" });
80+
await removeFromZaakSelection(mockKey, [mockZaak2]);
81+
82+
const filteredSelection = await getFilteredZaakSelection(
83+
mockKey,
84+
undefined,
85+
false,
86+
);
87+
88+
expect(Object.keys(filteredSelection)).toHaveLength(2);
89+
expect(filteredSelection[mockZaak1.url as string].selected).toBeTruthy();
90+
expect(filteredSelection[mockZaak2].selected).toBeFalsy();
91+
});
92+
7793
it("should return a single selected Zaak", async () => {
7894
await addToZaakSelection(mockKey, [mockZaak1]);
7995

frontend/src/lib/zaakSelection/zaakSelection.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,18 @@ export async function getZaakSelectionSize<DetailType = unknown>(
136136
* Returns a single zaak in the zaak selection.
137137
* @param key A key identifying the selection
138138
* @param zaak Either a `Zaak.url` or `Zaak` object.
139+
* @param selectedOnly
139140
*/
140141
export async function getZaakSelectionItem<DetailType = unknown>(
141142
key: string,
142143
zaak: string | Zaak,
144+
selectedOnly = true,
143145
) {
144146
const zaakSelection = await getZaakSelection<DetailType>(key);
145147
const url = _getZaakUrl(zaak);
146-
return zaakSelection[url]?.selected ? zaakSelection[url] : undefined;
148+
return zaakSelection[url]?.selected || !selectedOnly
149+
? zaakSelection[url]
150+
: undefined;
147151
}
148152

149153
/**

frontend/src/pages/destructionlist/abstract/BaseListView.tsx

+59-21
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import {
77
Solid,
88
TypedField,
99
} from "@maykin-ui/admin-ui";
10-
import React, { useCallback } from "react";
10+
import React, { useCallback, useMemo } from "react";
1111
import { useNavigation } from "react-router-dom";
1212

1313
import { DestructionList } from "../../../lib/api/destructionLists";
1414
import { Review } from "../../../lib/api/review";
1515
import { PaginatedZaken } from "../../../lib/api/zaken";
16+
import { Zaak } from "../../../types";
1617
import { DestructionListToolbar } from "../detail/components";
1718
import { useFields } from "../hooks/useFields";
1819
import { useFilter } from "../hooks/useFilter";
@@ -34,14 +35,18 @@ export type BaseListViewProps = React.PropsWithChildren<{
3435
paginatedZaken: PaginatedZaken;
3536
secondaryNavigationItems?: ListTemplateProps["secondaryNavigationItems"];
3637

38+
selectable?: boolean;
3739
allowSelectAllPages?: boolean;
3840
selectionActions?: ButtonProps[];
41+
initiallySelectedZakenOnPage?: Zaak[];
3942

4043
extraFields?: TypedField[];
4144
filterSelectionZaken?: ZaakSelectionZaakFilter;
4245
getSelectionDetail?: ZaakSelectionDetailGetter;
4346

4447
dataGridProps?: Partial<DataGridProps>;
48+
49+
onClearZaakSelection?: () => void; // FIXME: REMOVE?
4550
}>;
4651

4752
export function BaseListView({
@@ -54,8 +59,10 @@ export function BaseListView({
5459
paginatedZaken,
5560
secondaryNavigationItems,
5661

62+
selectable = true,
5763
allowSelectAllPages,
5864
selectionActions,
65+
initiallySelectedZakenOnPage = [],
5966

6067
extraFields,
6168
filterSelectionZaken,
@@ -64,6 +71,8 @@ export function BaseListView({
6471
dataGridProps,
6572

6673
children,
74+
75+
onClearZaakSelection,
6776
}: BaseListViewProps) {
6877
const { state } = useNavigation();
6978
const [page, setPage] = usePage();
@@ -79,10 +88,11 @@ export function BaseListView({
7988

8089
// Selection.
8190
const [
82-
selectedZakenOnPage,
91+
_selectedZakenOnPage,
8392
handleSelect,
8493
{
85-
hasSelection,
94+
deSelectedZakenOnPage,
95+
hasSelection: _hasSelection,
8696
allPagesSelected,
8797
handleSelectAllPages,
8898
clearZaakSelection,
@@ -94,25 +104,51 @@ export function BaseListView({
94104
getSelectionDetail,
95105
);
96106

107+
// Merge `selectedZakenOnPage`.
108+
const selectedZakenOnPage = useMemo(() => {
109+
const deselectedZaakUrls = deSelectedZakenOnPage.map(
110+
(z) => z.url as string,
111+
);
112+
const filteredInitiallySelectedZakenOnPage =
113+
initiallySelectedZakenOnPage.filter(
114+
(z) => !deselectedZaakUrls.includes(z.url as string),
115+
);
116+
117+
return [...filteredInitiallySelectedZakenOnPage, ..._selectedZakenOnPage];
118+
}, [
119+
deSelectedZakenOnPage,
120+
initiallySelectedZakenOnPage,
121+
_selectedZakenOnPage,
122+
]);
123+
124+
// Merge `hasSelection`.
125+
const hasSelection = _hasSelection || selectedZakenOnPage.length > 0;
126+
127+
const handleClearZaakSelection = () => {
128+
clearZaakSelection();
129+
onClearZaakSelection?.();
130+
};
131+
97132
// Selection actions.
98133
const getSelectionActions = useCallback(() => {
99-
const fixedItems = hasSelection
100-
? ([
101-
{
102-
children: (
103-
<>
104-
<Solid.ExclamationTriangleIcon />
105-
Huidige selectie wissen
106-
</>
107-
),
108-
variant: "warning",
109-
wrap: false,
110-
onClick: clearZaakSelection,
111-
},
112-
] as ButtonProps[])
113-
: [];
134+
const fixedItems =
135+
selectable && hasSelection
136+
? ([
137+
{
138+
children: (
139+
<>
140+
<Solid.ExclamationTriangleIcon />
141+
Huidige selectie wissen
142+
</>
143+
),
144+
variant: "warning",
145+
wrap: false,
146+
onClick: handleClearZaakSelection,
147+
},
148+
] as ButtonProps[])
149+
: [];
114150
return [...(selectionActions || []), ...fixedItems];
115-
}, [hasSelection, selectedZakenOnPage, selectionActions]);
151+
}, [selectable, hasSelection, selectedZakenOnPage, selectionActions]);
116152

117153
return (
118154
<ListTemplate
@@ -128,7 +164,7 @@ export function BaseListView({
128164
fieldsSelectable: true,
129165
pageSize: 100,
130166
showPaginator: true,
131-
selectable: true,
167+
selectable: selectable,
132168
filterable: true,
133169
tableLayout: "fixed",
134170

@@ -142,7 +178,9 @@ export function BaseListView({
142178
objectList: paginatedZaken.results as unknown as AttributeData[],
143179
page,
144180
sort: sort,
145-
selected: selectedZakenOnPage as unknown as AttributeData[],
181+
selected: selectable
182+
? (selectedZakenOnPage as unknown as AttributeData[])
183+
: [],
146184
selectionActions: getSelectionActions(),
147185

148186
onFieldsChange: setFields,

frontend/src/pages/destructionlist/detail/DestructionListDetail.stories.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ const meta: Meta<typeof DestructionListDetailPage> = {
7777
status: 200,
7878
response: FIXTURE_SELECTIELIJSTKLASSE_CHOICES,
7979
},
80+
{
81+
url: "http://localhost:8000/api/v1/_zaaktypen-choices/?inDestructionList=00000000-0000-0000-0000-000000000000",
82+
method: "GET",
83+
status: 200,
84+
response: FIXTURE_SELECTIELIJSTKLASSE_CHOICES,
85+
},
8086
],
8187
},
8288
};

frontend/src/pages/destructionlist/detail/DestructionListDetail.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ import { useSecondaryNavigation } from "./hooks/useSecondaryNavigation";
1414
export function DestructionListDetailPage() {
1515
const { destructionList } = useLoaderData() as DestructionListDetailContext;
1616
const isInReview = destructionList.status === "changes_requested";
17-
1817
const secondaryNavigationItems = useSecondaryNavigation();
1918

19+
// TODO: SEPARATE ROUTE?
20+
if (!isInReview) {
21+
return <DestructionListEdit />;
22+
}
23+
24+
// FIXME: MIGRATE TO NEW APPROACH (NEW URL?)
2025
return (
2126
<CardBaseTemplate secondaryNavigationItems={secondaryNavigationItems}>
2227
<DestructionListToolbar />
23-
{isInReview ? <DestructionListProcessReview /> : <DestructionListEdit />}
28+
<DestructionListProcessReview />
2429
</CardBaseTemplate>
2530
);
2631
}

0 commit comments

Comments
 (0)