From 42f9b56f895886d34db150aeb11f3effea01b0b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=C3=A8s=20Adem?= Date: Mon, 7 Oct 2024 20:26:52 +0200 Subject: [PATCH 1/2] feat: extract card component for consistency + minor ui fixes --- src/app/applications/[id]/TermsAcceptance.tsx | 4 + src/app/applications/[id]/sidebarItems.tsx | 18 +- src/app/basket/page.tsx | 2 +- src/app/datasets/DatasetCard.tsx | 64 +++++++ .../datasets}/DatasetList.tsx | 8 +- src/app/datasets/DatasetListContainer.tsx | 2 +- src/app/datasets/datasetCardItems.ts | 57 ++++++ .../requests/applications/ApplicationCard.tsx | 23 +++ .../requests/applications/ApplicationItem.tsx | 66 ------- src/app/requests/applications/DatasetList.tsx | 29 ---- .../applications/applicationCardItems.ts | 38 ++++ src/app/requests/applications/index.tsx | 4 +- .../entitlements/EmptyEntitlements.tsx | 2 +- .../requests/entitlements/EntitlementCard.tsx | 26 +-- .../entitlements/EntitlementsList.tsx | 8 +- .../entitlements/entitlementCardItems.ts | 30 ++++ src/components/Card.tsx | 91 ++++++++++ src/components/DatasetCard.tsx | 162 ------------------ 18 files changed, 344 insertions(+), 290 deletions(-) create mode 100644 src/app/datasets/DatasetCard.tsx rename src/{components => app/datasets}/DatasetList.tsx (75%) create mode 100644 src/app/datasets/datasetCardItems.ts create mode 100644 src/app/requests/applications/ApplicationCard.tsx delete mode 100644 src/app/requests/applications/ApplicationItem.tsx delete mode 100644 src/app/requests/applications/DatasetList.tsx create mode 100644 src/app/requests/applications/applicationCardItems.ts create mode 100644 src/app/requests/entitlements/entitlementCardItems.ts create mode 100644 src/components/Card.tsx delete mode 100644 src/components/DatasetCard.tsx diff --git a/src/app/applications/[id]/TermsAcceptance.tsx b/src/app/applications/[id]/TermsAcceptance.tsx index 2eb33ad3..71840a8b 100644 --- a/src/app/applications/[id]/TermsAcceptance.tsx +++ b/src/app/applications/[id]/TermsAcceptance.tsx @@ -50,6 +50,10 @@ export default function TermsAcceptance() { } }; + if (!application?.licenses || application?.licenses.length === 0) { + return

No terms and conditions have been defined.

; + } + return (
{alert && ( diff --git a/src/app/applications/[id]/sidebarItems.tsx b/src/app/applications/[id]/sidebarItems.tsx index a1bc3183..7f6fb8c6 100644 --- a/src/app/applications/[id]/sidebarItems.tsx +++ b/src/app/applications/[id]/sidebarItems.tsx @@ -2,14 +2,18 @@ // // SPDX-License-Identifier: Apache-2.0 -import DatasetList from "@/app/requests/applications/DatasetList"; import { createTextItem, SidebarItem } from "@/components/Sidebar"; import { RetrievedApplication } from "@/types/application.types"; import { formatApplicationProp } from "@/utils/application"; import { formatDateTime } from "@/utils/formatDate"; -import { faHistory, faUser } from "@fortawesome/free-solid-svg-icons"; +import { + faDatabase, + faHistory, + faUser, +} from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import TermsAcceptance from "./TermsAcceptance"; +import { getLabelName } from "@/utils/getLabelName"; export function createApplicationSidebarItems( application: RetrievedApplication @@ -19,7 +23,15 @@ export function createApplicationSidebarItems( return [ { label: "Datasets", - value: , + value: datasets.map((dataset, index) => ( + + +

{getLabelName(dataset.title)}

+
+ )), }, { label: "Participants", diff --git a/src/app/basket/page.tsx b/src/app/basket/page.tsx index 98f375d8..ada4a56a 100644 --- a/src/app/basket/page.tsx +++ b/src/app/basket/page.tsx @@ -13,7 +13,7 @@ import { useDatasetBasket } from "@/providers/DatasetBasketProvider"; import { createApplication } from "@/services/daam/index.client"; import { faPaperPlane, faPlusCircle } from "@fortawesome/free-solid-svg-icons"; import { signIn, useSession } from "next-auth/react"; -import DatasetList from "../../components/DatasetList"; +import DatasetList from "../datasets/DatasetList"; import { AxiosError } from "axios"; export default function Page() { diff --git a/src/app/datasets/DatasetCard.tsx b/src/app/datasets/DatasetCard.tsx new file mode 100644 index 00000000..7accde18 --- /dev/null +++ b/src/app/datasets/DatasetCard.tsx @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +import Button from "@/components/Button"; +import { useWindowSize } from "@/hooks"; +import { useDatasetBasket } from "@/providers/DatasetBasketProvider"; +import { SearchedDataset } from "@/services/discovery/types/dataset.types"; +import { truncateDescription } from "@/utils/textProcessing"; +import { faMinusCircle, faPlusCircle } from "@fortawesome/free-solid-svg-icons"; +import Card, { CardItem } from "../../components/Card"; + +type DatasetCardProps = { + dataset: SearchedDataset; + cardItems: CardItem[]; +}; + +function DatasetCard({ dataset, cardItems }: Readonly) { + const screenSize = useWindowSize(); + const truncatedDesc = dataset.description + ? truncateDescription(dataset.description, screenSize) + : null; + + const { basket, addDatasetToBasket, removeDatasetFromBasket, isLoading } = + useDatasetBasket(); + + const isInBasket = basket.some((ds) => ds.id === dataset.id); + + const toggleDatasetInBasket = (e: React.MouseEvent) => { + e.preventDefault(); + if (isInBasket) { + removeDatasetFromBasket(dataset); + } else { + addDatasetToBasket(dataset); + } + }; + + const hasIdentifier = !!dataset.identifier; + const buttonDisabled = isLoading || !hasIdentifier; + + return ( + theme.label)} + description={truncatedDesc || "No description available"} + cardItems={cardItems} + keywords={dataset.keywords?.map((keyword) => keyword.label)} + button={ +
- {children} - - ); -} - -export default DatasetCard; From abef59e5dd1d5d1776155dd4471c41ccdaab57e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=C3=A8s=20Adem?= Date: Tue, 8 Oct 2024 15:07:00 +0200 Subject: [PATCH 2/2] test: card items --- .../__tests__/datasetCardItems.test.ts | 69 +++++++++++++++ .../__tests__/applicationCardItems.test.ts | 49 +++++++++++ .../__tests__/entitlementCardItems.test.ts | 84 +++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 src/app/datasets/__tests__/datasetCardItems.test.ts create mode 100644 src/app/requests/applications/__tests__/applicationCardItems.test.ts create mode 100644 src/app/requests/entitlements/__tests__/entitlementCardItems.test.ts diff --git a/src/app/datasets/__tests__/datasetCardItems.test.ts b/src/app/datasets/__tests__/datasetCardItems.test.ts new file mode 100644 index 00000000..d561aa5c --- /dev/null +++ b/src/app/datasets/__tests__/datasetCardItems.test.ts @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +import { SearchedDataset } from "@/services/discovery/types/dataset.types"; +import { createDatasetCardItems } from "../datasetCardItems"; + +describe("datasetCardItems", () => { + beforeEach(() => { + global.window = {} as unknown as Window & typeof globalThis; + }); + + afterEach(() => { + global.window = undefined as unknown as Window & typeof globalThis; + }); + + it("should return dataset card items", () => { + const dataset: SearchedDataset = { + id: "1", + title: "", + description: "dataset1 description", + themes: [{ value: "theme1", label: "theme1" }], + keywords: [ + { + label: "keyword1", + value: "keyword1", + }, + { + label: "keyword2", + value: "keyword2", + }, + ], + distributions: [ + { + id: "r", + title: "distribution1", + description: "distribution1 description", + format: { + label: "format1", + value: "format1", + }, + licenses: [], + createdAt: "2022-01-01T00:00:00.000Z", + modifiedAt: "2022-01-01T00:00:00.000Z", + uri: "distribution1", + }, + ], + organization: { + id: "1", + title: "organization1", + imageUrl: "", + numberOfDatasets: 0, + name: "organization1", + description: "organization1 description", + }, + createdAt: "2024-03-01T00:00:00.000Z", + modifiedAt: "", + recordsCount: 21, + }; + + const items = createDatasetCardItems(dataset); + expect(items.length).toBe(5); + expect(items[0].text).toBe("Created on 1 March 2024"); + expect(items[1].text).toBe(""); + expect(items[2].text).toBe("Published by organization1"); + expect(items[3].text).toBe("1 Distribution"); + expect(items[4].text).toBe("21 Records"); + }); +}); diff --git a/src/app/requests/applications/__tests__/applicationCardItems.test.ts b/src/app/requests/applications/__tests__/applicationCardItems.test.ts new file mode 100644 index 00000000..2478611e --- /dev/null +++ b/src/app/requests/applications/__tests__/applicationCardItems.test.ts @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +import { createApplicationCardItems } from "../applicationCardItems"; +import { ListedApplication } from "@/types/application.types"; + +describe("applicationCardItems", () => { + beforeEach(() => { + global.window = {} as unknown as Window & typeof globalThis; + }); + + afterEach(() => { + global.window = undefined as unknown as Window & typeof globalThis; + }); + + it("should return application card items", () => { + const application: ListedApplication = { + id: 1, + title: "application1", + description: "app 1 description", + datasets: [], + currentState: "submitted", + createdAt: "2024-07-12", + stateChangedAt: "2024-08-03", + }; + + const items = createApplicationCardItems(application); + expect(items.length).toBe(2); + expect(items[0].text).toBe("Created on 12 July 2024"); + expect(items[1].text).toBe("Modified on 3 August 2024"); + }); + it("should return applicationCardItems with empty strings when dates are not empty", () => { + const application: ListedApplication = { + id: 1, + title: "application1", + description: "app 1 description", + datasets: [], + currentState: "submitted", + createdAt: "", + stateChangedAt: "", + }; + + const items = createApplicationCardItems(application); + expect(items.length).toBe(2); + expect(items[0].text).toBe(""); + expect(items[1].text).toBe(""); + }); +}); diff --git a/src/app/requests/entitlements/__tests__/entitlementCardItems.test.ts b/src/app/requests/entitlements/__tests__/entitlementCardItems.test.ts new file mode 100644 index 00000000..78a4aa6b --- /dev/null +++ b/src/app/requests/entitlements/__tests__/entitlementCardItems.test.ts @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +import { SearchedDataset } from "@/services/discovery/types/dataset.types"; +import { createEntitlementCardItems } from "../entitlementCardItems"; + +describe("entitlementCardItems", () => { + beforeEach(() => { + global.window = {} as unknown as Window & typeof globalThis; + }); + + afterEach(() => { + global.window = undefined as unknown as Window & typeof globalThis; + }); + + it("should return entitlement Card items", () => { + const dataset: SearchedDataset = { + id: "1", + title: "", + description: "dataset1 description", + themes: [{ value: "theme1", label: "theme1" }], + keywords: [ + { + label: "keyword1", + value: "keyword1", + }, + { + label: "keyword2", + value: "keyword2", + }, + ], + distributions: [ + { + id: "1", + title: "distribution1", + description: "distribution1 description", + format: { + label: "format1", + value: "format1", + }, + licenses: [], + createdAt: "2022-01-01T00:00:00.000Z", + modifiedAt: "2022-01-01T00:00:00.000Z", + uri: "distribution1", + }, + { + id: "2", + title: "distribution2", + description: "distribution2 description", + format: { + label: "format1", + value: "format1", + }, + licenses: [], + createdAt: "2022-01-01T00:00:00.000Z", + modifiedAt: "2022-01-01T00:00:00.000Z", + uri: "distribution1", + }, + ], + organization: { + id: "1", + title: "organization1", + imageUrl: "", + numberOfDatasets: 0, + name: "organization1", + description: "organization1 description", + }, + createdAt: "2024-03-01T00:00:00.000Z", + modifiedAt: "", + }; + + const items = createEntitlementCardItems(dataset, "2024-06-23", ""); + + expect(items.length).toBe(7); + expect(items[0].text).toBe("Created on 1 March 2024"); + expect(items[1].text).toBe(""); + expect(items[2].text).toBe("Published by organization1"); + expect(items[3].text).toBe("2 Distributions"); + expect(items[4].text).toBe(""); + expect(items[5].text).toBe("Start: 23 June 2024"); + expect(items[6].text).toBe("End: N/A"); + }); +});