From 7c84145223f0be0c0f26b4c85578751d569cd41a Mon Sep 17 00:00:00 2001 From: Julian Roeland Date: Fri, 22 Nov 2024 12:10:23 +0100 Subject: [PATCH 1/4] :sparkles: [#498] feat: implement prepopulation of zaken --- frontend/src/lib/api/destructionListsItem.ts | 1 + .../review/DestructionListReview.loader.ts | 13 +++++++----- .../review/DestructionListReview.stories.tsx | 10 ++++++---- .../review/DestructionListReview.tsx | 20 +++++++++++-------- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/frontend/src/lib/api/destructionListsItem.ts b/frontend/src/lib/api/destructionListsItem.ts index 661c22176..49dfe293b 100644 --- a/frontend/src/lib/api/destructionListsItem.ts +++ b/frontend/src/lib/api/destructionListsItem.ts @@ -33,6 +33,7 @@ export async function listDestructionListItems( page_size?: number; "item-processing_status"?: ProcessingStatus; "item-status": DestructionListItemStatus; // TODO ? + "item-order_review_ignored"?: string; }, ) { const response = await request("GET", "/destruction-list-items/", { diff --git a/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts b/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts index 39a1d2095..b72758ae4 100644 --- a/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts +++ b/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts @@ -6,6 +6,10 @@ import { DestructionList, getDestructionList, } from "../../../lib/api/destructionLists"; +import { + PaginatedDestructionListItems, + listDestructionListItems, +} from "../../../lib/api/destructionListsItem"; import { Review, ReviewItemWithZaak, @@ -17,7 +21,6 @@ import { getLatestReviewResponse, } from "../../../lib/api/reviewResponse"; import { listReviewers } from "../../../lib/api/reviewers"; -import { PaginatedZaken, listZaken } from "../../../lib/api/zaken"; import { canReviewDestructionListRequired, loginRequired, @@ -31,7 +34,7 @@ export type DestructionListReviewContext = { destructionList: DestructionList; logItems: AuditLogItem[]; - paginatedZaken: PaginatedZaken; + paginatedZaken: PaginatedDestructionListItems; review: Review; reviewItems?: ReviewItemWithZaak[]; reviewResponse?: ReviewResponse; @@ -76,9 +79,9 @@ export const destructionListReviewLoader = loginRequired( reviewItemsPromise, reviewResponsePromise, listReviewers(), - listZaken({ - ...objParams, - in_destruction_list: uuid, + listDestructionListItems(uuid, { + "item-order_review_ignored": String(true), + ...(objParams as unknown as URLSearchParams), }), ]); diff --git a/frontend/src/pages/destructionlist/review/DestructionListReview.stories.tsx b/frontend/src/pages/destructionlist/review/DestructionListReview.stories.tsx index fd25615ac..1eda330e3 100644 --- a/frontend/src/pages/destructionlist/review/DestructionListReview.stories.tsx +++ b/frontend/src/pages/destructionlist/review/DestructionListReview.stories.tsx @@ -12,7 +12,7 @@ import { destructionListAssigneesFactory, destructionListFactory, } from "../../../fixtures/destructionList"; -import { paginatedZakenFactory } from "../../../fixtures/paginatedZaken"; +import { paginatedDestructionListItemsFactory } from "../../../fixtures/destructionListItem"; import { reviewFactory } from "../../../fixtures/review"; import { beoordelaarFactory, @@ -167,7 +167,7 @@ const FIXTURE: DestructionListReviewContext = { logItems: [], review: reviewFactory(), reviewers: usersFactory(), - paginatedZaken: paginatedZakenFactory(), + paginatedZaken: paginatedDestructionListItemsFactory(), }; export const ReviewerCanApproveZaak: Story = { @@ -186,8 +186,10 @@ export const ReviewerCanApproveZaak: Story = { }); const approve = approves[0]; await userEvent.click(approve); - const checkbox = await canvas.findByRole("checkbox", { checked: true }); - await expect(checkbox).toBeInTheDocument(); + // Find all checkboxes + const checkboxes = await canvas.findAllByRole("checkbox"); + const checkbox = checkboxes[0]; + await expect(checkbox).toBeChecked(); }, }; diff --git a/frontend/src/pages/destructionlist/review/DestructionListReview.tsx b/frontend/src/pages/destructionlist/review/DestructionListReview.tsx index fc5e28ba0..2ec3f14cd 100644 --- a/frontend/src/pages/destructionlist/review/DestructionListReview.tsx +++ b/frontend/src/pages/destructionlist/review/DestructionListReview.tsx @@ -7,7 +7,7 @@ import { useConfirm, usePrompt, } from "@maykin-ui/admin-ui"; -import React, { useMemo } from "react"; +import { useMemo } from "react"; import { useLoaderData } from "react-router-dom"; import { @@ -60,6 +60,9 @@ export function DestructionListReviewPage() { reviewItems, reviewResponse, } = useLoaderData() as DestructionListReviewContext; + const zakenResults = paginatedZaken.results + .map((zaak) => zaak.zaak) + .filter((zaak) => zaak !== null) as Zaak[]; const user = useWhoAmI(); @@ -70,7 +73,7 @@ export function DestructionListReviewPage() { comment: string; }>( storageKey, - paginatedZaken.results, + zakenResults, filterSelectionZaken, getSelectionDetail, RestBackend, @@ -84,7 +87,7 @@ export function DestructionListReviewPage() { comment: string; }>( storageKey, - paginatedZaken.results.map((z) => z.url as string), + paginatedZaken.results.map((z) => z.zaak?.url as string), true, RestBackend, ); @@ -125,14 +128,15 @@ export function DestructionListReviewPage() { uuid, destructionList.status, ); - const zaakReviewStatusBadges = useZaakReviewStatusBadges( - paginatedZaken.results, - { ...approvedZaakSelection, ...excludedZaakSelection }, - ); + const zaakReviewStatusBadges = useZaakReviewStatusBadges(zakenResults, { + ...approvedZaakSelection, + ...excludedZaakSelection, + }); // The object list of the current page with review actions appended. const objectList = useMemo(() => { - return paginatedZaken.results.map((zaak) => { + return paginatedZaken.results.map((result) => { + const zaak = result.zaak as Zaak; const badge = zaakReviewStatusBadges[zaak.url as string].badge; const actions = getActionsToolbarForZaak(zaak); return { ...zaak, Beoordeling: badge, Acties: actions }; From ed2930aab33b676edfdeffc007c8c421fb5d340c Mon Sep 17 00:00:00 2001 From: Julian Roeland Date: Thu, 28 Nov 2024 11:22:48 +0100 Subject: [PATCH 2/4] :bug: - fix: fixed incorrect type assertion --- .../pages/destructionlist/review/DestructionListReview.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/destructionlist/review/DestructionListReview.tsx b/frontend/src/pages/destructionlist/review/DestructionListReview.tsx index 2ec3f14cd..6004ef366 100644 --- a/frontend/src/pages/destructionlist/review/DestructionListReview.tsx +++ b/frontend/src/pages/destructionlist/review/DestructionListReview.tsx @@ -87,7 +87,7 @@ export function DestructionListReviewPage() { comment: string; }>( storageKey, - paginatedZaken.results.map((z) => z.zaak?.url as string), + zakenResults.map((zaak) => zaak.url as string), true, RestBackend, ); @@ -135,14 +135,13 @@ export function DestructionListReviewPage() { // The object list of the current page with review actions appended. const objectList = useMemo(() => { - return paginatedZaken.results.map((result) => { - const zaak = result.zaak as Zaak; + return zakenResults.map((zaak) => { const badge = zaakReviewStatusBadges[zaak.url as string].badge; const actions = getActionsToolbarForZaak(zaak); return { ...zaak, Beoordeling: badge, Acties: actions }; }); }, [ - paginatedZaken, + zakenResults, zaakReviewStatusBadges, reviewItems, excludedZaakSelection, From d0074e9a013d5dfca89b27cf070c3adadbf6882c Mon Sep 17 00:00:00 2001 From: Julian Roeland Date: Tue, 3 Dec 2024 16:07:05 +0100 Subject: [PATCH 3/4] :ok_hand: - pr changes --- frontend/src/fixtures/destructionListItem.ts | 3 +++ .../src/hooks/useZaakReviewStatusBadges.tsx | 21 ++++++++++++++----- frontend/src/lib/api/destructionListsItem.ts | 19 +++++++++++++---- frontend/src/lib/api/review.ts | 2 +- frontend/src/pages/constants.tsx | 2 ++ .../review/DestructionListReview.loader.ts | 4 ++-- .../review/DestructionListReview.tsx | 19 +++++++++++++---- 7 files changed, 54 insertions(+), 16 deletions(-) diff --git a/frontend/src/fixtures/destructionListItem.ts b/frontend/src/fixtures/destructionListItem.ts index fe08291f6..bed7e13b1 100644 --- a/frontend/src/fixtures/destructionListItem.ts +++ b/frontend/src/fixtures/destructionListItem.ts @@ -12,6 +12,7 @@ export const FIXTURE_DESTRUCTION_LIST_ITEM: DestructionListItem = { zaak: zaakFactory(), processingStatus: "new", plannedDestructionDate: null, + reviewAdviceIgnored: null, }; export const FIXTURE_DESTRUCTION_LIST_ITEM_DELETED: DestructionListItem = { pk: 2, @@ -20,6 +21,7 @@ export const FIXTURE_DESTRUCTION_LIST_ITEM_DELETED: DestructionListItem = { zaak: null, processingStatus: "succeeded", plannedDestructionDate: "2026-01-01T00:00:00Z", + reviewAdviceIgnored: null, }; export const FIXTURE_DESTRUCTION_LIST_ITEM_FAILED: DestructionListItem = { pk: 3, @@ -28,6 +30,7 @@ export const FIXTURE_DESTRUCTION_LIST_ITEM_FAILED: DestructionListItem = { zaak: zaakFactory(), processingStatus: "failed", plannedDestructionDate: "2026-01-01T00:00:00Z", + reviewAdviceIgnored: null, }; export const destructionListItemFactory = createObjectFactory( diff --git a/frontend/src/hooks/useZaakReviewStatusBadges.tsx b/frontend/src/hooks/useZaakReviewStatusBadges.tsx index 89acd95ea..3b942c364 100644 --- a/frontend/src/hooks/useZaakReviewStatusBadges.tsx +++ b/frontend/src/hooks/useZaakReviewStatusBadges.tsx @@ -16,14 +16,27 @@ import { export function useZaakReviewStatusBadges( zakenOnPage: Zaak[], reviewedZaakSelectionOnPage: ZaakSelection<{ approved: boolean }>, + reviewAdviceIgnoredResults: Record, // Map of reviewAdviceIgnored ): Record { const statuses = useZaakReviewStatuses( zakenOnPage, reviewedZaakSelectionOnPage, ); + return useMemo(() => { const badges = zakenOnPage.map((z) => { const status = statuses[z.url as string]; + const reviewAdviceIgnored = reviewAdviceIgnoredResults[z.url as string]; + + if (reviewAdviceIgnored) { + // Display "Herboordelen" badge for reviewAdviceIgnored zaken + return ( + // @ts-expect-error - style props not supported (yet?) + + Herboordelen + + ); + } if (typeof status === "boolean") { if (status) { @@ -37,8 +50,7 @@ export function useZaakReviewStatusBadges( return ( // @ts-expect-error - style props not supported (yet?) - - Uitgezonderd + Uitgezonderd ); } @@ -46,8 +58,7 @@ export function useZaakReviewStatusBadges( return ( // @ts-expect-error - style props not supported (yet?) - - Niet beoordeeld + Niet beoordeeld ); } @@ -58,5 +69,5 @@ export function useZaakReviewStatusBadges( { badge: badges[i], status: statuses[z.url as string] }, ]); return Object.fromEntries(entries); - }, [statuses]); + }, [statuses, reviewAdviceIgnoredResults, zakenOnPage]); } diff --git a/frontend/src/lib/api/destructionListsItem.ts b/frontend/src/lib/api/destructionListsItem.ts index 49dfe293b..3ccc22f0c 100644 --- a/frontend/src/lib/api/destructionListsItem.ts +++ b/frontend/src/lib/api/destructionListsItem.ts @@ -10,6 +10,7 @@ export type DestructionListItem = { zaak: Zaak | null; processingStatus: ProcessingStatus; plannedDestructionDate: string | null; + reviewAdviceIgnored: boolean | null; }; export interface ZaakItem extends Zaak { @@ -32,15 +33,25 @@ export async function listDestructionListItems( page?: number; page_size?: number; "item-processing_status"?: ProcessingStatus; - "item-status": DestructionListItemStatus; // TODO ? - "item-order_review_ignored"?: string; + "item-status"?: DestructionListItemStatus; + "item-order_review_ignored"?: string | boolean; }, ) { + if (params && !(params instanceof URLSearchParams)) { + if (typeof params["item-order_review_ignored"] === "boolean") { + params["item-order_review_ignored"] = String( + params["item-order_review_ignored"], + ); + } + } + + // Use the params object directly in the request const response = await request("GET", "/destruction-list-items/", { "item-destruction_list": destructionListUuid, "item-status": "suggested", - ...params, - } as typeof params & { "item-destruction_list": string }); + ...((params as Record) || {}), + }); + const promise: Promise = response.json(); return promise; } diff --git a/frontend/src/lib/api/review.ts b/frontend/src/lib/api/review.ts index 89596adee..5281c5ead 100644 --- a/frontend/src/lib/api/review.ts +++ b/frontend/src/lib/api/review.ts @@ -5,7 +5,7 @@ import { request } from "./request"; export type Review = { destructionList: string; - decision: "accepted" | "rejected"; + decision: "accepted" | "rejected" | "ignored_review"; listFeedback: string; pk?: number; author?: User; diff --git a/frontend/src/pages/constants.tsx b/frontend/src/pages/constants.tsx index 2a16f8d0f..16e502780 100644 --- a/frontend/src/pages/constants.tsx +++ b/frontend/src/pages/constants.tsx @@ -10,6 +10,7 @@ import { Review } from "../lib/api/review"; export const REVIEW_DECISION_MAPPING: Record = { accepted: "Goedgekeurd", rejected: "Afgewezen", + ignored_review: "Herboordelen", }; export const REVIEW_DECISION_LEVEL_MAPPING: Record< @@ -18,6 +19,7 @@ export const REVIEW_DECISION_LEVEL_MAPPING: Record< > = { accepted: "success", rejected: "danger", + ignored_review: "info", }; export const STATUSES_ELIGIBLE_FOR_EDIT = ["new", "changes_requested"]; diff --git a/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts b/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts index b72758ae4..d9671eaca 100644 --- a/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts +++ b/frontend/src/pages/destructionlist/review/DestructionListReview.loader.ts @@ -80,8 +80,8 @@ export const destructionListReviewLoader = loginRequired( reviewResponsePromise, listReviewers(), listDestructionListItems(uuid, { - "item-order_review_ignored": String(true), - ...(objParams as unknown as URLSearchParams), + "item-order_review_ignored": true, + ...objParams, }), ]); diff --git a/frontend/src/pages/destructionlist/review/DestructionListReview.tsx b/frontend/src/pages/destructionlist/review/DestructionListReview.tsx index 6004ef366..fc2549bcb 100644 --- a/frontend/src/pages/destructionlist/review/DestructionListReview.tsx +++ b/frontend/src/pages/destructionlist/review/DestructionListReview.tsx @@ -123,15 +123,26 @@ export function DestructionListReviewPage() { ), ); + const reviewAdviceIgnoredResults = Object.fromEntries( + paginatedZaken.results.map((result) => [ + result.zaak?.url as string, + result.reviewAdviceIgnored || false, + ]), + ); + const submitAction = useSubmitAction(); const destructionListReviewKey = getDestructionListReviewKey( uuid, destructionList.status, ); - const zaakReviewStatusBadges = useZaakReviewStatusBadges(zakenResults, { - ...approvedZaakSelection, - ...excludedZaakSelection, - }); + const zaakReviewStatusBadges = useZaakReviewStatusBadges( + zakenResults, + { + ...approvedZaakSelection, + ...excludedZaakSelection, + }, + reviewAdviceIgnoredResults, + ); // The object list of the current page with review actions appended. const objectList = useMemo(() => { From 0fd3ad33c4483a9ab7e752d2023a159b31b6c999 Mon Sep 17 00:00:00 2001 From: Julian Roeland Date: Tue, 3 Dec 2024 20:26:25 +0100 Subject: [PATCH 4/4] :ok_hand: - fix: updated the icon --- frontend/src/hooks/useZaakReviewStatusBadges.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/hooks/useZaakReviewStatusBadges.tsx b/frontend/src/hooks/useZaakReviewStatusBadges.tsx index 3b942c364..836c6bf0d 100644 --- a/frontend/src/hooks/useZaakReviewStatusBadges.tsx +++ b/frontend/src/hooks/useZaakReviewStatusBadges.tsx @@ -33,7 +33,7 @@ export function useZaakReviewStatusBadges( return ( // @ts-expect-error - style props not supported (yet?) - Herboordelen + Herboordelen ); }