From 757e1a7844703f1d9e9d1fdf85eace6c122416ad Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Mon, 11 Dec 2023 17:12:13 -0500 Subject: [PATCH 01/31] add physical edition badge --- CHANGELOG.md | 1 + src/components/EditionCard/EditionCard.tsx | 17 +++++-- src/components/InstanceCard/InstanceCard.tsx | 20 ++++++-- src/util/EditionCardUtils.tsx | 53 ++++++++++++++++++-- 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce5383d4..d4f66a73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix: SFR-1839- pw automated test fix / update the login credentials - Refactor New Relic browser monitoring instrumentation - Update Playwright.yml to use same package versions as package.json +- Add Physical Edition badge to EDD editions ## [0.17.5] diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index dcd5a6cf..ac8ea849 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -5,6 +5,7 @@ import { CardHeading, Box, CardActions, + Flex, } from "@nypl/design-system-react-components"; import Link from "../Link/Link"; import { WorkEdition } from "~/src/types/DataModel"; @@ -42,6 +43,7 @@ export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ }; const coverUrl = EditionCardUtils.getCover(edition.links); + const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); return ( = ({ p="s" flexFlow={{ md: "column nowrap", lg: "row" }} alignItems={{ md: "flex-start", lg: "center" }} + sx={{ ".card-right": { maxWidth: { base: "100%", md: "200px" } } }} > - {editionYearElem(edition)} + + {editionYearElem(edition)} + {isPhysicalEdition && EditionCardUtils.getPhysicalEditionBadge()} + @@ -85,6 +93,7 @@ export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ {EditionCardUtils.getLanguageDisplayText(edition)} {EditionCardUtils.getLicense(previewItem)} + {isPhysicalEdition && EditionCardUtils.getScanAndDeliverBlurb()} {EditionCardUtils.getCtas( diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index 86c08639..086fa1a2 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -6,6 +6,7 @@ import { CardActions, CardContent, CardHeading, + Flex, } from "@nypl/design-system-react-components"; import EditionCardUtils from "~/src/util/EditionCardUtils"; import Link from "../Link/Link"; @@ -27,6 +28,7 @@ export const InstanceCard: React.FC<{ const edition = props.edition; const instance: Instance = props.instance; const previewItem = EditionCardUtils.getPreviewItem(instance.items); + const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); return ( - - {edition.publication_date - ? edition.publication_date - : "Edition Year Unknown"} + + + + {edition.publication_date + ? edition.publication_date + : "Edition Year Unknown"} + + {isPhysicalEdition && EditionCardUtils.getPhysicalEditionBadge()} +
@@ -56,6 +67,7 @@ export const InstanceCard: React.FC<{
{EditionCardUtils.getWorldCatElem(instance)}
{EditionCardUtils.getLicense(previewItem)} + {isPhysicalEdition && EditionCardUtils.getScanAndDeliverBlurb()}
{EditionCardUtils.getCtas( diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 00e2c5dc..0e821dcc 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -8,7 +8,14 @@ import { WorkEdition, Identifier, } from "../types/DataModel"; -import { Box, Button, Icon } from "@nypl/design-system-react-components"; +import { + Box, + Button, + Flex, + Icon, + Text, + StatusBadge, +} from "@nypl/design-system-react-components"; import Link from "~/src/components/Link/Link"; import { formatUrl, truncateStringOnWhitespace } from "./Util"; import { @@ -344,9 +351,9 @@ export default class EditionCardUtils { to={`https://login.nypl.org/auth/login?redirect_uri=${encodeURIComponent( window.location.href )}`} - linkType="button" + linkType="buttonSecondary" > - Log in for options + Log in to request scan ); @@ -372,4 +379,44 @@ export default class EditionCardUtils { }) ); } + + static getPhysicalEditionBadge() { + return Physical Edition; + } + + static getScanAndDeliverBlurb() { + return ( + + + + A partial scan of this edition can be requested via NYPL's{" "} + + Scan and Deliver + {" "} + service + + + ); + } + + static isAvailableOnline(item: ApiItem) { + return ( + item && + item.links.find((link: ItemLink) => { + return ( + link.flags["reader"] || link.flags["embed"] || link.flags["download"] + ); + }) + ); + } + + static isPhysicalEdition(item: ApiItem): boolean { + const availableOnline = this.isAvailableOnline(item); + const eddLink = + item && item.links + ? item.links.find((link) => link.flags.edd) + : undefined; + + return !availableOnline && eddLink !== undefined; + } } From ee19270a74c5ff869a17934d01adfd06288aec33 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Mon, 11 Dec 2023 17:33:58 -0500 Subject: [PATCH 02/31] update tests --- CHANGELOG.md | 2 +- src/components/CollectionItemCard/EddLink.tsx | 10 ++----- .../EditionCard/EditionCard.test.tsx | 27 ++++++++++++------- .../InstanceCard/InstanceCard.test.tsx | 23 ++++++++++------ src/util/EditionCardUtils.tsx | 17 +++--------- 5 files changed, 39 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a15fdd92..8ddc84d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ - Refactor New Relic browser monitoring instrumentation - Update Playwright.yml to use same package versions as package.json - Fix: reverse node to v18.18.2 -- Add Physical Edition badge to EDD editions +- Add Physical Edition badge and Scan and Deliver blurb to EDD editions ## [0.17.5] diff --git a/src/components/CollectionItemCard/EddLink.tsx b/src/components/CollectionItemCard/EddLink.tsx index bf7a973c..bc5e97bd 100644 --- a/src/components/CollectionItemCard/EddLink.tsx +++ b/src/components/CollectionItemCard/EddLink.tsx @@ -1,6 +1,4 @@ import React from "react"; -import { Box } from "@nypl/design-system-react-components"; -import { SCAN_AND_DELIVER_LINK } from "~/src/constants/links"; import { OpdsLink } from "~/src/types/OpdsModel"; import Link from "~/src/components/Link/Link"; @@ -11,17 +9,13 @@ export const EddLink: React.FC<{ if (isLoggedIn) { return ( <> - You can request a partial scan via NYPL - - Scan and Deliver - - Request + Request Scan ); @@ -35,7 +29,7 @@ export const EddLink: React.FC<{ )}`} linkType="button" > - Log in for options + Log in to request scan ); diff --git a/src/components/EditionCard/EditionCard.test.tsx b/src/components/EditionCard/EditionCard.test.tsx index 2ddb2f86..cda4b68d 100644 --- a/src/components/EditionCard/EditionCard.test.tsx +++ b/src/components/EditionCard/EditionCard.test.tsx @@ -98,17 +98,19 @@ describe("Edition with EDD", () => { expect(screen.queryByText("Download PDF")).toBeInTheDocument(); expect(screen.queryByText("Read Online")).toBeInTheDocument(); - expect(screen.queryByText("Log in for options")).not.toBeInTheDocument(); - expect(screen.queryByText("Request")).not.toBeInTheDocument(); + expect( + screen.queryByText("Log in to request scan") + ).not.toBeInTheDocument(); + expect(screen.queryByText("Request Scan")).not.toBeInTheDocument(); }); test("Shows Login button when EDD is available but user is not logged in", () => { render(); expect( - screen.getByRole("link", { name: "Log in for options" }) + screen.getByRole("link", { name: "Log in to request scan" }) ).toBeInTheDocument(); expect( - screen.getByRole("link", { name: "Log in for options" }) + screen.getByRole("link", { name: "Log in to request scan" }) ).toHaveAttribute( "href", expect.stringContaining("https://login.nypl.org/auth/login") @@ -117,23 +119,30 @@ describe("Edition with EDD", () => { expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); - test("Shows EDD Request button and 'Scan and Deliver' link when user is logged in", () => { + test("Shows EDD Request button when user is logged in", () => { // Set cookie before rendering the component document.cookie = `${NYPL_SESSION_ID}="randomvalue"`; render(); - expect(screen.getByRole("link", { name: "Request" })).toBeInTheDocument(); - expect(screen.getByRole("link", { name: "Request" })).toHaveAttribute( + expect( + screen.getByRole("link", { name: "Request Scan" }) + ).toBeInTheDocument(); + expect(screen.getByRole("link", { name: "Request Scan" })).toHaveAttribute( "href", expect.stringContaining("test-link-url") ); + expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); + expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); + }); + + test("Shows 'Physical Edition' badge and 'Scan and Deliver' link ", () => { + render(); + expect(screen.getByText("Physical Edition")).toBeInTheDocument(); expect( screen.getByRole("link", { name: "Scan and Deliver" }) ).toBeInTheDocument(); expect( screen.getByRole("link", { name: "Scan and Deliver" }) ).toHaveAttribute("href", "https://www.nypl.org/research/scan-and-deliver"); - expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); - expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); }); diff --git a/src/components/InstanceCard/InstanceCard.test.tsx b/src/components/InstanceCard/InstanceCard.test.tsx index e7827b7f..4ba9f336 100644 --- a/src/components/InstanceCard/InstanceCard.test.tsx +++ b/src/components/InstanceCard/InstanceCard.test.tsx @@ -166,7 +166,7 @@ describe("Instance with EDD", () => { expect(screen.queryByText("Download PDF")).toBeInTheDocument(); expect(screen.queryByText("Read Online")).toBeInTheDocument(); expect(screen.queryByText("Log in for options")).not.toBeInTheDocument(); - expect(screen.queryByText("Request")).not.toBeInTheDocument(); + expect(screen.queryByText("Request Scan")).not.toBeInTheDocument(); }); test("Shows Login button when EDD is available but user is not logged in", () => { @@ -174,10 +174,10 @@ describe("Instance with EDD", () => { ); expect( - screen.getByRole("link", { name: "Log in for options" }) + screen.getByRole("link", { name: "Log in to request scan" }) ).toBeInTheDocument(); expect( - screen.getByRole("link", { name: "Log in for options" }) + screen.getByRole("link", { name: "Log in to request scan" }) ).toHaveAttribute( "href", expect.stringContaining("https://login.nypl.org/auth/login") @@ -186,25 +186,32 @@ describe("Instance with EDD", () => { expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); - test("Shows EDD Request button and 'Scan and Deliver' link when user is logged in", () => { + test("Shows EDD Request button when user is logged in", () => { // Set cookie before rendering the component document.cookie = `${NYPL_SESSION_ID}="randomvalue"`; render( ); - expect(screen.getByRole("link", { name: "Request" })).toBeInTheDocument(); - expect(screen.getByRole("link", { name: "Request" })).toHaveAttribute( + expect( + screen.getByRole("link", { name: "Request Scan" }) + ).toBeInTheDocument(); + expect(screen.getByRole("link", { name: "Request Scan" })).toHaveAttribute( "href", expect.stringContaining("test-link-url") ); + expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); + expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); + }); + + test("Shows 'Physical Edition' badge and 'Scan and Deliver' link", () => { + render(); + expect(screen.getByText("Physical Edition")).toBeInTheDocument(); expect( screen.getByRole("link", { name: "Scan and Deliver" }) ).toBeInTheDocument(); expect( screen.getByRole("link", { name: "Scan and Deliver" }) ).toHaveAttribute("href", "https://www.nypl.org/research/scan-and-deliver"); - expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); - expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); }); diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 0e821dcc..2edec12a 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -27,6 +27,7 @@ import { import { ApiSearchQuery } from "../types/SearchQuery"; import { MediaTypes } from "../constants/mediaTypes"; import { trackCtaClick } from "../lib/adobe/Analytics"; +import { SCAN_AND_DELIVER_LINK } from "../constants/links"; // EditionCard holds all the methods needed to build an Edition Card export default class EditionCardUtils { @@ -324,22 +325,13 @@ export default class EditionCardUtils { if (isLoggedIn) { return ( <> - - You can request a partial scan via NYPL - - - Scan and Deliver - - Request + Request Scan ); @@ -390,10 +382,7 @@ export default class EditionCardUtils { A partial scan of this edition can be requested via NYPL's{" "} - - Scan and Deliver - {" "} - service + Scan and Deliver service ); From a400180aebe6c670020b27bdc4237ada24e01b7f Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Tue, 12 Dec 2023 13:45:35 -0500 Subject: [PATCH 03/31] render components directly --- src/components/EditionCard/EditionCard.tsx | 6 +++-- .../EditionCard/PhysicalEditionBadge.tsx | 6 +++++ .../EditionCard/ScanAndDeliverBlurb.tsx | 16 ++++++++++++ src/components/InstanceCard/InstanceCard.tsx | 6 +++-- src/util/EditionCardUtils.tsx | 26 +------------------ 5 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 src/components/EditionCard/PhysicalEditionBadge.tsx create mode 100644 src/components/EditionCard/ScanAndDeliverBlurb.tsx diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index ac8ea849..cc5299a2 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -13,6 +13,8 @@ import EditionCardUtils from "~/src/util/EditionCardUtils"; import { PLACEHOLDER_COVER_LINK } from "~/src/constants/editioncard"; import { useCookies } from "react-cookie"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; +import { PhysicalEditionBadge } from "./PhysicalEditionBadge"; +import { ScanAndDeliverBlurb } from "./ScanAndDeliverBlurb"; export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ edition, @@ -81,7 +83,7 @@ export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ > {editionYearElem(edition)} - {isPhysicalEdition && EditionCardUtils.getPhysicalEditionBadge()} + {isPhysicalEdition && }
@@ -93,7 +95,7 @@ export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ {EditionCardUtils.getLanguageDisplayText(edition)} {EditionCardUtils.getLicense(previewItem)} - {isPhysicalEdition && EditionCardUtils.getScanAndDeliverBlurb()} + {isPhysicalEdition && } {EditionCardUtils.getCtas( diff --git a/src/components/EditionCard/PhysicalEditionBadge.tsx b/src/components/EditionCard/PhysicalEditionBadge.tsx new file mode 100644 index 00000000..f8db1dbd --- /dev/null +++ b/src/components/EditionCard/PhysicalEditionBadge.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import { StatusBadge } from "@nypl/design-system-react-components"; + +export const PhysicalEditionBadge: React.FC = () => { + return Physical Edition; +}; diff --git a/src/components/EditionCard/ScanAndDeliverBlurb.tsx b/src/components/EditionCard/ScanAndDeliverBlurb.tsx new file mode 100644 index 00000000..72f54381 --- /dev/null +++ b/src/components/EditionCard/ScanAndDeliverBlurb.tsx @@ -0,0 +1,16 @@ +import { Flex, Icon, Text } from "@nypl/design-system-react-components"; +import React from "react"; +import Link from "../Link/Link"; +import { SCAN_AND_DELIVER_LINK } from "~/src/constants/links"; + +export const ScanAndDeliverBlurb: React.FC = () => { + return ( + + + + A partial scan of this edition can be requested via NYPL's{" "} + Scan and Deliver service + + + ); +}; diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index 086fa1a2..c5984bff 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -12,6 +12,8 @@ import EditionCardUtils from "~/src/util/EditionCardUtils"; import Link from "../Link/Link"; import { useCookies } from "react-cookie"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; +import { PhysicalEditionBadge } from "../EditionCard/PhysicalEditionBadge"; +import { ScanAndDeliverBlurb } from "../EditionCard/ScanAndDeliverBlurb"; // Creates an Instance card out of the Edition Year and Instance object // Note: Edition Year only needs to be passed because `instance.publication_date` @@ -55,7 +57,7 @@ export const InstanceCard: React.FC<{ ? edition.publication_date : "Edition Year Unknown"} - {isPhysicalEdition && EditionCardUtils.getPhysicalEditionBadge()} + {isPhysicalEdition && } @@ -67,7 +69,7 @@ export const InstanceCard: React.FC<{
{EditionCardUtils.getWorldCatElem(instance)}
{EditionCardUtils.getLicense(previewItem)} - {isPhysicalEdition && EditionCardUtils.getScanAndDeliverBlurb()} + {isPhysicalEdition && }
{EditionCardUtils.getCtas( diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 2edec12a..85e7172e 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -8,14 +8,7 @@ import { WorkEdition, Identifier, } from "../types/DataModel"; -import { - Box, - Button, - Flex, - Icon, - Text, - StatusBadge, -} from "@nypl/design-system-react-components"; +import { Box, Button, Icon } from "@nypl/design-system-react-components"; import Link from "~/src/components/Link/Link"; import { formatUrl, truncateStringOnWhitespace } from "./Util"; import { @@ -27,7 +20,6 @@ import { import { ApiSearchQuery } from "../types/SearchQuery"; import { MediaTypes } from "../constants/mediaTypes"; import { trackCtaClick } from "../lib/adobe/Analytics"; -import { SCAN_AND_DELIVER_LINK } from "../constants/links"; // EditionCard holds all the methods needed to build an Edition Card export default class EditionCardUtils { @@ -372,22 +364,6 @@ export default class EditionCardUtils { ); } - static getPhysicalEditionBadge() { - return Physical Edition; - } - - static getScanAndDeliverBlurb() { - return ( - - - - A partial scan of this edition can be requested via NYPL's{" "} - Scan and Deliver service - - - ); - } - static isAvailableOnline(item: ApiItem) { return ( item && From 82a024666fbb58c2e19b4b6a741cd1d691339db2 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Wed, 13 Dec 2023 17:25:46 -0500 Subject: [PATCH 04/31] add new badges and update styles --- CHANGELOG.md | 2 + src/components/CollectionItemCard/EddLink.tsx | 1 - .../EditionCard/CardRequiredBadge.tsx | 10 ++ src/components/EditionCard/EditionCard.tsx | 135 +++++++++++------- .../EditionCard/FeaturedEditionBadge.tsx | 10 ++ .../EditionCard/PhysicalEditionBadge.tsx | 2 +- .../EditionCard/ScanAndDeliverBlurb.tsx | 2 +- src/components/EditionDetail/Edition.tsx | 30 ++-- src/components/InstanceCard/InstanceCard.tsx | 107 ++++++++------ src/components/ResultsList/ResultsList.tsx | 6 +- src/components/Work/Work.tsx | 64 ++++----- src/util/EditionCardUtils.tsx | 1 - 12 files changed, 219 insertions(+), 151 deletions(-) create mode 100644 src/components/EditionCard/CardRequiredBadge.tsx create mode 100644 src/components/EditionCard/FeaturedEditionBadge.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ddc84d4..2ec47409 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ - Update Playwright.yml to use same package versions as package.json - Fix: reverse node to v18.18.2 - Add Physical Edition badge and Scan and Deliver blurb to EDD editions +- Add Library Card Required and Featured Editon badges +- Update styles for work and edition pages ## [0.17.5] diff --git a/src/components/CollectionItemCard/EddLink.tsx b/src/components/CollectionItemCard/EddLink.tsx index bc5e97bd..4638dc68 100644 --- a/src/components/CollectionItemCard/EddLink.tsx +++ b/src/components/CollectionItemCard/EddLink.tsx @@ -22,7 +22,6 @@ export const EddLink: React.FC<{ } else { return ( <> - May be available via NYPL

{ + return ( + + Library Card Required + + ); +}; diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index cc5299a2..c5a68d89 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -15,11 +15,14 @@ import { useCookies } from "react-cookie"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; import { PhysicalEditionBadge } from "./PhysicalEditionBadge"; import { ScanAndDeliverBlurb } from "./ScanAndDeliverBlurb"; +import { CardRequiredBadge } from "./CardRequiredBadge"; +import { FeaturedEditionBadge } from "./FeaturedEditionBadge"; -export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ - edition, - title, -}) => { +export const EditionCard: React.FC<{ + edition: WorkEdition; + title: string; + isFeaturedEdition?: boolean; +}> = ({ edition, title, isFeaturedEdition }) => { const [cookies] = useCookies([NYPL_SESSION_ID]); const previewItem = EditionCardUtils.getPreviewItem(edition.items); @@ -48,63 +51,85 @@ export const EditionCard: React.FC<{ edition: WorkEdition; title: string }> = ({ const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); return ( - - + {isPhysicalEdition && } + {isFeaturedEdition && } + + - - {editionYearElem(edition)} - {isPhysicalEdition && } - - - - - {EditionCardUtils.getPublisherAndLocation( - edition.publication_place, - edition.publishers + + + {editionYearElem(edition)} + {isPhysicalEdition && } + + + + + {EditionCardUtils.getPublisherAndLocation( + edition.publication_place, + edition.publishers + )} + {EditionCardUtils.getLanguageDisplayText(edition)} + + {EditionCardUtils.getLicense(previewItem)} + + + {isPhysicalEdition && } + + + {EditionCardUtils.getCtas( + previewItem, + title, + !!cookies[NYPL_SESSION_ID] )} - {EditionCardUtils.getLanguageDisplayText(edition)} - {EditionCardUtils.getLicense(previewItem)} - - {isPhysicalEdition && } - - - {EditionCardUtils.getCtas( - previewItem, - title, - !!cookies[NYPL_SESSION_ID] - )} - - +
+
+ ); }; diff --git a/src/components/EditionCard/FeaturedEditionBadge.tsx b/src/components/EditionCard/FeaturedEditionBadge.tsx new file mode 100644 index 00000000..e32fc54c --- /dev/null +++ b/src/components/EditionCard/FeaturedEditionBadge.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import { StatusBadge } from "@nypl/design-system-react-components"; + +export const FeaturedEditionBadge: React.FC = () => { + return ( + + Featured Edition + + ); +}; diff --git a/src/components/EditionCard/PhysicalEditionBadge.tsx b/src/components/EditionCard/PhysicalEditionBadge.tsx index f8db1dbd..eefa0f48 100644 --- a/src/components/EditionCard/PhysicalEditionBadge.tsx +++ b/src/components/EditionCard/PhysicalEditionBadge.tsx @@ -2,5 +2,5 @@ import React from "react"; import { StatusBadge } from "@nypl/design-system-react-components"; export const PhysicalEditionBadge: React.FC = () => { - return Physical Edition; + return Physical Edition; }; diff --git a/src/components/EditionCard/ScanAndDeliverBlurb.tsx b/src/components/EditionCard/ScanAndDeliverBlurb.tsx index 72f54381..8ae07f89 100644 --- a/src/components/EditionCard/ScanAndDeliverBlurb.tsx +++ b/src/components/EditionCard/ScanAndDeliverBlurb.tsx @@ -5,7 +5,7 @@ import { SCAN_AND_DELIVER_LINK } from "~/src/constants/links"; export const ScanAndDeliverBlurb: React.FC = () => { return ( - + A partial scan of this edition can be requested via NYPL's{" "} diff --git a/src/components/EditionDetail/Edition.tsx b/src/components/EditionDetail/Edition.tsx index cac149fa..5df912dc 100644 --- a/src/components/EditionDetail/Edition.tsx +++ b/src/components/EditionDetail/Edition.tsx @@ -124,15 +124,13 @@ const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = ( )} {featuredInstance && ( - <> - - Featured Copy - - - - - - + + + )} {edition.inCollections && edition.inCollections.length > 0 && ( @@ -178,11 +176,17 @@ const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = ( const contentPrimaryElement = ( <> - - {edition.instances && ( + {edition.instances && edition.instances.length > 1 && ( + + )} + {edition.instances && edition.instances.length > 1 && ( - All Copies + Other Copies = ( )} - {edition.instances.map((instance) => ( + {edition.instances.slice(1).map((instance) => ( = (props) => { // cookies defaults to be undefined if not fonud const [cookies] = useCookies([NYPL_SESSION_ID]); const edition = props.edition; const instance: Instance = props.instance; + const isFeaturedEdition = props.isFeaturedEdition; const previewItem = EditionCardUtils.getPreviewItem(instance.items); const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); return ( - - + {isPhysicalEdition && } + {isFeaturedEdition && } + + - - - {edition.publication_date - ? edition.publication_date - : "Edition Year Unknown"} - - {isPhysicalEdition && } - - - -
- {EditionCardUtils.getPublisherAndLocation( - instance.publication_place, - instance.publishers + + + + {edition.publication_date + ? edition.publication_date + : "Edition Year Unknown"} + + {isPhysicalEdition && } + + + +
+ {EditionCardUtils.getPublisherAndLocation( + instance.publication_place, + instance.publishers + )} +
+
{EditionCardUtils.getWorldCatElem(instance)}
+ {EditionCardUtils.getLicense(previewItem)} + {isPhysicalEdition && } +
+ + {EditionCardUtils.getCtas( + previewItem, + instance.title, + !!cookies[NYPL_SESSION_ID] )} -
-
{EditionCardUtils.getWorldCatElem(instance)}
- {EditionCardUtils.getLicense(previewItem)} - {isPhysicalEdition && } -
- - {EditionCardUtils.getCtas( - previewItem, - instance.title, - !!cookies[NYPL_SESSION_ID] - )} - -
+
+
+ ); }; diff --git a/src/components/ResultsList/ResultsList.tsx b/src/components/ResultsList/ResultsList.tsx index a0105836..9557c1bd 100644 --- a/src/components/ResultsList/ResultsList.tsx +++ b/src/components/ResultsList/ResultsList.tsx @@ -71,7 +71,11 @@ const ResultsList: React.FC<{ works: ApiWork[] }> = ({ works }) => { By {EditionCardUtils.getAuthorsList(work.authors)} )} - + 1} + />
{getEditionsLinkElement(work)}
); diff --git a/src/components/Work/Work.tsx b/src/components/Work/Work.tsx index c8fdca83..0f0121fe 100644 --- a/src/components/Work/Work.tsx +++ b/src/components/Work/Work.tsx @@ -81,41 +81,29 @@ const WorkDetail: React.FC<{ workResult: WorkResult; backUrl?: string }> = ( const contentTopElement = ( <> - - - {work.title} - - {props.backUrl && ( - - - Back to search results - - - )} - + + {work.title} + {work.sub_title && {work.sub_title}} {authorsList && authorsList.length && ( By {joinArrayOfElements(authorsList, "")} )} + {props.backUrl && ( + + + Back to search results + + + )} {featuredEdition && ( - <> - - - Featured Edition - - - - - - + + + )} {work.inCollections && work.inCollections.length > 0 && ( = ( const contentPrimaryElement = ( <> - + {work.editions && work.editions.length > 1 && ( + + )} - {work.editions && ( + {work.editions && work.editions.length > 1 && ( <> - - - All Editions + + + Other Editions = ( /> - {work.editions.map((edition: WorkEdition) => ( + {work.editions.slice(1).map((edition: WorkEdition) => ( - May be available via NYPL

Date: Wed, 13 Dec 2023 18:04:48 -0500 Subject: [PATCH 05/31] update tests --- src/components/EditionDetail/Edition.test.tsx | 18 ++++++++--------- src/components/EditionDetail/Edition.tsx | 18 ++++++++++------- src/components/Work/Work.test.tsx | 20 ++++++++----------- src/components/Work/Work.tsx | 18 ++++++++++------- 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/components/EditionDetail/Edition.test.tsx b/src/components/EditionDetail/Edition.test.tsx index fa77af87..a1e08506 100644 --- a/src/components/EditionDetail/Edition.test.tsx +++ b/src/components/EditionDetail/Edition.test.tsx @@ -66,15 +66,13 @@ describe("Renders edition component when given valid edition", () => { ); }); }); - test("Three cards show up in page", () => { - expect( - screen.getByRole("heading", { name: "Featured Copy" }) - ).toBeInTheDocument(); + test("Two cards show up in page", () => { + expect(screen.getByText("Featured Edition")).toBeInTheDocument(); const featuredEditionHeadings = screen.getAllByRole("heading", { name: "1923", }); - expect(featuredEditionHeadings.length).toEqual(3); - expect(screen.getAllByAltText("Cover").length).toBe(3); + expect(featuredEditionHeadings.length).toEqual(2); + expect(screen.getAllByAltText("Cover").length).toBe(2); expect( screen .getAllByText("License: Public Domain when viewed in the US")[0] @@ -82,12 +80,12 @@ describe("Renders edition component when given valid edition", () => { ).toContain("/license"); }); - test("Featured Card, which has publisher 'Miller', shows up twice", () => { + test("Featured Card, which has publisher 'Miller', shows up once", () => { expect( screen.getAllByText("Published in Paris, France by Miller,", { selector: "div", }).length - ).toBe(2); + ).toBe(1); }); test("Shows Details Table", () => { expect( @@ -191,12 +189,12 @@ describe("All Copies Toggle", () => { render(); }); - test("Featured Card, which has publisher 'Publisher 1', shows up twice", () => { + test("Featured Card, which has publisher 'Publisher 1', shows up once", () => { expect( screen.getAllByText("Published in Paris, France by Publisher 1", { selector: "div", }).length - ).toBe(2); + ).toBe(1); }); }); }); diff --git a/src/components/EditionDetail/Edition.tsx b/src/components/EditionDetail/Edition.tsx index 5df912dc..4f67c048 100644 --- a/src/components/EditionDetail/Edition.tsx +++ b/src/components/EditionDetail/Edition.tsx @@ -201,13 +201,17 @@ const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = (
)} - {edition.instances.slice(1).map((instance) => ( - - ))} + {edition.instances + .filter( + (instance) => instance.instance_id !== featuredInstance.instance_id + ) + .map((instance) => ( + + ))} ); diff --git a/src/components/Work/Work.test.tsx b/src/components/Work/Work.test.tsx index 5289886f..d869e9a1 100644 --- a/src/components/Work/Work.test.tsx +++ b/src/components/Work/Work.test.tsx @@ -54,14 +54,12 @@ describe("Renders Work component when given valid work", () => { }); }); - test("Featured Edition Card shows up twice in page", () => { - expect( - screen.getByRole("heading", { name: "Featured Edition" }) - ).toBeInTheDocument(); + test("Featured Edition Card shows up once in page", () => { + expect(screen.getByText("Featured Edition")).toBeInTheDocument(); const featuredEditionHeadings = screen.getAllByRole("heading", { name: "1967 Edition", }); - expect(featuredEditionHeadings.length).toEqual(2); + expect(featuredEditionHeadings.length).toEqual(1); featuredEditionHeadings.forEach((heading) => { expect( (within(heading).getByRole("link") as HTMLLinkElement).href @@ -71,13 +69,13 @@ describe("Renders Work component when given valid work", () => { ).toContain("?featured=1280883"); }); - expect(screen.getAllByAltText("Cover for 1967 Edition").length).toBe(2); + expect(screen.getAllByAltText("Cover for 1967 Edition").length).toBe(1); expect( screen.getAllByText( "Published by Foreign Service Institute, Dept. of State;" ).length - ).toBe(2); - expect(screen.getAllByText("Languages: English, German").length).toBe(2); + ).toBe(1); + expect(screen.getAllByText("Languages: English, German").length).toBe(1); expect( screen.getAllByText("License: Unknown")[0].closest("a").href ).toContain("/license"); @@ -180,13 +178,11 @@ describe("Edition Cards and toggles", () => { }); test("1980 edition shows up twice", () => { - expect( - screen.getByRole("heading", { name: "Featured Edition" }) - ).toBeInTheDocument(); + expect(screen.getByText("Featured Edition")).toBeInTheDocument(); const featuredEditionHeadings = screen.getAllByRole("heading", { name: "1980 Edition", }); - expect(featuredEditionHeadings.length).toEqual(2); + expect(featuredEditionHeadings.length).toEqual(1); }); }); }); diff --git a/src/components/Work/Work.tsx b/src/components/Work/Work.tsx index 0f0121fe..249f02bc 100644 --- a/src/components/Work/Work.tsx +++ b/src/components/Work/Work.tsx @@ -174,13 +174,17 @@ const WorkDetail: React.FC<{ workResult: WorkResult; backUrl?: string }> = ( /> - {work.editions.slice(1).map((edition: WorkEdition) => ( - - ))} + {work.editions + .filter( + (edition) => edition.edition_id !== featuredEdition.edition_id + ) + .map((edition: WorkEdition) => ( + + ))} )} From f7e539ed18e660f09095324337111992fcf47e9b Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 15 Dec 2023 13:36:47 -0500 Subject: [PATCH 06/31] fix some mobile styles --- src/components/EditionCard/EditionCard.tsx | 11 +- src/components/Search/Search.tsx | 217 ++++++++++----------- 2 files changed, 114 insertions(+), 114 deletions(-) diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index c5a68d89..e2b7aeca 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -76,12 +76,12 @@ export const EditionCard: React.FC<{ }} isAlignedRightActions paddingTop="m" - flexFlow={{ md: "column nowrap", lg: "row" }} + flexFlow={{ base: "column nowrap", md: "row" }} sx={{ ".card-right": { - maxWidth: { base: "100%", lg: "200px" }, - marginStart: { base: "0", lg: "m" }, - marginTop: { base: "xs", lg: 0 }, + maxWidth: { base: "100%", md: "200px" }, + marginStart: { base: "0", md: "m" }, + marginTop: { base: "xs", md: 0 }, }, }} > @@ -120,6 +120,9 @@ export const EditionCard: React.FC<{ display="flex" flexDir="column" whiteSpace="nowrap" + sx={{ + width: { base: "100%", md: "200px" }, + }} gap={4} > {EditionCardUtils.getCtas( diff --git a/src/components/Search/Search.tsx b/src/components/Search/Search.tsx index 009e9140..6770f8ef 100644 --- a/src/components/Search/Search.tsx +++ b/src/components/Search/Search.tsx @@ -9,9 +9,9 @@ import { Flex, Form, useModal, - useNYPLBreakpoints, TemplateAppContainer, Text, + useNYPLBreakpoints, } from "@nypl/design-system-react-components"; import { useRouter } from "next/router"; import { FacetItem, Query } from "~/src/types/DataModel"; @@ -47,7 +47,7 @@ const SearchResults: React.FC<{ const { onClose, onOpen, Modal } = useModal(); - const { isLargerThanMedium } = useNYPLBreakpoints(); + const { isLargerThanLarge } = useNYPLBreakpoints(); const router = useRouter(); @@ -96,13 +96,6 @@ const SearchResults: React.FC<{ return facets; }; - const getFilterCount = (searchQuery: SearchQuery) => { - return searchQuery.showAll !== SearchQueryDefaults.showAll - ? searchQuery.filters.length + 1 - : searchQuery.filters.length; - }; - - const filterCount = getFilterCount(searchQuery); const numberOfWorks = searchResults.data.totalWorks; const works: ApiWork[] = searchResults.data.works; @@ -182,6 +175,84 @@ const SearchResults: React.FC<{ ]} > + + + + + + onChangePerPage(e)} + onChangeSort={(e) => onChangeSort(e)} + /> + +
+ + Refine Results + + { + changeFilters(filters); + }} + changeShowAll={(showAll: boolean) => { + changeShowAll(showAll); + }} + /> + + + } + /> + {searchQuery.filters.length > 0 && !isLargerThanLarge && ( + + )} +
); @@ -224,107 +295,33 @@ const SearchResults: React.FC<{ ); const contentSidebarElement = ( - <> - {!isLargerThanMedium && ( - - )} - - - - onChangePerPage(e)} - onChangeSort={(e) => onChangeSort(e)} - /> - -
- - Refine Results - - { - changeFilters(filters); - }} - changeShowAll={(showAll: boolean) => { - changeShowAll(showAll); - }} - /> - - - } - /> - {searchQuery.filters.length > 0 && !isLargerThanMedium && ( - - )} -
+ - - Refine Results - - { - changeFilters(filters); - }} - changeShowAll={(showAll: boolean) => { - changeShowAll(showAll); - }} - /> - - + Refine Results +
+ { + changeFilters(filters); + }} + changeShowAll={(showAll: boolean) => { + changeShowAll(showAll); + }} + /> + ); const contentPrimaryElement = ( @@ -344,7 +341,7 @@ const SearchResults: React.FC<{ contentTop={contentTopElement} contentSidebar={contentSidebarElement} contentPrimary={contentPrimaryElement} - sidebar="left" + sidebar={"left"} /> ); }; From fcbc0886a7dd0de78a36c2241996cf9a2a896730 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 15 Dec 2023 14:08:49 -0500 Subject: [PATCH 07/31] update search tests --- src/__tests__/Search.test.tsx | 18 ++++++++++-------- src/__tests__/componentHelpers/FilterYears.tsx | 12 +++++++----- .../EditionCard/ScanAndDeliverBlurb.tsx | 2 +- src/components/FilterYears/FilterYears.tsx | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/__tests__/Search.test.tsx b/src/__tests__/Search.test.tsx index 0a364ce0..fb45156a 100644 --- a/src/__tests__/Search.test.tsx +++ b/src/__tests__/Search.test.tsx @@ -41,7 +41,9 @@ const emptySearchResults: ApiSearchResult = { }, }; const clickFiltersButton = async () => - userEvent.click(await screen.findByRole("button", { name: "Filters (0)" })); + userEvent.click( + await screen.findByRole("button", { name: "Refine results" }) + ); describe("Renders Search Results Page", () => { beforeEach(() => { @@ -82,7 +84,7 @@ describe("Renders Search Results Page", () => { describe("Filters modal show and hide", () => { test("Filters button appears", () => { expect( - screen.getByRole("button", { name: "Filters (0)" }) + screen.getByRole("button", { name: "Refine results" }) ).toBeInTheDocument(); }); test("clicking 'filters' button shows filters contents", async () => { @@ -141,7 +143,7 @@ describe("Renders Search Results Page", () => { await userEvent.click(screen.getByRole("button", { name: "Go Back" })); expect( - screen.getByRole("button", { name: "Filters (0)" }) + screen.getByRole("button", { name: "Refine results" }) ).toBeInTheDocument(); }, 15000); }); @@ -163,7 +165,7 @@ describe("Renders Search Results Page", () => { await userEvent.click(screen.getByRole("button", { name: "Go Back" })); expect( - screen.getByRole("button", { name: "Filters (0)" }) + screen.getByRole("button", { name: "Refine results" }) ).toBeInTheDocument(); }, 15000); }); @@ -184,7 +186,7 @@ describe("Renders Search Results Page", () => { }); await userEvent.click(screen.getByRole("button", { name: "Go Back" })); expect( - screen.getByRole("button", { name: "Filters (1)" }) + screen.getByRole("button", { name: "Refine results" }) ).toBeInTheDocument(); }, 15000); }); @@ -217,7 +219,7 @@ describe("Renders Search Results Page", () => { await userEvent.click(screen.getByRole("button", { name: "Go Back" })); await userEvent.click( - screen.getByRole("button", { name: "Filters (1)" }) + screen.getByRole("button", { name: "Refine results" }) ); const languages2 = screen.getByRole("group", { @@ -247,7 +249,7 @@ describe("Renders Search Results Page", () => { }); await userEvent.click(screen.getByRole("button", { name: "Go Back" })); expect( - screen.getByRole("button", { name: "Filters (1)" }) + screen.getByRole("button", { name: "Refine results" }) ).toBeInTheDocument(); }, 15000); }); @@ -275,7 +277,7 @@ describe("Renders Search Results Page", () => { }); await userEvent.click(screen.getByRole("button", { name: "Go Back" })); expect( - screen.getByRole("button", { name: "Filters (1)" }) + screen.getByRole("button", { name: "Refine results" }) ).toBeInTheDocument(); }, 15000); }); diff --git a/src/__tests__/componentHelpers/FilterYears.tsx b/src/__tests__/componentHelpers/FilterYears.tsx index 5bbeaf10..b1508f91 100644 --- a/src/__tests__/componentHelpers/FilterYears.tsx +++ b/src/__tests__/componentHelpers/FilterYears.tsx @@ -23,7 +23,9 @@ export const FilterYearsTests = ( }) ).toHaveValue((endYear && endYear.value) || null); if (hasApplyButton) { - expect(screen.getByRole("button", { name: "Apply" })).toBeInTheDocument(); + expect( + screen.getByRole("button", { name: "Apply year" }) + ).toBeInTheDocument(); } }); @@ -36,7 +38,7 @@ export const FilterYearsTests = ( name: "From", }); const applyButton = within(yearGroup).getByRole("button", { - name: "Apply", + name: "Apply year", }); await userEvent.type(fromInput, "1990"); expect(fromInput).toHaveValue(1990); @@ -58,7 +60,7 @@ export const FilterYearsTests = ( name: "To", }); const applyButton = within(yearGroup).getByRole("button", { - name: "Apply", + name: "Apply year", }); await userEvent.type(toInput, "1990"); await userEvent.click(applyButton); @@ -83,7 +85,7 @@ export const FilterYearsTests = ( name: "From", }); const applyButton = within(yearGroup).getByRole("button", { - name: "Apply", + name: "Apply year", }); await userEvent.type(fromInput, "1990"); await userEvent.type(toInput, "2000"); @@ -109,7 +111,7 @@ export const FilterYearsTests = ( name: "From", }); const applyButton = within(yearGroup).getByRole("button", { - name: "Apply", + name: "Apply year", }); await userEvent.type(fromInput, "1990"); await userEvent.type(toInput, "1890"); diff --git a/src/components/EditionCard/ScanAndDeliverBlurb.tsx b/src/components/EditionCard/ScanAndDeliverBlurb.tsx index 8ae07f89..9b3dc21d 100644 --- a/src/components/EditionCard/ScanAndDeliverBlurb.tsx +++ b/src/components/EditionCard/ScanAndDeliverBlurb.tsx @@ -5,7 +5,7 @@ import { SCAN_AND_DELIVER_LINK } from "~/src/constants/links"; export const ScanAndDeliverBlurb: React.FC = () => { return ( - + A partial scan of this edition can be requested via NYPL's{" "} diff --git a/src/components/FilterYears/FilterYears.tsx b/src/components/FilterYears/FilterYears.tsx index 2f180539..62f7a8a5 100644 --- a/src/components/FilterYears/FilterYears.tsx +++ b/src/components/FilterYears/FilterYears.tsx @@ -93,7 +93,7 @@ const FilterYears: React.FC<{ id={isModal ? "year-filter-button-modal" : "year-filter-button"} onClick={() => onSubmit()} > - Apply + Apply year )} From b0c272a9aba8e53a82093a43228a73e586820daa Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 15 Dec 2023 15:07:42 -0500 Subject: [PATCH 08/31] update gap between ctas --- src/components/EditionCard/EditionCard.tsx | 2 +- src/components/InstanceCard/InstanceCard.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index e2b7aeca..3732eff8 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -123,7 +123,7 @@ export const EditionCard: React.FC<{ sx={{ width: { base: "100%", md: "200px" }, }} - gap={4} + gap="xs" > {EditionCardUtils.getCtas( previewItem, diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index dbd33211..efdb3f87 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -90,7 +90,7 @@ export const InstanceCard: React.FC<{ display="flex" flexDir="column" whiteSpace="nowrap" - gap={4} + gap="xs" > {EditionCardUtils.getCtas( previewItem, From 8d40b4a06a890c0db75fcab41a84f371ba38c191 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Mon, 18 Dec 2023 11:33:28 -0500 Subject: [PATCH 09/31] fix mobile card overflow issue --- src/components/EditionCard/EditionCard.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index 3732eff8..a942a37f 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -58,7 +58,7 @@ export const EditionCard: React.FC<{ paddingBottom="l" paddingRight="l" > - + {isPhysicalEdition && } {isFeaturedEdition && } @@ -76,12 +76,13 @@ export const EditionCard: React.FC<{ }} isAlignedRightActions paddingTop="m" - flexFlow={{ base: "column nowrap", md: "row" }} + flexFlow={{ md: "column nowrap", lg: "row" }} + justifyContent={{ md: "center", lg: "left" }} sx={{ ".card-right": { - maxWidth: { base: "100%", md: "200px" }, - marginStart: { base: "0", md: "m" }, - marginTop: { base: "xs", md: 0 }, + maxWidth: { base: "100%", lg: "200px" }, + marginStart: { base: "0", lg: "m" }, + marginTop: { base: "xs", lg: 0 }, }, }} > @@ -121,7 +122,7 @@ export const EditionCard: React.FC<{ flexDir="column" whiteSpace="nowrap" sx={{ - width: { base: "100%", md: "200px" }, + width: { base: "100%", lg: "200px" }, }} gap="xs" > From d727900ef4414e4d92a8da47b997b5b977c7e599 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Wed, 20 Dec 2023 16:00:48 -0500 Subject: [PATCH 10/31] address comments --- .../EditionCard/CardRequiredBadge.tsx | 4 +- src/components/EditionCard/Ctas.tsx | 38 ++++ src/components/EditionCard/DownloadLink.tsx | 47 +++++ src/components/EditionCard/EddLink.tsx | 38 ++++ src/components/EditionCard/EditionCard.tsx | 31 +-- .../EditionCard/FeaturedEditionBadge.tsx | 4 +- .../EditionCard/LanguageDisplayText.tsx | 13 ++ .../EditionCard/PhysicalEditionBadge.tsx | 4 +- .../EditionCard/PublisherAndLocation.tsx | 23 +++ src/components/EditionCard/ReadOnlineLink.tsx | 26 +++ .../EditionCard/ScanAndDeliverBlurb.tsx | 4 +- src/components/InstanceCard/InstanceCard.tsx | 31 +-- src/components/InstanceCard/WorldCat.tsx | 19 ++ src/util/EditionCardUtils.tsx | 187 ++---------------- 14 files changed, 271 insertions(+), 198 deletions(-) create mode 100644 src/components/EditionCard/Ctas.tsx create mode 100644 src/components/EditionCard/DownloadLink.tsx create mode 100644 src/components/EditionCard/EddLink.tsx create mode 100644 src/components/EditionCard/LanguageDisplayText.tsx create mode 100644 src/components/EditionCard/PublisherAndLocation.tsx create mode 100644 src/components/EditionCard/ReadOnlineLink.tsx create mode 100644 src/components/InstanceCard/WorldCat.tsx diff --git a/src/components/EditionCard/CardRequiredBadge.tsx b/src/components/EditionCard/CardRequiredBadge.tsx index 397d9f55..995967c2 100644 --- a/src/components/EditionCard/CardRequiredBadge.tsx +++ b/src/components/EditionCard/CardRequiredBadge.tsx @@ -1,10 +1,12 @@ import React from "react"; import { StatusBadge } from "@nypl/design-system-react-components"; -export const CardRequiredBadge: React.FC = () => { +const CardRequiredBadge: React.FC = () => { return ( Library Card Required ); }; + +export default CardRequiredBadge; diff --git a/src/components/EditionCard/Ctas.tsx b/src/components/EditionCard/Ctas.tsx new file mode 100644 index 00000000..7caa8841 --- /dev/null +++ b/src/components/EditionCard/Ctas.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { ApiItem } from "~/src/types/DataModel"; +import EditionCardUtils from "~/src/util/EditionCardUtils"; +import DownloadLink from "./DownloadLink"; +import EddLink from "./EddLink"; +import ReadOnlineLink from "./ReadOnlineLink"; + +const Ctas: React.FC<{ + item: ApiItem | undefined; + title: string; + isLoggedIn: boolean; +}> = ({ item, title, isLoggedIn }) => { + const readOnlineLink = EditionCardUtils.getReadOnlineLink(item); + const downloadLink = EditionCardUtils.selectDownloadLink(item); + + if (readOnlineLink || downloadLink) { + return ( + <> + {readOnlineLink && } + {downloadLink && ( + + )} + + ); + } + + const eddLink = + item && item.links ? item.links.find((link) => link.flags.edd) : undefined; + + // Offer EDD if available + if (eddLink !== undefined) { + return ; + } + + return <>Not yet available; +}; + +export default Ctas; diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx new file mode 100644 index 00000000..9b6b2a6f --- /dev/null +++ b/src/components/EditionCard/DownloadLink.tsx @@ -0,0 +1,47 @@ +import { Box, Button, Icon } from "@nypl/design-system-react-components"; +import React from "react"; +import Link from "~/src/components/Link/Link"; +import { trackCtaClick } from "~/src/lib/adobe/Analytics"; +import { ItemLink } from "~/src/types/DataModel"; +import { formatUrl } from "~/src/util/Util"; + +const DownloadLink: React.FC<{ + downloadLink: ItemLink; + title: string; +}> = ({ downloadLink, title }) => { + if (downloadLink && downloadLink.url) { + const formattedUrl = formatUrl(downloadLink.url); + const trackDownloadCta = () => { + trackCtaClick({ + cta_section: `${title}`, + cta_text: "Download", + destination_url: `${formattedUrl}`, + }); + }; + return ( + + + + + + ); + } +}; + +export default DownloadLink; diff --git a/src/components/EditionCard/EddLink.tsx b/src/components/EditionCard/EddLink.tsx new file mode 100644 index 00000000..9713c753 --- /dev/null +++ b/src/components/EditionCard/EddLink.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import Link from "~/src/components/Link/Link"; +import { ItemLink } from "~/src/types/DataModel"; + +const EddLink: React.FC<{ + eddLink: ItemLink; + isLoggedIn: boolean; +}> = ({ eddLink, isLoggedIn }) => { + if (isLoggedIn) { + return ( + <> + + Request Scan + + + ); + } else { + return ( + <> + + Log in to request scan + + + ); + } +}; + +export default EddLink; diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index a942a37f..3e803c10 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -13,10 +13,13 @@ import EditionCardUtils from "~/src/util/EditionCardUtils"; import { PLACEHOLDER_COVER_LINK } from "~/src/constants/editioncard"; import { useCookies } from "react-cookie"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; -import { PhysicalEditionBadge } from "./PhysicalEditionBadge"; -import { ScanAndDeliverBlurb } from "./ScanAndDeliverBlurb"; -import { CardRequiredBadge } from "./CardRequiredBadge"; -import { FeaturedEditionBadge } from "./FeaturedEditionBadge"; +import Ctas from "./Ctas"; +import LanguageDisplayText from "./LanguageDisplayText"; +import PublisherAndLocation from "./PublisherAndLocation"; +import CardRequiredBadge from "./CardRequiredBadge"; +import FeaturedEditionBadge from "./FeaturedEditionBadge"; +import PhysicalEditionBadge from "./PhysicalEditionBadge"; +import ScanAndDeliverBlurb from "./ScanAndDeliverBlurb"; export const EditionCard: React.FC<{ edition: WorkEdition; @@ -106,11 +109,11 @@ export const EditionCard: React.FC<{ - {EditionCardUtils.getPublisherAndLocation( - edition.publication_place, - edition.publishers - )} - {EditionCardUtils.getLanguageDisplayText(edition)} + + {EditionCardUtils.getLicense(previewItem)} @@ -126,11 +129,11 @@ export const EditionCard: React.FC<{ }} gap="xs" > - {EditionCardUtils.getCtas( - previewItem, - title, - !!cookies[NYPL_SESSION_ID] - )} +
diff --git a/src/components/EditionCard/FeaturedEditionBadge.tsx b/src/components/EditionCard/FeaturedEditionBadge.tsx index e32fc54c..23accff9 100644 --- a/src/components/EditionCard/FeaturedEditionBadge.tsx +++ b/src/components/EditionCard/FeaturedEditionBadge.tsx @@ -1,10 +1,12 @@ import React from "react"; import { StatusBadge } from "@nypl/design-system-react-components"; -export const FeaturedEditionBadge: React.FC = () => { +const FeaturedEditionBadge: React.FC = () => { return ( Featured Edition ); }; + +export default FeaturedEditionBadge; diff --git a/src/components/EditionCard/LanguageDisplayText.tsx b/src/components/EditionCard/LanguageDisplayText.tsx new file mode 100644 index 00000000..0966ef3f --- /dev/null +++ b/src/components/EditionCard/LanguageDisplayText.tsx @@ -0,0 +1,13 @@ +import { Box } from "@nypl/design-system-react-components"; +import React from "react"; +import { WorkEdition } from "~/src/types/DataModel"; +import EditionCardUtils from "~/src/util/EditionCardUtils"; + +const LanguageDisplayText: React.FC<{ previewEdition: WorkEdition }> = ({ + previewEdition, +}) => { + const languageText = EditionCardUtils.getLanguageDisplayText(previewEdition); + return {languageText}; +}; + +export default LanguageDisplayText; diff --git a/src/components/EditionCard/PhysicalEditionBadge.tsx b/src/components/EditionCard/PhysicalEditionBadge.tsx index eefa0f48..6be5bf84 100644 --- a/src/components/EditionCard/PhysicalEditionBadge.tsx +++ b/src/components/EditionCard/PhysicalEditionBadge.tsx @@ -1,6 +1,8 @@ import React from "react"; import { StatusBadge } from "@nypl/design-system-react-components"; -export const PhysicalEditionBadge: React.FC = () => { +const PhysicalEditionBadge: React.FC = () => { return Physical Edition; }; + +export default PhysicalEditionBadge; diff --git a/src/components/EditionCard/PublisherAndLocation.tsx b/src/components/EditionCard/PublisherAndLocation.tsx new file mode 100644 index 00000000..f1e77db3 --- /dev/null +++ b/src/components/EditionCard/PublisherAndLocation.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import { Agent } from "~/src/types/DataModel"; +import EditionCardUtils from "~/src/util/EditionCardUtils"; + +const PublisherAndLocation: React.FC<{ + pubPlace: string; + publishers: Agent[]; +}> = ({ pubPlace, publishers }) => { + const displayLocation = + EditionCardUtils.getPublisherDisplayLocation(pubPlace); + + const displayName = EditionCardUtils.getPublishersDisplayText(publishers); + + return ( + <> + {!displayLocation && !displayName + ? "Publisher and Location Unknown" + : `Published${displayLocation}${displayName}`} + + ); +}; + +export default PublisherAndLocation; diff --git a/src/components/EditionCard/ReadOnlineLink.tsx b/src/components/EditionCard/ReadOnlineLink.tsx new file mode 100644 index 00000000..a3c64a8a --- /dev/null +++ b/src/components/EditionCard/ReadOnlineLink.tsx @@ -0,0 +1,26 @@ +import { Box } from "@nypl/design-system-react-components"; +import React from "react"; +import Link from "~/src/components/Link/Link"; +import { ItemLink } from "~/src/types/DataModel"; + +// "Read Online" button should only show up if the link was flagged as "reader" or "embed" +const ReadOnlineLink: React.FC<{ readOnlineLink: ItemLink }> = ({ + readOnlineLink, +}) => { + return ( + readOnlineLink && ( + + + Read Online + + + ) + ); +}; + +export default ReadOnlineLink; diff --git a/src/components/EditionCard/ScanAndDeliverBlurb.tsx b/src/components/EditionCard/ScanAndDeliverBlurb.tsx index 9b3dc21d..d0eb452a 100644 --- a/src/components/EditionCard/ScanAndDeliverBlurb.tsx +++ b/src/components/EditionCard/ScanAndDeliverBlurb.tsx @@ -3,7 +3,7 @@ import React from "react"; import Link from "../Link/Link"; import { SCAN_AND_DELIVER_LINK } from "~/src/constants/links"; -export const ScanAndDeliverBlurb: React.FC = () => { +const ScanAndDeliverBlurb: React.FC = () => { return ( @@ -14,3 +14,5 @@ export const ScanAndDeliverBlurb: React.FC = () => { ); }; + +export default ScanAndDeliverBlurb; diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index efdb3f87..5510d569 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -13,10 +13,13 @@ import EditionCardUtils from "~/src/util/EditionCardUtils"; import Link from "../Link/Link"; import { useCookies } from "react-cookie"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; -import { PhysicalEditionBadge } from "../EditionCard/PhysicalEditionBadge"; -import { ScanAndDeliverBlurb } from "../EditionCard/ScanAndDeliverBlurb"; -import { CardRequiredBadge } from "../EditionCard/CardRequiredBadge"; -import { FeaturedEditionBadge } from "../EditionCard/FeaturedEditionBadge"; +import Ctas from "../EditionCard/Ctas"; +import PublisherAndLocation from "../EditionCard/PublisherAndLocation"; +import WorldCat from "./WorldCat"; +import CardRequiredBadge from "../EditionCard/CardRequiredBadge"; +import FeaturedEditionBadge from "../EditionCard/FeaturedEditionBadge"; +import PhysicalEditionBadge from "../EditionCard/PhysicalEditionBadge"; +import ScanAndDeliverBlurb from "../EditionCard/ScanAndDeliverBlurb"; // Creates an Instance card out of the Edition Year and Instance object // Note: Edition Year only needs to be passed because `instance.publication_date` @@ -77,12 +80,12 @@ export const InstanceCard: React.FC<{
- {EditionCardUtils.getPublisherAndLocation( - instance.publication_place, - instance.publishers - )} +
-
{EditionCardUtils.getWorldCatElem(instance)}
+ {EditionCardUtils.getLicense(previewItem)} {isPhysicalEdition && }
@@ -92,11 +95,11 @@ export const InstanceCard: React.FC<{ whiteSpace="nowrap" gap="xs" > - {EditionCardUtils.getCtas( - previewItem, - instance.title, - !!cookies[NYPL_SESSION_ID] - )} + diff --git a/src/components/InstanceCard/WorldCat.tsx b/src/components/InstanceCard/WorldCat.tsx new file mode 100644 index 00000000..82a4eda7 --- /dev/null +++ b/src/components/InstanceCard/WorldCat.tsx @@ -0,0 +1,19 @@ +import { Box } from "@nypl/design-system-react-components"; +import React from "react"; +import Link from "~/src/components/Link/Link"; +import { Instance } from "~/src/types/DataModel"; +import EditionCardUtils from "~/src/util/EditionCardUtils"; + +const WorldCat: React.FC<{ + instance: Instance; +}> = ({ instance }) => { + const oclcLink = EditionCardUtils.getOclcLink(instance); + return ( + + oclcLink ? (Find in a library) : ( + <>Find in Library Unavailable) + + ); +}; + +export default WorldCat; diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 87322e34..68e99795 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -8,7 +8,6 @@ import { WorkEdition, Identifier, } from "../types/DataModel"; -import { Box, Button, Icon } from "@nypl/design-system-react-components"; import Link from "~/src/components/Link/Link"; import { formatUrl, truncateStringOnWhitespace } from "./Util"; import { @@ -19,7 +18,6 @@ import { } from "../constants/editioncard"; import { ApiSearchQuery } from "../types/SearchQuery"; import { MediaTypes } from "../constants/mediaTypes"; -import { trackCtaClick } from "../lib/adobe/Analytics"; // EditionCard holds all the methods needed to build an Edition Card export default class EditionCardUtils { @@ -120,40 +118,23 @@ export default class EditionCardUtils { return coverLink ? formatUrl(coverLink.url) : PLACEHOLDER_COVER_LINK; } - /** - * Get publisher and publish location - * @param pubPlace - The display name of the place of publication - * @param agents - an array of Agents - * @returns A display element for publisher and location - */ - static getPublisherAndLocation( - pubPlace: string, - publishers: Agent[] - ): JSX.Element { - const publisherDisplayLocation = (pubPlace: string) => { - return pubPlace - ? ` in ${truncateStringOnWhitespace(pubPlace, MAX_PLACE_LENGTH)}` - : ""; - }; - - const publisherDisplayText = (publishers: Agent[]) => { - if (!publishers || publishers.length === 0) return ""; - const publisherNames = publishers.map( - (pubAgent: Agent) => pubAgent && pubAgent.name - ); - return ` by ${EditionCardUtils.getFirstAndCountMore(publisherNames)}`; - }; + static getPublisherDisplayLocation(pubPlace: string): undefined | string { + return ( + pubPlace && + ` in ${truncateStringOnWhitespace(pubPlace, MAX_PLACE_LENGTH)}` + ); + } - const displayLocation = publisherDisplayLocation(pubPlace); - const displayName = publisherDisplayText(publishers); - if (!displayLocation && !displayName) - return <>Publisher and Location Unknown; - const publisherText = `Published${displayLocation}${displayName}`; - return <>{publisherText}; + static getPublishersDisplayText(publishers: Agent[]): undefined | string { + if (!publishers || publishers.length === 0) return ""; + const publisherNames = publishers.map( + (pubAgent: Agent) => pubAgent && pubAgent.name + ); + return ` by ${EditionCardUtils.getFirstAndCountMore(publisherNames)}`; } // Language Display - static getLanguageDisplayText(previewEdition: WorkEdition) { + static getLanguageDisplayText(previewEdition: WorkEdition): string { if ( previewEdition && previewEdition.languages && @@ -166,27 +147,27 @@ export default class EditionCardUtils { .map((lang: Language) => lang.language); if (languagesTextList && languagesTextList.length) { const languageText = `Languages: ${languagesTextList.join(", ")}`; - return <>{languageText}; + return languageText; } } - return <>Languages: Undetermined; + return "Languages: Undetermined"; } // Rights - static getLicense(item: ApiItem) { + static getLicense(item: ApiItem): string { return item && item.rights && item.rights.length > 0 ? `License: ${item.rights[0].rightsStatement}` : "License: Unknown"; } - static getReadLink = (item: ApiItem, type: "reader" | "embed") => { + static getReadLink = (item: ApiItem, type: "reader" | "embed"): ItemLink => { if (!item || !item.links) return undefined; return item.links.find((link: ItemLink) => { return link.flags[type]; }); }; - static selectDownloadLink = (item: ApiItem) => { + static selectDownloadLink = (item: ApiItem): ItemLink => { if (!item || !item.links) return undefined; return item.links.find((link: ItemLink) => { return link.flags["download"]; @@ -199,69 +180,11 @@ export default class EditionCardUtils { const embeddedLink = EditionCardUtils.getReadLink(item, "embed"); // Prefer local link over embedded link const readOnlineLink = localLink ?? embeddedLink; - if (readOnlineLink) { - return ( - - Read Online - - ); - } - return undefined; + return readOnlineLink; }; - static getDownloadLink(editionItem: ApiItem, title: string) { - if (!editionItem || !editionItem.links) return undefined; - - const selectedLink = EditionCardUtils.selectDownloadLink(editionItem); - - if (selectedLink && selectedLink.url) { - const formattedUrl = formatUrl(selectedLink.url); - - const trackDownloadCta = () => { - trackCtaClick({ - cta_section: `${title}`, - cta_text: "Download", - destination_url: `${formattedUrl}`, - }); - }; - return ( - - - - ); - } - } - - static getNoLinkElement(showRequestButton: boolean) { - if (showRequestButton) { - return Not Yet Available {showRequestButton}; - } - return <>Not yet available; - } - - static getWorldCatElem(instance: Instance) { + static getOclcLink(instance: Instance): string { const oclc = instance && instance.identifiers ? instance.identifiers.find( @@ -271,76 +194,8 @@ export default class EditionCardUtils { const oclcLink = oclc ? `https://www.worldcat.org/oclc/${oclc.identifier}` : undefined; - return oclc ? ( - Find in a library - ) : ( - <>Find in Library Unavailable - ); - } - static getCtas( - item: ApiItem | undefined, - title: string, - isLoggedIn: boolean - ) { - const readOnlineLink = EditionCardUtils.getReadOnlineLink(item); - const downloadLink = EditionCardUtils.getDownloadLink(item, title); - - // If a digital version exists, link directly - if (readOnlineLink || downloadLink) { - return ( - <> - {readOnlineLink} - {downloadLink} - - ); - } - - const eddLink = - item && item.links - ? item.links.find((link) => link.flags.edd) - : undefined; - - // Offer EDD if available - if (eddLink !== undefined) { - const eddElement = EditionCardUtils.getEddLinkElement( - eddLink, - isLoggedIn - ); - return <>{eddElement}; - } - - return <>{EditionCardUtils.getNoLinkElement(false)}; - } - - static getEddLinkElement(eddLink: ItemLink, isLoggedIn: boolean) { - if (isLoggedIn) { - return ( - <> - - Request Scan - - - ); - } else { - return ( - <> - - Log in to request scan - - - ); - } + return oclcLink; } // Get readable item or non-catalog item From 9d4cb483b53fc2710f2bda8f206d28c6030f9ff4 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Wed, 20 Dec 2023 16:42:27 -0500 Subject: [PATCH 11/31] fix test errors --- src/components/EditionCard/EditionCard.tsx | 2 +- src/components/EditionCard/LanguageDisplayText.tsx | 6 +++--- src/components/EditionCard/PublisherAndLocation.tsx | 5 +++-- src/components/InstanceCard/WorldCat.tsx | 7 +++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index 3e803c10..fb0e79c6 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -113,7 +113,7 @@ export const EditionCard: React.FC<{ pubPlace={edition.publication_place} publishers={edition.publishers} /> - + {EditionCardUtils.getLicense(previewItem)} diff --git a/src/components/EditionCard/LanguageDisplayText.tsx b/src/components/EditionCard/LanguageDisplayText.tsx index 0966ef3f..5059e355 100644 --- a/src/components/EditionCard/LanguageDisplayText.tsx +++ b/src/components/EditionCard/LanguageDisplayText.tsx @@ -3,10 +3,10 @@ import React from "react"; import { WorkEdition } from "~/src/types/DataModel"; import EditionCardUtils from "~/src/util/EditionCardUtils"; -const LanguageDisplayText: React.FC<{ previewEdition: WorkEdition }> = ({ - previewEdition, +const LanguageDisplayText: React.FC<{ edition: WorkEdition }> = ({ + edition, }) => { - const languageText = EditionCardUtils.getLanguageDisplayText(previewEdition); + const languageText = EditionCardUtils.getLanguageDisplayText(edition); return {languageText}; }; diff --git a/src/components/EditionCard/PublisherAndLocation.tsx b/src/components/EditionCard/PublisherAndLocation.tsx index f1e77db3..c2675564 100644 --- a/src/components/EditionCard/PublisherAndLocation.tsx +++ b/src/components/EditionCard/PublisherAndLocation.tsx @@ -7,9 +7,10 @@ const PublisherAndLocation: React.FC<{ publishers: Agent[]; }> = ({ pubPlace, publishers }) => { const displayLocation = - EditionCardUtils.getPublisherDisplayLocation(pubPlace); + EditionCardUtils.getPublisherDisplayLocation(pubPlace) || ""; - const displayName = EditionCardUtils.getPublishersDisplayText(publishers); + const displayName = + EditionCardUtils.getPublishersDisplayText(publishers) || ""; return ( <> diff --git a/src/components/InstanceCard/WorldCat.tsx b/src/components/InstanceCard/WorldCat.tsx index 82a4eda7..74a07867 100644 --- a/src/components/InstanceCard/WorldCat.tsx +++ b/src/components/InstanceCard/WorldCat.tsx @@ -10,8 +10,11 @@ const WorldCat: React.FC<{ const oclcLink = EditionCardUtils.getOclcLink(instance); return ( - oclcLink ? (Find in a library) : ( - <>Find in Library Unavailable) + {oclcLink ? ( + Find in a library + ) : ( + <>Find in Library Unavailable + )} ); }; From 7c1514f9727caa83bf500b1fb43ee28e8538b7f3 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Thu, 21 Dec 2023 10:30:30 -0500 Subject: [PATCH 12/31] refactor ResultsList and resolve VQA issues --- src/components/AuthorsList/AuthorsList.tsx | 42 +++++++++++++++++++ src/components/EditionCard/EditionCard.tsx | 1 + .../EditionCard/ScanAndDeliverBlurb.tsx | 6 ++- .../EditionCard/ViewEditionsLink.tsx | 28 +++++++++++++ src/components/EditionDetail/Edition.tsx | 14 +++---- src/components/ResultsList/ResultsList.tsx | 27 +++--------- src/components/Work/Work.tsx | 15 ++++--- .../WorkDetailDefinitionList.tsx | 6 ++- src/util/EditionCardUtils.tsx | 31 -------------- 9 files changed, 98 insertions(+), 72 deletions(-) create mode 100644 src/components/AuthorsList/AuthorsList.tsx create mode 100644 src/components/EditionCard/ViewEditionsLink.tsx diff --git a/src/components/AuthorsList/AuthorsList.tsx b/src/components/AuthorsList/AuthorsList.tsx new file mode 100644 index 00000000..b5476f17 --- /dev/null +++ b/src/components/AuthorsList/AuthorsList.tsx @@ -0,0 +1,42 @@ +import React from "react"; +import { ApiSearchQuery } from "~/src/types/SearchQuery"; +import Link from "~/src/components/Link/Link"; +import { Agent } from "~/src/types/DataModel"; + +const AuthorsList: React.FC<{ authors: Agent[] }> = ({ authors }) => { + if (!authors || authors.length === 0) return undefined; + + return ( + <> + {authors.map((author: Agent, i: number) => { + const authorLinkText = author.name; + const query: ApiSearchQuery = { + query: author.viaf ? `viaf:${author.viaf}` : `author:${author.name}`, + }; + if (author.viaf) { + query.display = `author:${author.name}`; + } + return ( + + + {authorLinkText} + + {i < authors.length - 1 && ", "} + + ); + })} + + ); +}; + +export default AuthorsList; diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index fb0e79c6..9bcd4403 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -58,6 +58,7 @@ export const EditionCard: React.FC<{ border="1px" borderColor="ui.border.default" padding="s" + paddingLeft={{ base: "l", md: null }} paddingBottom="l" paddingRight="l" > diff --git a/src/components/EditionCard/ScanAndDeliverBlurb.tsx b/src/components/EditionCard/ScanAndDeliverBlurb.tsx index d0eb452a..67059c8d 100644 --- a/src/components/EditionCard/ScanAndDeliverBlurb.tsx +++ b/src/components/EditionCard/ScanAndDeliverBlurb.tsx @@ -5,7 +5,11 @@ import { SCAN_AND_DELIVER_LINK } from "~/src/constants/links"; const ScanAndDeliverBlurb: React.FC = () => { return ( - + A partial scan of this edition can be requested via NYPL's{" "} diff --git a/src/components/EditionCard/ViewEditionsLink.tsx b/src/components/EditionCard/ViewEditionsLink.tsx new file mode 100644 index 00000000..66271461 --- /dev/null +++ b/src/components/EditionCard/ViewEditionsLink.tsx @@ -0,0 +1,28 @@ +import { Box } from "@nypl/design-system-react-components"; +import React from "react"; +import { ApiWork } from "~/src/types/WorkQuery"; +import Link from "../Link/Link"; + +const ViewEditionsLink: React.FC<{ work: ApiWork }> = ({ work }) => { + const editionCount = work.edition_count; + const previewEdition = work.editions && work.editions[0]; + + return ( + editionCount > 1 && ( + + + {`View All ${editionCount} Editions`} + + + ) + ); +}; + +export default ViewEditionsLink; diff --git a/src/components/EditionDetail/Edition.tsx b/src/components/EditionDetail/Edition.tsx index 4f67c048..850890fb 100644 --- a/src/components/EditionDetail/Edition.tsx +++ b/src/components/EditionDetail/Edition.tsx @@ -20,15 +20,12 @@ import EditionDetailDefinitionList from "~/src/components/EditionDetailDefinitio import Link from "~/src/components/Link/Link"; import { InstanceCard } from "../InstanceCard/InstanceCard"; import SearchHeader from "../SearchHeader/SearchHeader"; -import { - joinArrayOfElements, - truncateStringOnWhitespace, -} from "~/src/util/Util"; +import { truncateStringOnWhitespace } from "~/src/util/Util"; import { MAX_TITLE_LENGTH } from "~/src/constants/editioncard"; import { Instance } from "~/src/types/DataModel"; -import EditionCardUtils from "~/src/util/EditionCardUtils"; import { PLACEHOLDER_LINK } from "~/src/constants/collection"; import DrbBreakout from "../DrbBreakout/DrbBreakout"; +import AuthorsList from "../AuthorsList/AuthorsList"; const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = ( props @@ -39,7 +36,6 @@ const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = ( const { pathname, query } = router; const featuredItemId = query.featured as string; const edition: ApiEdition = props.editionResult.data; - const authorsList = EditionCardUtils.getAuthorsList(edition.work_authors); const passedInFeaturedItem = featuredItemId ? edition.instances.find((instance) => { @@ -119,8 +115,10 @@ const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = ( )} {edition.sub_title && {edition.sub_title}} - {authorsList && authorsList.length && ( - By {joinArrayOfElements(authorsList, "")} + {edition.work_authors && edition.work_authors.length && ( + + By + )} {featuredInstance && ( diff --git a/src/components/ResultsList/ResultsList.tsx b/src/components/ResultsList/ResultsList.tsx index 9557c1bd..e5e7fb82 100644 --- a/src/components/ResultsList/ResultsList.tsx +++ b/src/components/ResultsList/ResultsList.tsx @@ -7,25 +7,8 @@ import EmptySearchSvg from "../Svgs/EmptySearchSvg"; import { truncateStringOnWhitespace } from "~/src/util/Util"; import { MAX_TITLE_LENGTH } from "~/src/constants/editioncard"; import { ApiWork } from "~/src/types/WorkQuery"; - -export const getEditionsLinkElement = (work: ApiWork) => { - const editionCount = work.edition_count; - const previewEdition = work.editions && work.editions[0]; - - return editionCount > 1 ? ( - - {`View All ${editionCount} Editions`} - - ) : undefined; -}; +import ViewEditionsLink from "../EditionCard/ViewEditionsLink"; +import AuthorsList from "../AuthorsList/AuthorsList"; const ResultsList: React.FC<{ works: ApiWork[] }> = ({ works }) => { if (works.length === 0) { @@ -66,9 +49,9 @@ const ResultsList: React.FC<{ works: ApiWork[] }> = ({ works }) => { {EditionCardUtils.getSubtitle(work.sub_title)} - {EditionCardUtils.getAuthorsList(work.authors) && ( + {work.authors && work.authors.length && ( - By {EditionCardUtils.getAuthorsList(work.authors)} + By )} = ({ works }) => { title={work.title} isFeaturedEdition={work.edition_count > 1} /> -
{getEditionsLinkElement(work)}
+
); })} diff --git a/src/components/Work/Work.tsx b/src/components/Work/Work.tsx index 249f02bc..8455e42a 100644 --- a/src/components/Work/Work.tsx +++ b/src/components/Work/Work.tsx @@ -13,10 +13,7 @@ import { CardHeading, TemplateAppContainer, } from "@nypl/design-system-react-components"; -import { - joinArrayOfElements, - truncateStringOnWhitespace, -} from "~/src/util/Util"; +import { truncateStringOnWhitespace } from "~/src/util/Util"; import { EditionCard } from "~/src/components/EditionCard/EditionCard"; import WorkDetailDefinitionList from "~/src/components/WorkDetailDefinitionList/WorkDetailDefinitionList"; import { ApiWork, WorkResult } from "~/src/types/WorkQuery"; @@ -27,6 +24,7 @@ import Link from "../Link/Link"; import { MAX_TITLE_LENGTH } from "~/src/constants/editioncard"; import { PLACEHOLDER_LINK } from "~/src/constants/collection"; import DrbBreakout from "../DrbBreakout/DrbBreakout"; +import AuthorsList from "../AuthorsList/AuthorsList"; const WorkDetail: React.FC<{ workResult: WorkResult; backUrl?: string }> = ( props @@ -37,9 +35,8 @@ const WorkDetail: React.FC<{ workResult: WorkResult; backUrl?: string }> = ( const featuredEditionId = query.featured; const work: ApiWork = props.workResult.data; - //Edition Card Preprocessing - const authorsList = EditionCardUtils.getAuthorsList(work.authors); + //Edition Card Preprocessing const passedInFeaturedEdition = featuredEditionId ? work.editions.find( (edition) => edition.edition_id === Number(featuredEditionId) @@ -85,8 +82,10 @@ const WorkDetail: React.FC<{ workResult: WorkResult; backUrl?: string }> = ( {work.title} {work.sub_title && {work.sub_title}} - {authorsList && authorsList.length && ( - By {joinArrayOfElements(authorsList, "")} + {work.authors && work.authors.length && ( + + By + )} {props.backUrl && ( diff --git a/src/components/WorkDetailDefinitionList/WorkDetailDefinitionList.tsx b/src/components/WorkDetailDefinitionList/WorkDetailDefinitionList.tsx index b43e810d..976e3057 100644 --- a/src/components/WorkDetailDefinitionList/WorkDetailDefinitionList.tsx +++ b/src/components/WorkDetailDefinitionList/WorkDetailDefinitionList.tsx @@ -3,8 +3,8 @@ import { List } from "@nypl/design-system-react-components"; import Link from "~/src/components/Link/Link"; import { unique, flattenDeep, uniqueAndSortByFrequency } from "~/src/util/Util"; import { Language, Subject } from "~/src/types/DataModel"; -import EditionCardUtils from "~/src/util/EditionCardUtils"; import { ApiWork } from "~/src/types/WorkQuery"; +import AuthorsList from "../AuthorsList/AuthorsList"; // extract unique language array from instances of a work item const getLanguagesForWork = (work: ApiWork) => @@ -76,7 +76,9 @@ const WorkDetailDefinitionList: React.FC<{ work: ApiWork }> = ({ work }) => { )}
Authors
-
{EditionCardUtils.getAuthorsList(work.authors)}
+
+ +
{work.subjects && work.subjects.length > 0 && ( <>
Subjects
diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 68e99795..53b7917c 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -8,7 +8,6 @@ import { WorkEdition, Identifier, } from "../types/DataModel"; -import Link from "~/src/components/Link/Link"; import { formatUrl, truncateStringOnWhitespace } from "./Util"; import { MAX_PLACE_LENGTH, @@ -16,7 +15,6 @@ import { MAX_SUBTITILE_LENGTH, PLACEHOLDER_COVER_LINK, } from "../constants/editioncard"; -import { ApiSearchQuery } from "../types/SearchQuery"; import { MediaTypes } from "../constants/mediaTypes"; // EditionCard holds all the methods needed to build an Edition Card @@ -76,35 +74,6 @@ export default class EditionCardUtils { ); } - static getAuthorsList(authors: Agent[]): JSX.Element[] { - if (!authors || authors.length === 0) return null; - return authors.map((author: Agent, i: number) => { - const authorLinkText = author.name; - const query: ApiSearchQuery = { - query: author.viaf ? `viaf:${author.viaf}` : `author:${author.name}`, - }; - if (author.viaf) { - query.display = `author:${author.name}`; - } - return ( - - - {authorLinkText} - - {i < authors.length - 1 && ", "} - - ); - }); - } - /** Get Cover Image * @param covers - The list of covers * @returns The URL of the cover that should be displayed. From 92a5c941d5d74cf01949c3fd141629080a8479a9 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Tue, 2 Jan 2024 17:13:34 -0500 Subject: [PATCH 13/31] add limited access ctas --- CHANGELOG.md | 1 + src/__tests__/fixtures/EditionCardFixture.ts | 32 +++++++++++++ src/components/EditionCard/Ctas.tsx | 13 +++++- src/components/EditionCard/DownloadLink.tsx | 20 ++++++--- .../EditionCard/EditionCard.test.tsx | 45 +++++++++++++++++++ src/components/EditionCard/EditionCard.tsx | 3 ++ src/components/EditionCard/ReadOnlineLink.tsx | 28 +++++++----- src/components/EditionCard/UpBlurb.tsx | 22 +++++++++ src/types/DataModel.ts | 1 + src/util/EditionCardUtils.tsx | 16 +++++++ 10 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 src/components/EditionCard/UpBlurb.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ec47409..296084a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Add Physical Edition badge and Scan and Deliver blurb to EDD editions - Add Library Card Required and Featured Editon badges - Update styles for work and edition pages +- Add login buttons and info blurb UP items ## [0.17.5] diff --git a/src/__tests__/fixtures/EditionCardFixture.ts b/src/__tests__/fixtures/EditionCardFixture.ts index 821c737c..28e01279 100644 --- a/src/__tests__/fixtures/EditionCardFixture.ts +++ b/src/__tests__/fixtures/EditionCardFixture.ts @@ -106,3 +106,35 @@ export const eddEdition: WorkEdition = { }, ], }; + +export const upEdition: WorkEdition = { + ...fullEdition, + items: [ + { + links: [ + { + url: "test-link-url", + link_id: 12, + mediaType: "application/epub+xml", + flags: { + catalog: false, + download: false, + reader: true, + nypl_login: true, + }, + }, + { + url: "test-link-url-2", + link_id: 23, + mediaType: "application/epub+zip", + flags: { + catalog: false, + download: true, + reader: false, + nypl_login: true, + }, + }, + ], + }, + ], +}; diff --git a/src/components/EditionCard/Ctas.tsx b/src/components/EditionCard/Ctas.tsx index 7caa8841..43c85b85 100644 --- a/src/components/EditionCard/Ctas.tsx +++ b/src/components/EditionCard/Ctas.tsx @@ -16,9 +16,18 @@ const Ctas: React.FC<{ if (readOnlineLink || downloadLink) { return ( <> - {readOnlineLink && } + {readOnlineLink && ( + + )} {downloadLink && ( - + )} ); diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx index 9b6b2a6f..4d519aa7 100644 --- a/src/components/EditionCard/DownloadLink.tsx +++ b/src/components/EditionCard/DownloadLink.tsx @@ -8,19 +8,29 @@ import { formatUrl } from "~/src/util/Util"; const DownloadLink: React.FC<{ downloadLink: ItemLink; title: string; -}> = ({ downloadLink, title }) => { + isLoggedIn: boolean; +}> = ({ downloadLink, title, isLoggedIn }) => { if (downloadLink && downloadLink.url) { - const formattedUrl = formatUrl(downloadLink.url); + let linkText = "Download PDF"; + let linkUrl = formatUrl(downloadLink.url); + const trackDownloadCta = () => { trackCtaClick({ cta_section: `${title}`, cta_text: "Download", - destination_url: `${formattedUrl}`, + destination_url: `${linkUrl}`, }); }; + + if (downloadLink.flags.nypl_login && !isLoggedIn) { + linkText = "Log in to download PDF"; + linkUrl = `https://login.nypl.org/auth/login?redirect_uri=${encodeURIComponent( + window.location.href + )}`; + } return ( - + diff --git a/src/components/EditionCard/EditionCard.test.tsx b/src/components/EditionCard/EditionCard.test.tsx index cda4b68d..c977cbdc 100644 --- a/src/components/EditionCard/EditionCard.test.tsx +++ b/src/components/EditionCard/EditionCard.test.tsx @@ -5,6 +5,7 @@ import { PLACEHOLDER_COVER_LINK } from "~/src/constants/editioncard"; import { eddEdition, fullEdition, + upEdition, } from "~/src/__tests__/fixtures/EditionCardFixture"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; @@ -146,3 +147,47 @@ describe("Edition with EDD", () => { ).toHaveAttribute("href", "https://www.nypl.org/research/scan-and-deliver"); }); }); + +describe("Edition with UP", () => { + test("Shows Login button when user is not logged in", () => { + document.cookie = `${NYPL_SESSION_ID}=""`; + render(); + expect( + screen.getByRole("link", { name: "Log in to read online" }) + ).toBeInTheDocument(); + expect( + screen.getByRole("link", { name: "Log in to read online" }) + ).toHaveAttribute( + "href", + expect.stringContaining("https://login.nypl.org/auth/login") + ); + expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); + expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); + }); + test("Shows Read Online and Download buttons when user is logged in", () => { + // Set cookie before rendering the component + document.cookie = `${NYPL_SESSION_ID}="randomvalue"`; + render(); + + expect( + screen.getByRole("link", { name: "Read Online" }) + ).toBeInTheDocument(); + expect(screen.getByRole("link", { name: "Read Online" })).toHaveAttribute( + "href", + expect.stringContaining("/read/12") + ); + expect( + screen.getByRole("link", { name: "Download PDF" }) + ).toBeInTheDocument(); + expect(screen.getByRole("link", { name: "Download PDF" })).toHaveAttribute( + "href", + expect.stringContaining("test-link-url") + ); + }); + test("Shows blurb with publisher", () => { + render(); + expect( + screen.getByText("Digitalized by NYPL with permission of publisher_1") + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index 9bcd4403..b6103f91 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -20,6 +20,7 @@ import CardRequiredBadge from "./CardRequiredBadge"; import FeaturedEditionBadge from "./FeaturedEditionBadge"; import PhysicalEditionBadge from "./PhysicalEditionBadge"; import ScanAndDeliverBlurb from "./ScanAndDeliverBlurb"; +import UpBlurb from "./UpBlurb"; export const EditionCard: React.FC<{ edition: WorkEdition; @@ -52,6 +53,7 @@ export const EditionCard: React.FC<{ const coverUrl = EditionCardUtils.getCover(edition.links); const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); + const isUniversityPress = EditionCardUtils.isUniversityPress(previewItem); return ( {isPhysicalEdition && } + {isUniversityPress && } = ({ - readOnlineLink, -}) => { +const ReadOnlineLink: React.FC<{ + readOnlineLink: ItemLink; + isLoggedIn: boolean; +}> = ({ readOnlineLink, isLoggedIn }) => { + let linkText = "Read Online"; + let linkUrl: any = { + pathname: `/read/${readOnlineLink.link_id}`, + }; + + if (readOnlineLink.flags.nypl_login && !isLoggedIn) { + linkText = "Log in to read online"; + linkUrl = `https://login.nypl.org/auth/login?redirect_uri=${encodeURIComponent( + window.location.href + )}`; + } + return ( readOnlineLink && ( - - Read Online + + {linkText} ) diff --git a/src/components/EditionCard/UpBlurb.tsx b/src/components/EditionCard/UpBlurb.tsx new file mode 100644 index 00000000..c24095dc --- /dev/null +++ b/src/components/EditionCard/UpBlurb.tsx @@ -0,0 +1,22 @@ +import { Flex, Icon, Text } from "@nypl/design-system-react-components"; +import React from "react"; +import { Agent } from "~/src/types/DataModel"; +import EditionCardUtils from "~/src/util/EditionCardUtils"; + +const UpBlurb: React.FC<{ publishers: Agent[] }> = ({ publishers }) => { + const publisher = EditionCardUtils.getUpPublisher(publishers); + return ( + + + + Digitalized by NYPL with permission of {publisher} + + + ); +}; + +export default UpBlurb; diff --git a/src/types/DataModel.ts b/src/types/DataModel.ts index 807cd2f8..3b434cee 100644 --- a/src/types/DataModel.ts +++ b/src/types/DataModel.ts @@ -64,6 +64,7 @@ export type LinkFlags = { reader: boolean; edd?: boolean; embed?: boolean; + nypl_login?: boolean; }; export type ItemLink = { diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 53b7917c..ebe95691 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -102,6 +102,14 @@ export default class EditionCardUtils { return ` by ${EditionCardUtils.getFirstAndCountMore(publisherNames)}`; } + static getUpPublisher(publishers: Agent[]): undefined | string { + if (!publishers || publishers.length === 0) return ""; + const publisherNames = publishers.map( + (pubAgent: Agent) => pubAgent && pubAgent.name + ); + return EditionCardUtils.getFirstAndCountMore(publisherNames); + } + // Language Display static getLanguageDisplayText(previewEdition: WorkEdition): string { if ( @@ -207,4 +215,12 @@ export default class EditionCardUtils { return !availableOnline && eddLink !== undefined; } + + static isUniversityPress(item: ApiItem): boolean { + const universityPress = + item && item.links + ? item.links.find((link) => !link.flags.edd && link.flags.nypl_login) + : undefined; + return universityPress !== undefined; + } } From f55bbe07340087184716ad4332243d90b65081bb Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 5 Jan 2024 15:17:59 -0500 Subject: [PATCH 14/31] accessibility updates for ctas and search --- CHANGELOG.md | 1 + src/components/CollectionItemCard/Ctas.tsx | 2 +- .../CollectionItemCard/DownloadLink.tsx | 33 ++++++++--------- .../CollectionItemCard/ReadOnlineLink.tsx | 6 +++- src/components/EditionCard/Ctas.tsx | 1 + src/components/EditionCard/DownloadLink.tsx | 35 +++++++++---------- src/components/EditionCard/ReadOnlineLink.tsx | 9 +++-- src/components/Link/Link.tsx | 11 +++++- src/constants/labels.ts | 4 +-- 9 files changed, 58 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a37b5a01..5f71a52e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Update styles for work and edition pages - Add login buttons and info blurb UP items - SFR-1869: Add assertion step to minimize timeout errors +- Fix: Improve accessibility of CTAs and search bar ## [0.17.5] diff --git a/src/components/CollectionItemCard/Ctas.tsx b/src/components/CollectionItemCard/Ctas.tsx index 0424813d..07a264e0 100644 --- a/src/components/CollectionItemCard/Ctas.tsx +++ b/src/components/CollectionItemCard/Ctas.tsx @@ -16,7 +16,7 @@ const Ctas: React.FC<{ return ( <> {/* If a digital version exists, link directly */} - + ); diff --git a/src/components/CollectionItemCard/DownloadLink.tsx b/src/components/CollectionItemCard/DownloadLink.tsx index 36f09a7e..70919aa7 100644 --- a/src/components/CollectionItemCard/DownloadLink.tsx +++ b/src/components/CollectionItemCard/DownloadLink.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Button, Icon } from "@nypl/design-system-react-components"; +import { Icon } from "@nypl/design-system-react-components"; import CollectionUtils from "~/src/util/CollectionUtils"; import Link from "~/src/components/Link/Link"; import { OpdsLink } from "~/src/types/OpdsModel"; @@ -26,23 +26,20 @@ const DownloadLink: React.FC<{ links: OpdsLink[]; title: string }> = ({ if (selectedLink && selectedLink.href) { return ( - - + + + Download PDF ); } diff --git a/src/components/CollectionItemCard/ReadOnlineLink.tsx b/src/components/CollectionItemCard/ReadOnlineLink.tsx index 74f8e85a..7aed23a5 100644 --- a/src/components/CollectionItemCard/ReadOnlineLink.tsx +++ b/src/components/CollectionItemCard/ReadOnlineLink.tsx @@ -5,7 +5,10 @@ import { formatUrl } from "~/src/util/Util"; import Link from "~/src/components/Link/Link"; // "Read Online" button should only show up if the link was flagged as "reader" or "embed" -const ReadOnlineLink: React.FC<{ links: OpdsLink[] }> = ({ links }) => { +const ReadOnlineLink: React.FC<{ links: OpdsLink[]; title: string }> = ({ + links, + title, +}) => { const localLink = CollectionUtils.getReadLink(links, "readable"); const embeddedLink = CollectionUtils.getReadLink(links, "embedable"); @@ -20,6 +23,7 @@ const ReadOnlineLink: React.FC<{ links: OpdsLink[] }> = ({ links }) => { pathname: formatUrl(readOnlineLink.href), }} linkType="button" + aria-label={`${title} Read Online`} > Read Online diff --git a/src/components/EditionCard/Ctas.tsx b/src/components/EditionCard/Ctas.tsx index 43c85b85..15b821ab 100644 --- a/src/components/EditionCard/Ctas.tsx +++ b/src/components/EditionCard/Ctas.tsx @@ -20,6 +20,7 @@ const Ctas: React.FC<{ )} {downloadLink && ( diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx index 4d519aa7..4679cfdd 100644 --- a/src/components/EditionCard/DownloadLink.tsx +++ b/src/components/EditionCard/DownloadLink.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Icon } from "@nypl/design-system-react-components"; +import { Box, Icon } from "@nypl/design-system-react-components"; import React from "react"; import Link from "~/src/components/Link/Link"; import { trackCtaClick } from "~/src/lib/adobe/Analytics"; @@ -28,26 +28,23 @@ const DownloadLink: React.FC<{ window.location.href )}`; } + return ( - - + + + {linkText} ); diff --git a/src/components/EditionCard/ReadOnlineLink.tsx b/src/components/EditionCard/ReadOnlineLink.tsx index c7165985..e9bb2298 100644 --- a/src/components/EditionCard/ReadOnlineLink.tsx +++ b/src/components/EditionCard/ReadOnlineLink.tsx @@ -7,7 +7,8 @@ import { ItemLink } from "~/src/types/DataModel"; const ReadOnlineLink: React.FC<{ readOnlineLink: ItemLink; isLoggedIn: boolean; -}> = ({ readOnlineLink, isLoggedIn }) => { + title: string; +}> = ({ readOnlineLink, isLoggedIn, title }) => { let linkText = "Read Online"; let linkUrl: any = { pathname: `/read/${readOnlineLink.link_id}`, @@ -23,7 +24,11 @@ const ReadOnlineLink: React.FC<{ return ( readOnlineLink && ( - + {linkText} diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx index 5b1ffb33..549b3e25 100644 --- a/src/components/Link/Link.tsx +++ b/src/components/Link/Link.tsx @@ -10,12 +10,21 @@ interface IProps extends React.AnchorHTMLAttributes { isUnderlined?: boolean; } -const Link = ({ children, to, linkType, isUnderlined }: IProps) => { +const Link = ({ + children, + to, + linkType, + isUnderlined, + "aria-label": ariaLabel, + onClick, +}: IProps) => { return ( {children} diff --git a/src/constants/labels.ts b/src/constants/labels.ts index 3c37571e..851f53f1 100644 --- a/src/constants/labels.ts +++ b/src/constants/labels.ts @@ -96,6 +96,6 @@ export const FormatTypes = [ ]; export const errorMessagesText = { - emptySearch: "Please enter a search term", - invalidDate: "Start date must be before End date", + emptySearch: "Error: Please enter a search term", + invalidDate: "Error: Start date must be before End date", }; From 3788ca448f275afa6bd643245f14579861ac8dbc Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 5 Jan 2024 15:22:46 -0500 Subject: [PATCH 15/31] add aria-label to edd link --- src/components/CollectionItemCard/Ctas.tsx | 2 +- src/components/CollectionItemCard/EddLink.tsx | 5 ++++- src/components/EditionCard/Ctas.tsx | 2 +- src/components/EditionCard/EddLink.tsx | 5 ++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/CollectionItemCard/Ctas.tsx b/src/components/CollectionItemCard/Ctas.tsx index 07a264e0..fde53e72 100644 --- a/src/components/CollectionItemCard/Ctas.tsx +++ b/src/components/CollectionItemCard/Ctas.tsx @@ -23,7 +23,7 @@ const Ctas: React.FC<{ } if (eddLink) { - return ; + return ; } return <>Not yet available; diff --git a/src/components/CollectionItemCard/EddLink.tsx b/src/components/CollectionItemCard/EddLink.tsx index 4638dc68..62c21142 100644 --- a/src/components/CollectionItemCard/EddLink.tsx +++ b/src/components/CollectionItemCard/EddLink.tsx @@ -5,7 +5,8 @@ import Link from "~/src/components/Link/Link"; export const EddLink: React.FC<{ eddLink: OpdsLink; isLoggedIn: boolean; -}> = ({ eddLink, isLoggedIn }) => { + title: string; +}> = ({ eddLink, isLoggedIn, title }) => { if (isLoggedIn) { return ( <> @@ -14,6 +15,7 @@ export const EddLink: React.FC<{ to={`https://${eddLink.href}`} linkType="button" target="_blank" + aria-label={`Request scan for ${title}`} > Request Scan @@ -27,6 +29,7 @@ export const EddLink: React.FC<{ window.location.href )}`} linkType="button" + aria-label={`Log in to request scan for ${title}`} > Log in to request scan diff --git a/src/components/EditionCard/Ctas.tsx b/src/components/EditionCard/Ctas.tsx index 15b821ab..8562745c 100644 --- a/src/components/EditionCard/Ctas.tsx +++ b/src/components/EditionCard/Ctas.tsx @@ -39,7 +39,7 @@ const Ctas: React.FC<{ // Offer EDD if available if (eddLink !== undefined) { - return ; + return ; } return <>Not yet available; diff --git a/src/components/EditionCard/EddLink.tsx b/src/components/EditionCard/EddLink.tsx index 9713c753..a38809a1 100644 --- a/src/components/EditionCard/EddLink.tsx +++ b/src/components/EditionCard/EddLink.tsx @@ -5,7 +5,8 @@ import { ItemLink } from "~/src/types/DataModel"; const EddLink: React.FC<{ eddLink: ItemLink; isLoggedIn: boolean; -}> = ({ eddLink, isLoggedIn }) => { + title: string; +}> = ({ eddLink, isLoggedIn, title }) => { if (isLoggedIn) { return ( <> @@ -14,6 +15,7 @@ const EddLink: React.FC<{ to={`https://${eddLink.url}`} linkType="button" target="_blank" + aria-label={`Request scan for ${title}`} > Request Scan @@ -27,6 +29,7 @@ const EddLink: React.FC<{ window.location.href )}`} linkType="buttonSecondary" + aria-label={`Log in to request scan for ${title}`} > Log in to request scan From 2871045d88f8a0d11cd399dd73aa98294f34dbb8 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 5 Jan 2024 15:46:49 -0500 Subject: [PATCH 16/31] update tests --- .../componentHelpers/FilterYears.tsx | 2 +- src/__tests__/componentHelpers/SearchForm.tsx | 4 +-- .../EditionCard/EditionCard.test.tsx | 35 +++++++++---------- src/components/EditionCard/ReadOnlineLink.tsx | 2 +- .../InstanceCard/InstanceCard.test.tsx | 14 ++++---- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/__tests__/componentHelpers/FilterYears.tsx b/src/__tests__/componentHelpers/FilterYears.tsx index b1508f91..e5d2862a 100644 --- a/src/__tests__/componentHelpers/FilterYears.tsx +++ b/src/__tests__/componentHelpers/FilterYears.tsx @@ -118,7 +118,7 @@ export const FilterYearsTests = ( await user.click(applyButton); expect( - screen.getByText("Start date must be before End date") + screen.getByText("Error: Start date must be before End date") ).toBeInTheDocument(); expect(mockRouter).toMatchObject({}); }); diff --git a/src/__tests__/componentHelpers/SearchForm.tsx b/src/__tests__/componentHelpers/SearchForm.tsx index fd12753d..71251d1c 100644 --- a/src/__tests__/componentHelpers/SearchForm.tsx +++ b/src/__tests__/componentHelpers/SearchForm.tsx @@ -53,7 +53,7 @@ export const searchFormTests = (mockRouter) => { "Tom Nook" ); expect( - screen.queryByText("Please enter a search term") + screen.queryByText("Error: Please enter a search term") ).not.toBeInTheDocument(); expect(mockRouter).toMatchObject({ @@ -74,7 +74,7 @@ export const searchFormTests = (mockRouter) => { expect(mockRouter).toMatchObject({}); expect( - screen.getByText("Please enter a search term") + screen.getByText("Error: Please enter a search term") ).toBeInTheDocument(); }); }); diff --git a/src/components/EditionCard/EditionCard.test.tsx b/src/components/EditionCard/EditionCard.test.tsx index c977cbdc..a147cb36 100644 --- a/src/components/EditionCard/EditionCard.test.tsx +++ b/src/components/EditionCard/EditionCard.test.tsx @@ -108,10 +108,10 @@ describe("Edition with EDD", () => { test("Shows Login button when EDD is available but user is not logged in", () => { render(); expect( - screen.getByRole("link", { name: "Log in to request scan" }) + screen.getByRole("link", { name: "Log in to request scan for title" }) ).toBeInTheDocument(); expect( - screen.getByRole("link", { name: "Log in to request scan" }) + screen.getByRole("link", { name: "Log in to request scan for title" }) ).toHaveAttribute( "href", expect.stringContaining("https://login.nypl.org/auth/login") @@ -126,12 +126,11 @@ describe("Edition with EDD", () => { render(); expect( - screen.getByRole("link", { name: "Request Scan" }) + screen.getByRole("link", { name: "Request scan for title" }) ).toBeInTheDocument(); - expect(screen.getByRole("link", { name: "Request Scan" })).toHaveAttribute( - "href", - expect.stringContaining("test-link-url") - ); + expect( + screen.getByRole("link", { name: "Request scan for title" }) + ).toHaveAttribute("href", expect.stringContaining("test-link-url")); expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); @@ -153,10 +152,10 @@ describe("Edition with UP", () => { document.cookie = `${NYPL_SESSION_ID}=""`; render(); expect( - screen.getByRole("link", { name: "Log in to read online" }) + screen.getByRole("link", { name: "title Log in to read online" }) ).toBeInTheDocument(); expect( - screen.getByRole("link", { name: "Log in to read online" }) + screen.getByRole("link", { name: "title Log in to read online" }) ).toHaveAttribute( "href", expect.stringContaining("https://login.nypl.org/auth/login") @@ -170,19 +169,17 @@ describe("Edition with UP", () => { render(); expect( - screen.getByRole("link", { name: "Read Online" }) + screen.getByRole("link", { name: "title Read Online" }) ).toBeInTheDocument(); - expect(screen.getByRole("link", { name: "Read Online" })).toHaveAttribute( - "href", - expect.stringContaining("/read/12") - ); expect( - screen.getByRole("link", { name: "Download PDF" }) + screen.getByRole("link", { name: "title Read Online" }) + ).toHaveAttribute("href", expect.stringContaining("/read/12")); + expect( + screen.getByRole("link", { name: "title Download PDF" }) ).toBeInTheDocument(); - expect(screen.getByRole("link", { name: "Download PDF" })).toHaveAttribute( - "href", - expect.stringContaining("test-link-url") - ); + expect( + screen.getByRole("link", { name: "title Download PDF" }) + ).toHaveAttribute("href", expect.stringContaining("test-link-url")); }); test("Shows blurb with publisher", () => { render(); diff --git a/src/components/EditionCard/ReadOnlineLink.tsx b/src/components/EditionCard/ReadOnlineLink.tsx index e9bb2298..3d0f5c2a 100644 --- a/src/components/EditionCard/ReadOnlineLink.tsx +++ b/src/components/EditionCard/ReadOnlineLink.tsx @@ -27,7 +27,7 @@ const ReadOnlineLink: React.FC<{ {linkText} diff --git a/src/components/InstanceCard/InstanceCard.test.tsx b/src/components/InstanceCard/InstanceCard.test.tsx index 4ba9f336..20d6d245 100644 --- a/src/components/InstanceCard/InstanceCard.test.tsx +++ b/src/components/InstanceCard/InstanceCard.test.tsx @@ -10,6 +10,7 @@ const fullInstance: Instance = { instance_id: 12345, publishers: [{ name: "publisher_1", roles: ["publisher"] }], publication_place: "Paris", + title: "title", items: [ { links: [ @@ -174,10 +175,10 @@ describe("Instance with EDD", () => { ); expect( - screen.getByRole("link", { name: "Log in to request scan" }) + screen.getByRole("link", { name: "Log in to request scan for title" }) ).toBeInTheDocument(); expect( - screen.getByRole("link", { name: "Log in to request scan" }) + screen.getByRole("link", { name: "Log in to request scan for title" }) ).toHaveAttribute( "href", expect.stringContaining("https://login.nypl.org/auth/login") @@ -194,12 +195,11 @@ describe("Instance with EDD", () => { ); expect( - screen.getByRole("link", { name: "Request Scan" }) + screen.getByRole("link", { name: "Request scan for title" }) ).toBeInTheDocument(); - expect(screen.getByRole("link", { name: "Request Scan" })).toHaveAttribute( - "href", - expect.stringContaining("test-link-url") - ); + expect( + screen.getByRole("link", { name: "Request scan for title" }) + ).toHaveAttribute("href", expect.stringContaining("test-link-url")); expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); From 9a7cc3b27c1ea04951f9d228099b27f6da305da2 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Tue, 9 Jan 2024 15:04:34 -0500 Subject: [PATCH 17/31] resolve accessibility review issues --- src/components/CollectionCard/CollectionCard.tsx | 4 ---- src/components/CollectionItemCard/CollectionItemCard.test.tsx | 2 +- src/components/CollectionItemCard/CollectionItemCard.tsx | 3 +-- src/components/EditionDetail/Edition.test.tsx | 2 +- src/components/InstanceCard/InstanceCard.test.tsx | 4 ++-- src/components/InstanceCard/InstanceCard.tsx | 2 +- 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/components/CollectionCard/CollectionCard.tsx b/src/components/CollectionCard/CollectionCard.tsx index 62b0959c..5325ef78 100644 --- a/src/components/CollectionCard/CollectionCard.tsx +++ b/src/components/CollectionCard/CollectionCard.tsx @@ -5,7 +5,6 @@ import { CardHeading, } from "@nypl/design-system-react-components"; import { Opds2Feed } from "~/src/types/OpdsModel"; -import CollectionUtils from "~/src/util/CollectionUtils"; import { truncateStringOnWhitespace } from "~/src/util/Util"; import { MAX_DESCRIPTION_LENGTH, @@ -16,11 +15,8 @@ import { export const CollectionCard: React.FC<{ collection: Opds2Feed }> = ({ collection, }) => { - const collectionId = CollectionUtils.getId(collection.links); - return ( { expect(screen.queryByText("Read Online")).toBeInTheDocument(); }); test("Shows cover", () => { - expect(screen.getByAltText("Cover").closest("img").src).toEqual( + expect(screen.getByAltText("").closest("img").src).toEqual( "https://test-sfr-covers.s3.amazonaws.com/default/defaultCover.png" ); }); diff --git a/src/components/CollectionItemCard/CollectionItemCard.tsx b/src/components/CollectionItemCard/CollectionItemCard.tsx index 7429a4b9..93abd1af 100644 --- a/src/components/CollectionItemCard/CollectionItemCard.tsx +++ b/src/components/CollectionItemCard/CollectionItemCard.tsx @@ -31,12 +31,11 @@ export const CollectionItemCard: React.FC<{ src: CollectionUtils.getCover(collectionItem), size: "xsmall", aspectRatio: "original", - alt: "Cover", + alt: ``, }} layout="row" isBordered isAlignedRightActions - id={`card-${CollectionUtils.getId(collectionItem.links)}`} p="s" > { name: "1923", }); expect(featuredEditionHeadings.length).toEqual(2); - expect(screen.getAllByAltText("Cover").length).toBe(2); + expect(screen.getAllByAltText("").length).toBe(2); expect( screen .getAllByText("License: Public Domain when viewed in the US")[0] diff --git a/src/components/InstanceCard/InstanceCard.test.tsx b/src/components/InstanceCard/InstanceCard.test.tsx index 20d6d245..f1c857cf 100644 --- a/src/components/InstanceCard/InstanceCard.test.tsx +++ b/src/components/InstanceCard/InstanceCard.test.tsx @@ -109,7 +109,7 @@ describe("Instance Card with Valid Data", () => { ); }); test("Shows cover", () => { - expect(screen.getByAltText("Cover").closest("img").src).toEqual( + expect(screen.getByAltText("").closest("img").src).toEqual( "https://test-cover/" ); }); @@ -144,7 +144,7 @@ describe("Instance Card with Minmal Data", () => { expect(screen.getByText("Find in Library Unavailable")).toBeInTheDocument(); }); test("Shows cover", () => { - expect(screen.getByAltText("Cover").closest("img").src).toEqual( + expect(screen.getByAltText("").closest("img").src).toEqual( PLACEHOLDER_COVER_LINK ); }); diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index 5510d569..08b0904f 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -57,7 +57,7 @@ export const InstanceCard: React.FC<{ src: EditionCardUtils.getCover(edition.links), size: "xsmall", aspectRatio: "original", - alt: "Cover", + alt: ``, }} layout="row" isAlignedRightActions From e8a1023562e7788f1aad581d3e4fc58af13c78ae Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 9 Feb 2024 13:51:04 -0500 Subject: [PATCH 18/31] implement auth for up download --- CHANGELOG.md | 9 +++++++++ README.md | 8 ++++++++ config/appConfig.ts | 4 ++-- src/components/EditionCard/Ctas.tsx | 11 +++++++++-- src/components/EditionCard/DownloadLink.tsx | 12 +++++++++--- src/components/EditionCard/EditionCard.tsx | 10 +--------- src/components/InstanceCard/InstanceCard.tsx | 11 +---------- src/lib/api/SearchApi.ts | 16 ++++++++++++++++ 8 files changed, 55 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84fffe6d..cc3ab47f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGE LOG +## [Pre-release] + +- Add Physical Edition badge and Scan and Deliver blurb to EDD editions +- Add Library Card Required and Featured Editon badges +- Update styles for work and edition pages +- Add login buttons and info blurb UP items +- Fix: Improve accessibility of CTAs and search bar +- Update README to include info about testing login locally + ## [0.17.6] - Upgrade newrelic to v11.5.0 diff --git a/README.md b/README.md index 2f423053..279b35b3 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,14 @@ Run `npm run dev` to start the local server at `localhost:3000` To view pdfs locally through the webreader, you will need to set up a local proxy. If you used environment variables from `.env.sample` you should be able to pull the [web-reader](https://github.com/NYPL-Simplified/web-reader) repo, install it, and run `npm run cors-proxy`. See the web-reader repo for more [instructions](https://github.com/NYPL-Simplified/web-reader#cors-proxy) +In order to successfully login under a local deployment, you will need to update your machine's `etc/hosts` file. This hosts file maps local host names to ip addresses. + +Add this to your `etc/hosts` file: + +``` + 127.0.0.1 local.nypl.org +``` + ### Dependencies - NextJS diff --git a/config/appConfig.ts b/config/appConfig.ts index 0a9e593d..6d0de008 100644 --- a/config/appConfig.ts +++ b/config/appConfig.ts @@ -8,8 +8,8 @@ const appConfig = { api: { url: { local: "localhost:5000", - development: "http://drb-api-qa.nypl.org", - qa: "http://drb-api-qa.nypl.org", + development: "https://drb-api-qa.nypl.org", + qa: "https://drb-api-qa.nypl.org", production: "http://drb-api-qa.nypl.org", }, searchPath: "/search", diff --git a/src/components/EditionCard/Ctas.tsx b/src/components/EditionCard/Ctas.tsx index 8562745c..7389cc5e 100644 --- a/src/components/EditionCard/Ctas.tsx +++ b/src/components/EditionCard/Ctas.tsx @@ -1,4 +1,6 @@ import React from "react"; +import { useCookies } from "react-cookie"; +import { NYPL_SESSION_ID } from "~/src/constants/auth"; import { ApiItem } from "~/src/types/DataModel"; import EditionCardUtils from "~/src/util/EditionCardUtils"; import DownloadLink from "./DownloadLink"; @@ -8,8 +10,12 @@ import ReadOnlineLink from "./ReadOnlineLink"; const Ctas: React.FC<{ item: ApiItem | undefined; title: string; - isLoggedIn: boolean; -}> = ({ item, title, isLoggedIn }) => { +}> = ({ item, title }) => { + // cookies defaults to be undefined if not fonud + const [cookies] = useCookies([NYPL_SESSION_ID]); + const loginCookie = cookies[NYPL_SESSION_ID]; + const isLoggedIn = !!loginCookie; + const readOnlineLink = EditionCardUtils.getReadOnlineLink(item); const downloadLink = EditionCardUtils.selectDownloadLink(item); @@ -28,6 +34,7 @@ const Ctas: React.FC<{ downloadLink={downloadLink} title={title} isLoggedIn={isLoggedIn} + loginCookie={loginCookie} /> )} diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx index 4679cfdd..ed9b8f32 100644 --- a/src/components/EditionCard/DownloadLink.tsx +++ b/src/components/EditionCard/DownloadLink.tsx @@ -2,6 +2,7 @@ import { Box, Icon } from "@nypl/design-system-react-components"; import React from "react"; import Link from "~/src/components/Link/Link"; import { trackCtaClick } from "~/src/lib/adobe/Analytics"; +import { fulfillFetcher } from "~/src/lib/api/SearchApi"; import { ItemLink } from "~/src/types/DataModel"; import { formatUrl } from "~/src/util/Util"; @@ -9,12 +10,17 @@ const DownloadLink: React.FC<{ downloadLink: ItemLink; title: string; isLoggedIn: boolean; -}> = ({ downloadLink, title, isLoggedIn }) => { + loginCookie?: string; +}> = ({ downloadLink, title, isLoggedIn, loginCookie }) => { if (downloadLink && downloadLink.url) { let linkText = "Download PDF"; let linkUrl = formatUrl(downloadLink.url); - const trackDownloadCta = () => { + const handleOnClick = (e) => { + if (linkUrl.includes("/fulfill/")) { + e.preventDefault(); + fulfillFetcher(linkUrl, loginCookie); + } trackCtaClick({ cta_section: `${title}`, cta_text: "Download", @@ -34,7 +40,7 @@ const DownloadLink: React.FC<{ handleOnClick(e)} aria-label={`${title} Download PDF`} > = ({ edition, title, isFeaturedEdition }) => { - const [cookies] = useCookies([NYPL_SESSION_ID]); - const previewItem = EditionCardUtils.getPreviewItem(edition.items); const editionYearElem = (edition: WorkEdition) => { @@ -133,11 +129,7 @@ export const EditionCard: React.FC<{ }} gap="xs" > - +
diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index 08b0904f..34a3b1d2 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -11,8 +11,6 @@ import { } from "@nypl/design-system-react-components"; import EditionCardUtils from "~/src/util/EditionCardUtils"; import Link from "../Link/Link"; -import { useCookies } from "react-cookie"; -import { NYPL_SESSION_ID } from "~/src/constants/auth"; import Ctas from "../EditionCard/Ctas"; import PublisherAndLocation from "../EditionCard/PublisherAndLocation"; import WorldCat from "./WorldCat"; @@ -31,9 +29,6 @@ export const InstanceCard: React.FC<{ instance: Instance; isFeaturedEdition?: boolean; }> = (props) => { - // cookies defaults to be undefined if not fonud - const [cookies] = useCookies([NYPL_SESSION_ID]); - const edition = props.edition; const instance: Instance = props.instance; const isFeaturedEdition = props.isFeaturedEdition; @@ -95,11 +90,7 @@ export const InstanceCard: React.FC<{ whiteSpace="nowrap" gap="xs" > - + diff --git a/src/lib/api/SearchApi.ts b/src/lib/api/SearchApi.ts index ffb4e5e3..8227c406 100644 --- a/src/lib/api/SearchApi.ts +++ b/src/lib/api/SearchApi.ts @@ -120,3 +120,19 @@ export const readFetcher = async (linkId: number) => { throw new Error(`cannot find work with linkId ${linkId}`); } }; + +export const fulfillFetcher = async (fulfillUrl, nyplIdentityCookie) => { + const url = new URL(fulfillUrl); + const res = await fetch(url.toString(), { + method: "GET", + headers: { + Authorization: `Bearer ${nyplIdentityCookie.access_token}`, + "Content-Type": "application/json", + }, + }); + if (res.ok) { + return res.json(); + } else { + throw new Error(`Unable to download PDF`); + } +}; From 69aae778c853396f847083a60d9ceb8c3889af26 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 9 Feb 2024 17:09:26 -0500 Subject: [PATCH 19/31] update api request --- src/components/EditionCard/DownloadLink.tsx | 7 +++++-- src/lib/api/SearchApi.ts | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx index ed9b8f32..edfa4a92 100644 --- a/src/components/EditionCard/DownloadLink.tsx +++ b/src/components/EditionCard/DownloadLink.tsx @@ -1,4 +1,5 @@ import { Box, Icon } from "@nypl/design-system-react-components"; +import { useRouter } from "next/router"; import React from "react"; import Link from "~/src/components/Link/Link"; import { trackCtaClick } from "~/src/lib/adobe/Analytics"; @@ -12,14 +13,16 @@ const DownloadLink: React.FC<{ isLoggedIn: boolean; loginCookie?: string; }> = ({ downloadLink, title, isLoggedIn, loginCookie }) => { + const router = useRouter(); if (downloadLink && downloadLink.url) { let linkText = "Download PDF"; let linkUrl = formatUrl(downloadLink.url); - const handleOnClick = (e) => { + const handleOnClick = async (e) => { if (linkUrl.includes("/fulfill/")) { e.preventDefault(); - fulfillFetcher(linkUrl, loginCookie); + const redirectUrl = await fulfillFetcher(linkUrl, loginCookie); + router.push(redirectUrl); } trackCtaClick({ cta_section: `${title}`, diff --git a/src/lib/api/SearchApi.ts b/src/lib/api/SearchApi.ts index 8227c406..09f1ca47 100644 --- a/src/lib/api/SearchApi.ts +++ b/src/lib/api/SearchApi.ts @@ -127,12 +127,11 @@ export const fulfillFetcher = async (fulfillUrl, nyplIdentityCookie) => { method: "GET", headers: { Authorization: `Bearer ${nyplIdentityCookie.access_token}`, - "Content-Type": "application/json", }, }); if (res.ok) { - return res.json(); + return res.url; } else { - throw new Error(`Unable to download PDF`); + throw new Error(`Unable to download UP PDF`); } }; From bc67b97af46ea9b818f80b8d4481056937ffb92b Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 9 Feb 2024 17:23:50 -0500 Subject: [PATCH 20/31] update tests --- src/__tests__/fixtures/InstanceCardFixture.ts | 86 ++++++++++++++++++ .../EditionCard/EditionCard.test.tsx | 2 + .../InstanceCard/InstanceCard.test.tsx | 89 ++----------------- 3 files changed, 93 insertions(+), 84 deletions(-) create mode 100644 src/__tests__/fixtures/InstanceCardFixture.ts diff --git a/src/__tests__/fixtures/InstanceCardFixture.ts b/src/__tests__/fixtures/InstanceCardFixture.ts new file mode 100644 index 00000000..ca708138 --- /dev/null +++ b/src/__tests__/fixtures/InstanceCardFixture.ts @@ -0,0 +1,86 @@ +import { Instance } from "~/src/types/DataModel"; + +export const fullInstance: Instance = { + instance_id: 12345, + publishers: [{ name: "publisher_1", roles: ["publisher"] }], + publication_place: "Paris", + title: "title", + items: [ + { + links: [ + { + url: "test-link-url", + link_id: 12, + mediaType: "application/epub+xml", + flags: { + catalog: false, + download: false, + reader: true, + }, + }, + { + url: "test-link-url-2", + link_id: 23, + mediaType: "application/epub+zip", + flags: { + catalog: false, + download: true, + reader: false, + }, + }, + { + url: "test-link-url-3", + link_id: 34, + mediaType: "application/html+edd", + flags: { + catalog: false, + download: false, + reader: false, + edd: true, + }, + }, + ], + rights: [ + { + license: "license content", + rightsStatement: "test rights statement", + }, + ], + }, + ], + identifiers: [ + { + authority: "ddc", + identifier: "300", + }, + { + authority: "oclc", + identifier: "1014189544", + }, + { + authority: "oclc", + identifier: "1030816762", + }, + ], +}; + +export const eddInstance: Instance = { + ...fullInstance, + items: [ + { + links: [ + { + url: "test-link-url", + link_id: 1, + mediaType: "application/html+edd", + flags: { + catalog: false, + download: false, + reader: false, + edd: true, + }, + }, + ], + }, + ], +}; diff --git a/src/components/EditionCard/EditionCard.test.tsx b/src/components/EditionCard/EditionCard.test.tsx index a147cb36..a69da820 100644 --- a/src/components/EditionCard/EditionCard.test.tsx +++ b/src/components/EditionCard/EditionCard.test.tsx @@ -9,6 +9,8 @@ import { } from "~/src/__tests__/fixtures/EditionCardFixture"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; +jest.mock("next/router", () => require("next-router-mock")); + describe("Edition Card with Valid Data", () => { beforeEach(() => { render(); diff --git a/src/components/InstanceCard/InstanceCard.test.tsx b/src/components/InstanceCard/InstanceCard.test.tsx index f1c857cf..54c337fa 100644 --- a/src/components/InstanceCard/InstanceCard.test.tsx +++ b/src/components/InstanceCard/InstanceCard.test.tsx @@ -5,91 +5,12 @@ import { Instance, WorkEdition } from "~/src/types/DataModel"; import { PLACEHOLDER_COVER_LINK } from "~/src/constants/editioncard"; import { fullEdition } from "~/src/__tests__/fixtures/EditionCardFixture"; import { NYPL_SESSION_ID } from "~/src/constants/auth"; +import { + fullInstance, + eddInstance, +} from "~/src/__tests__/fixtures/InstanceCardFixture"; -const fullInstance: Instance = { - instance_id: 12345, - publishers: [{ name: "publisher_1", roles: ["publisher"] }], - publication_place: "Paris", - title: "title", - items: [ - { - links: [ - { - url: "test-link-url", - link_id: 12, - mediaType: "application/epub+xml", - flags: { - catalog: false, - download: false, - reader: true, - }, - }, - { - url: "test-link-url-2", - link_id: 23, - mediaType: "application/epub+zip", - flags: { - catalog: false, - download: true, - reader: false, - }, - }, - { - url: "test-link-url-3", - link_id: 34, - mediaType: "application/html+edd", - flags: { - catalog: false, - download: false, - reader: false, - edd: true, - }, - }, - ], - rights: [ - { - license: "license content", - rightsStatement: "test rights statement", - }, - ], - }, - ], - identifiers: [ - { - authority: "ddc", - identifier: "300", - }, - { - authority: "oclc", - identifier: "1014189544", - }, - { - authority: "oclc", - identifier: "1030816762", - }, - ], -}; - -const eddInstance: Instance = { - ...fullInstance, - items: [ - { - links: [ - { - url: "test-link-url", - link_id: 1, - mediaType: "application/html+edd", - flags: { - catalog: false, - download: false, - reader: false, - edd: true, - }, - }, - ], - }, - ], -}; +jest.mock("next/router", () => require("next-router-mock")); describe("Instance Card with Valid Data", () => { beforeEach(() => { From 036a512bd2fdccdd63024eb1109df053cddac84a Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Mon, 12 Feb 2024 17:54:33 -0500 Subject: [PATCH 21/31] add tests for library card required badge --- src/__tests__/fixtures/InstanceCardFixture.ts | 32 ++++++++++++ .../EditionCard/EditionCard.test.tsx | 6 ++- src/components/EditionCard/EditionCard.tsx | 3 +- .../InstanceCard/InstanceCard.test.tsx | 52 ++++++++++++++++++- src/components/InstanceCard/InstanceCard.tsx | 6 ++- 5 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/__tests__/fixtures/InstanceCardFixture.ts b/src/__tests__/fixtures/InstanceCardFixture.ts index ca708138..664666fb 100644 --- a/src/__tests__/fixtures/InstanceCardFixture.ts +++ b/src/__tests__/fixtures/InstanceCardFixture.ts @@ -84,3 +84,35 @@ export const eddInstance: Instance = { }, ], }; + +export const upInstance: Instance = { + ...fullInstance, + items: [ + { + links: [ + { + url: "test-link-url", + link_id: 12, + mediaType: "application/epub+xml", + flags: { + catalog: false, + download: false, + reader: true, + nypl_login: true, + }, + }, + { + url: "test-link-url-2", + link_id: 23, + mediaType: "application/epub+zip", + flags: { + catalog: false, + download: true, + reader: false, + nypl_login: true, + }, + }, + ], + }, + ], +}; diff --git a/src/components/EditionCard/EditionCard.test.tsx b/src/components/EditionCard/EditionCard.test.tsx index a69da820..c4f4a652 100644 --- a/src/components/EditionCard/EditionCard.test.tsx +++ b/src/components/EditionCard/EditionCard.test.tsx @@ -137,7 +137,7 @@ describe("Edition with EDD", () => { expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); - test("Shows 'Physical Edition' badge and 'Scan and Deliver' link ", () => { + test("Shows 'Physical Edition' badge and 'Scan and Deliver' link", () => { render(); expect(screen.getByText("Physical Edition")).toBeInTheDocument(); expect( @@ -165,6 +165,10 @@ describe("Edition with UP", () => { expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); }); + test("Shows 'Library Card Required' badge", () => { + render(); + expect(screen.getByText("Library Card Required")).toBeInTheDocument(); + }); test("Shows Read Online and Download buttons when user is logged in", () => { // Set cookie before rendering the component document.cookie = `${NYPL_SESSION_ID}="randomvalue"`; diff --git a/src/components/EditionCard/EditionCard.tsx b/src/components/EditionCard/EditionCard.tsx index 4144722f..a5143e24 100644 --- a/src/components/EditionCard/EditionCard.tsx +++ b/src/components/EditionCard/EditionCard.tsx @@ -50,6 +50,7 @@ export const EditionCard: React.FC<{ const coverUrl = EditionCardUtils.getCover(edition.links); const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); const isUniversityPress = EditionCardUtils.isUniversityPress(previewItem); + const isLoginRequired = isPhysicalEdition || isUniversityPress; return ( - {isPhysicalEdition && } + {isLoginRequired && } {isFeaturedEdition && } require("next-router-mock")); @@ -136,3 +140,49 @@ describe("Instance with EDD", () => { ).toHaveAttribute("href", "https://www.nypl.org/research/scan-and-deliver"); }); }); + +describe("Instance with UP", () => { + test("Shows Login button when user is not logged in", () => { + document.cookie = `${NYPL_SESSION_ID}=""`; + render(); + expect( + screen.getByRole("link", { name: "title Log in to read online" }) + ).toBeInTheDocument(); + expect( + screen.getByRole("link", { name: "title Log in to read online" }) + ).toHaveAttribute( + "href", + expect.stringContaining("https://login.nypl.org/auth/login") + ); + expect(screen.queryByText("Download PDF")).not.toBeInTheDocument(); + expect(screen.queryByText("Read Online")).not.toBeInTheDocument(); + }); + test("Shows 'Library Card Required' badge", () => { + render(); + expect(screen.getByText("Library Card Required")).toBeInTheDocument(); + }); + test("Shows Read Online and Download buttons when user is logged in", () => { + // Set cookie before rendering the component + document.cookie = `${NYPL_SESSION_ID}="randomvalue"`; + render(); + + expect( + screen.getByRole("link", { name: "title Read Online" }) + ).toBeInTheDocument(); + expect( + screen.getByRole("link", { name: "title Read Online" }) + ).toHaveAttribute("href", expect.stringContaining("/read/12")); + expect( + screen.getByRole("link", { name: "title Download PDF" }) + ).toBeInTheDocument(); + expect( + screen.getByRole("link", { name: "title Download PDF" }) + ).toHaveAttribute("href", expect.stringContaining("test-link-url")); + }); + test("Shows blurb with publisher", () => { + render(); + expect( + screen.getByText("Digitalized by NYPL with permission of publisher_1") + ).toBeInTheDocument(); + }); +}); diff --git a/src/components/InstanceCard/InstanceCard.tsx b/src/components/InstanceCard/InstanceCard.tsx index 34a3b1d2..44f5df04 100644 --- a/src/components/InstanceCard/InstanceCard.tsx +++ b/src/components/InstanceCard/InstanceCard.tsx @@ -18,6 +18,7 @@ import CardRequiredBadge from "../EditionCard/CardRequiredBadge"; import FeaturedEditionBadge from "../EditionCard/FeaturedEditionBadge"; import PhysicalEditionBadge from "../EditionCard/PhysicalEditionBadge"; import ScanAndDeliverBlurb from "../EditionCard/ScanAndDeliverBlurb"; +import UpBlurb from "../EditionCard/UpBlurb"; // Creates an Instance card out of the Edition Year and Instance object // Note: Edition Year only needs to be passed because `instance.publication_date` @@ -34,6 +35,8 @@ export const InstanceCard: React.FC<{ const isFeaturedEdition = props.isFeaturedEdition; const previewItem = EditionCardUtils.getPreviewItem(instance.items); const isPhysicalEdition = EditionCardUtils.isPhysicalEdition(previewItem); + const isUniversityPress = EditionCardUtils.isUniversityPress(previewItem); + const isLoginRequired = isPhysicalEdition || isUniversityPress; return ( - {isPhysicalEdition && } + {isLoginRequired && } {isFeaturedEdition && } {EditionCardUtils.getLicense(previewItem)} {isPhysicalEdition && } + {isUniversityPress && } Date: Tue, 13 Feb 2024 16:51:42 -0500 Subject: [PATCH 22/31] redirect to login if 401 error --- src/components/CollectionItemCard/EddLink.tsx | 5 ++--- src/components/EditionCard/DownloadLink.tsx | 9 ++++----- src/components/EditionCard/EddLink.tsx | 5 ++--- src/components/EditionCard/ReadOnlineLink.tsx | 5 ++--- src/constants/links.ts | 2 ++ src/lib/api/SearchApi.ts | 5 +++++ 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/components/CollectionItemCard/EddLink.tsx b/src/components/CollectionItemCard/EddLink.tsx index 62c21142..cd4904a8 100644 --- a/src/components/CollectionItemCard/EddLink.tsx +++ b/src/components/CollectionItemCard/EddLink.tsx @@ -1,6 +1,7 @@ import React from "react"; import { OpdsLink } from "~/src/types/OpdsModel"; import Link from "~/src/components/Link/Link"; +import { LOGIN_LINK_BASE } from "~/src/constants/links"; export const EddLink: React.FC<{ eddLink: OpdsLink; @@ -25,9 +26,7 @@ export const EddLink: React.FC<{ return ( <> diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx index edfa4a92..241837ce 100644 --- a/src/components/EditionCard/DownloadLink.tsx +++ b/src/components/EditionCard/DownloadLink.tsx @@ -2,6 +2,7 @@ import { Box, Icon } from "@nypl/design-system-react-components"; import { useRouter } from "next/router"; import React from "react"; import Link from "~/src/components/Link/Link"; +import { LOGIN_LINK_BASE } from "~/src/constants/links"; import { trackCtaClick } from "~/src/lib/adobe/Analytics"; import { fulfillFetcher } from "~/src/lib/api/SearchApi"; import { ItemLink } from "~/src/types/DataModel"; @@ -18,7 +19,7 @@ const DownloadLink: React.FC<{ let linkText = "Download PDF"; let linkUrl = formatUrl(downloadLink.url); - const handleOnClick = async (e) => { + const handleDownload = async (e) => { if (linkUrl.includes("/fulfill/")) { e.preventDefault(); const redirectUrl = await fulfillFetcher(linkUrl, loginCookie); @@ -33,9 +34,7 @@ const DownloadLink: React.FC<{ if (downloadLink.flags.nypl_login && !isLoggedIn) { linkText = "Log in to download PDF"; - linkUrl = `https://login.nypl.org/auth/login?redirect_uri=${encodeURIComponent( - window.location.href - )}`; + linkUrl = LOGIN_LINK_BASE + encodeURIComponent(window.location.href); } return ( @@ -43,7 +42,7 @@ const DownloadLink: React.FC<{ handleOnClick(e)} + onClick={(e) => handleDownload(e)} aria-label={`${title} Download PDF`} > diff --git a/src/components/EditionCard/ReadOnlineLink.tsx b/src/components/EditionCard/ReadOnlineLink.tsx index 3d0f5c2a..95e84f95 100644 --- a/src/components/EditionCard/ReadOnlineLink.tsx +++ b/src/components/EditionCard/ReadOnlineLink.tsx @@ -1,6 +1,7 @@ import { Box } from "@nypl/design-system-react-components"; import React from "react"; import Link from "~/src/components/Link/Link"; +import { LOGIN_LINK_BASE } from "~/src/constants/links"; import { ItemLink } from "~/src/types/DataModel"; // "Read Online" button should only show up if the link was flagged as "reader" or "embed" @@ -16,9 +17,7 @@ const ReadOnlineLink: React.FC<{ if (readOnlineLink.flags.nypl_login && !isLoggedIn) { linkText = "Log in to read online"; - linkUrl = `https://login.nypl.org/auth/login?redirect_uri=${encodeURIComponent( - window.location.href - )}`; + linkUrl = LOGIN_LINK_BASE + encodeURIComponent(window.location.href); } return ( diff --git a/src/constants/links.ts b/src/constants/links.ts index 94c86cc3..7309fa20 100644 --- a/src/constants/links.ts +++ b/src/constants/links.ts @@ -1,2 +1,4 @@ export const SCAN_AND_DELIVER_LINK = "https://www.nypl.org/research/scan-and-deliver"; +export const LOGIN_LINK_BASE = + "https://login.nypl.org/auth/login?redirect_uri="; diff --git a/src/lib/api/SearchApi.ts b/src/lib/api/SearchApi.ts index 09f1ca47..5a8f2e03 100644 --- a/src/lib/api/SearchApi.ts +++ b/src/lib/api/SearchApi.ts @@ -5,6 +5,7 @@ import { EditionQuery, EditionResult } from "~/src/types/EditionQuery"; import { toLocationQuery } from "~/src/util/apiConversion"; import { LinkResult } from "~/src/types/LinkQuery"; import { ApiLanguageResponse } from "~/src/types/LanguagesQuery"; +import { LOGIN_LINK_BASE } from "~/src/constants/links"; const apiEnv = process.env["APP_ENV"]; const apiUrl = process.env["API_URL"] || appConfig.api.url[apiEnv]; @@ -132,6 +133,10 @@ export const fulfillFetcher = async (fulfillUrl, nyplIdentityCookie) => { if (res.ok) { return res.url; } else { + // redirect to the NYPL login page if access token is invalid + if (res.status === 401) { + return LOGIN_LINK_BASE + encodeURIComponent(window.location.href); + } throw new Error(`Unable to download UP PDF`); } }; From ca43db092673a85bb2503c7dc1a247d96838c9a2 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 16 Feb 2024 12:57:01 -0500 Subject: [PATCH 23/31] add error modal --- CHANGELOG.md | 2 + src/components/EditionCard/DownloadLink.tsx | 46 +++++++++++++++++-- .../EditionCard/ScanAndDeliverBlurb.tsx | 2 +- src/components/EditionCard/UpBlurb.tsx | 2 +- src/lib/api/SearchApi.ts | 18 ++++++-- src/types/FulfillQuery.ts | 6 +++ src/util/EditionCardUtils.tsx | 12 +++++ 7 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 src/types/FulfillQuery.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index cc3ab47f..ccb28d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - Add login buttons and info blurb UP items - Fix: Improve accessibility of CTAs and search bar - Update README to include info about testing login locally +- Add error Modal for failed download requests +- Update preview item to prioritize UP item ## [0.17.6] diff --git a/src/components/EditionCard/DownloadLink.tsx b/src/components/EditionCard/DownloadLink.tsx index 241837ce..0aaad4df 100644 --- a/src/components/EditionCard/DownloadLink.tsx +++ b/src/components/EditionCard/DownloadLink.tsx @@ -1,6 +1,11 @@ -import { Box, Icon } from "@nypl/design-system-react-components"; +import { + Box, + Flex, + Icon, + useModal, +} from "@nypl/design-system-react-components"; import { useRouter } from "next/router"; -import React from "react"; +import React, { useState } from "react"; import Link from "~/src/components/Link/Link"; import { LOGIN_LINK_BASE } from "~/src/constants/links"; import { trackCtaClick } from "~/src/lib/adobe/Analytics"; @@ -12,9 +17,16 @@ const DownloadLink: React.FC<{ downloadLink: ItemLink; title: string; isLoggedIn: boolean; - loginCookie?: string; + loginCookie?: any; }> = ({ downloadLink, title, isLoggedIn, loginCookie }) => { const router = useRouter(); + let errorModalMessage; + const { onOpen, Modal } = useModal(); + const [modalProps, setModalProps] = useState({ + bodyContent: null, + closeButtonLabel: "", + headingText: null, + }); if (downloadLink && downloadLink.url) { let linkText = "Download PDF"; let linkUrl = formatUrl(downloadLink.url); @@ -22,8 +34,31 @@ const DownloadLink: React.FC<{ const handleDownload = async (e) => { if (linkUrl.includes("/fulfill/")) { e.preventDefault(); - const redirectUrl = await fulfillFetcher(linkUrl, loginCookie); - router.push(redirectUrl); + const errorMessage = await fulfillFetcher(linkUrl, loginCookie, router); + if (errorMessage !== undefined) { + errorModalMessage = ( + + We were unable to download your item. The system reports ‘ + {errorMessage}’.
Please try again or{" "} + + contact us + {" "} + for assistance. +
+ ); + const errorHeading = ( + + + Download failed + + ); + setModalProps({ + bodyContent: errorModalMessage, + closeButtonLabel: "OK", + headingText: errorHeading, + }); + onOpen(); + } } trackCtaClick({ cta_section: `${title}`, @@ -54,6 +89,7 @@ const DownloadLink: React.FC<{ /> {linkText} +
); } diff --git a/src/components/EditionCard/ScanAndDeliverBlurb.tsx b/src/components/EditionCard/ScanAndDeliverBlurb.tsx index 67059c8d..c2f892bd 100644 --- a/src/components/EditionCard/ScanAndDeliverBlurb.tsx +++ b/src/components/EditionCard/ScanAndDeliverBlurb.tsx @@ -8,7 +8,7 @@ const ScanAndDeliverBlurb: React.FC = () => { diff --git a/src/components/EditionCard/UpBlurb.tsx b/src/components/EditionCard/UpBlurb.tsx index c24095dc..58f2c11c 100644 --- a/src/components/EditionCard/UpBlurb.tsx +++ b/src/components/EditionCard/UpBlurb.tsx @@ -9,7 +9,7 @@ const UpBlurb: React.FC<{ publishers: Agent[] }> = ({ publishers }) => { diff --git a/src/lib/api/SearchApi.ts b/src/lib/api/SearchApi.ts index 5a8f2e03..1f85c9a3 100644 --- a/src/lib/api/SearchApi.ts +++ b/src/lib/api/SearchApi.ts @@ -6,6 +6,8 @@ import { toLocationQuery } from "~/src/util/apiConversion"; import { LinkResult } from "~/src/types/LinkQuery"; import { ApiLanguageResponse } from "~/src/types/LanguagesQuery"; import { LOGIN_LINK_BASE } from "~/src/constants/links"; +import { NextRouter } from "next/router"; +import { FulfillResult } from "~/src/types/FulfillQuery"; const apiEnv = process.env["APP_ENV"]; const apiUrl = process.env["API_URL"] || appConfig.api.url[apiEnv]; @@ -122,7 +124,11 @@ export const readFetcher = async (linkId: number) => { } }; -export const fulfillFetcher = async (fulfillUrl, nyplIdentityCookie) => { +export const fulfillFetcher = async ( + fulfillUrl: string, + nyplIdentityCookie: any, + router: NextRouter +) => { const url = new URL(fulfillUrl); const res = await fetch(url.toString(), { method: "GET", @@ -131,12 +137,16 @@ export const fulfillFetcher = async (fulfillUrl, nyplIdentityCookie) => { }, }); if (res.ok) { - return res.url; + router.push(res.url); } else { // redirect to the NYPL login page if access token is invalid if (res.status === 401) { - return LOGIN_LINK_BASE + encodeURIComponent(window.location.href); + router.push(LOGIN_LINK_BASE + encodeURIComponent(window.location.href)); + } + if (res.status === 404) { + const fulfillResult: FulfillResult = await res.json(); + return fulfillResult.data; } - throw new Error(`Unable to download UP PDF`); } + return undefined; }; diff --git a/src/types/FulfillQuery.ts b/src/types/FulfillQuery.ts new file mode 100644 index 00000000..b1e86053 --- /dev/null +++ b/src/types/FulfillQuery.ts @@ -0,0 +1,6 @@ +export type FulfillResult = { + status?: number; + timestamp?: string; + responseType?: string; + data?: string; +}; diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index ebe95691..81356f2f 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -151,6 +151,13 @@ export default class EditionCardUtils { }); }; + static getUpLink = (item: ApiItem): ItemLink => { + if (!item || !item.links) return undefined; + return item.links.find((link: ItemLink) => { + return !link.flags.edd && link.flags.nypl_login; + }); + }; + // "Read Online" button should only show up if the link was flagged as "reader" or "embed" static getReadOnlineLink = (item: ApiItem) => { const localLink = EditionCardUtils.getReadLink(item, "reader"); @@ -179,6 +186,10 @@ export default class EditionCardUtils { static getPreviewItem(items: ApiItem[] | undefined) { if (!items) return undefined; + const firstUpItem = items.find((item) => { + return EditionCardUtils.getUpLink(item); + }); + const firstReadableItem = items.find((item) => { return ( EditionCardUtils.getReadLink(item, "reader") || @@ -188,6 +199,7 @@ export default class EditionCardUtils { // If no readable link found, we just return any link that's not a catalog (edd) return ( + firstUpItem ?? firstReadableItem ?? items.find((items) => { return items.links && items.links.find((link) => !link.flags.catalog); From c6a15d5c41d4354a934c4826c6281964bcc04675 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Wed, 21 Feb 2024 15:52:52 -0500 Subject: [PATCH 24/31] fix failed to load pdf error --- CHANGELOG.md | 1 + package-lock.json | 34 +++++++++------------------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc3ab47f..87bafeca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Add login buttons and info blurb UP items - Fix: Improve accessibility of CTAs and search bar - Update README to include info about testing login locally +- Hotfix: Update package-lock pdfjs-dist version ## [0.17.6] diff --git a/package-lock.json b/package-lock.json index 1911b582..a747f136 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19140,17 +19140,9 @@ } }, "node_modules/pdfjs-dist": { - "version": "2.12.313", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz", - "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==", - "peerDependencies": { - "worker-loader": "^3.0.8" - }, - "peerDependenciesMeta": { - "worker-loader": { - "optional": true - } - } + "version": "2.6.347", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.6.347.tgz", + "integrity": "sha512-QC+h7hG2su9v/nU1wEI3SnpPIrqJODL7GTDFvR74ANKGq1AFJW16PH8VWnhpiTi9YcLSFV9xLeWSgq+ckHLdVQ==" }, "node_modules/picocolors": { "version": "1.0.0", @@ -19749,9 +19741,8 @@ } }, "node_modules/react-pdf": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-5.7.2.tgz", - "integrity": "sha512-hdDwvf007V0i2rPCqQVS1fa70CXut17SN3laJYlRHzuqcu8sLLjEoeXihty6c0Ev5g1mw31b8OT8EwRw1s8C4g==", + "version": "5.3.2", + "integrity": "sha512-gT2xeUAUJem5UWNZYIQSPJAlPDbc3mIIhEgGK8P/qo1B68WIE4R4v3tNFYM9e5nqlKnGZG4Cd68SetlmnPejwA==", "dependencies": { "@babel/runtime": "^7.0.0", "file-loader": "^6.0.0", @@ -19759,17 +19750,15 @@ "make-event-props": "^1.1.0", "merge-class-names": "^1.1.1", "merge-refs": "^1.0.0", - "pdfjs-dist": "2.12.313", - "prop-types": "^15.6.2", - "tiny-invariant": "^1.0.0", - "tiny-warning": "^1.0.0" + "pdfjs-dist": "2.6.347", + "prop-types": "^15.6.2" }, "funding": { "url": "https://github.com/wojtekmaj/react-pdf?sponsor=1" }, "peerDependencies": { - "react": "^16.3.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0" + "react": "^16.3.0 || ^17.0.0-0", + "react-dom": "^16.3.0 || ^17.0.0-0" } }, "node_modules/react-popper": { @@ -21802,11 +21791,6 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", From 72b72e8e3df40d2d8e4e08272fc418e66eea3fd8 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Mon, 26 Feb 2024 12:19:19 -0500 Subject: [PATCH 25/31] remove featured edition logic --- CHANGELOG.md | 1 + src/util/EditionCardUtils.tsx | 23 ++++------------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a74edf..d155ce66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Add error Modal for failed download requests - Update preview item to prioritize UP item - Hotfix: Update package-lock pdfjs-dist version +- Remove featured edition logic from frontend ## [0.17.6] diff --git a/src/util/EditionCardUtils.tsx b/src/util/EditionCardUtils.tsx index 81356f2f..ba4bf8ab 100644 --- a/src/util/EditionCardUtils.tsx +++ b/src/util/EditionCardUtils.tsx @@ -182,34 +182,19 @@ export default class EditionCardUtils { return oclcLink; } - // Get readable item or non-catalog item + // return first item if links are available static getPreviewItem(items: ApiItem[] | undefined) { if (!items) return undefined; - const firstUpItem = items.find((item) => { - return EditionCardUtils.getUpLink(item); - }); - - const firstReadableItem = items.find((item) => { - return ( - EditionCardUtils.getReadLink(item, "reader") || - EditionCardUtils.getReadLink(item, "embed") - ); - }); + const firstItem = items[0]; - // If no readable link found, we just return any link that's not a catalog (edd) - return ( - firstUpItem ?? - firstReadableItem ?? - items.find((items) => { - return items.links && items.links.find((link) => !link.flags.catalog); - }) - ); + return firstItem.links ? firstItem : undefined; } static isAvailableOnline(item: ApiItem) { return ( item && + item.links && item.links.find((link: ItemLink) => { return ( link.flags["reader"] || link.flags["embed"] || link.flags["download"] From 04a0cc44a8ebd5600c72967f040793953be509c5 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Thu, 29 Feb 2024 15:09:03 -0500 Subject: [PATCH 26/31] add Kristo, Jiayong, and Olivia as codeowners --- .github/CODEOWNERS | 2 +- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 61a0e359..36b769fa 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ # Each line is a file pattern followed by one or more owners. These owners will be the default owners for everything in the repo. Unless a later match takes precedence,e ach owner will be requested for review when someone opens a pull request. -* @samanthaandrews @jackiequach +* @samanthaandrews @jackiequach @kristojorg @Toxiapo @oliviawongnyc diff --git a/CHANGELOG.md b/CHANGELOG.md index d155ce66..9f88a51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Update preview item to prioritize UP item - Hotfix: Update package-lock pdfjs-dist version - Remove featured edition logic from frontend +- Chore: Add Krist, Jiayong, and Olivia as codeowners ## [0.17.6] From d3d874b1aaa7fc2b1efaf3b6f2e236d0b33e00e1 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Thu, 7 Mar 2024 11:50:36 -0500 Subject: [PATCH 27/31] fix error for edition and work pages --- src/components/EditionDetail/Edition.tsx | 7 ++++--- src/util/EditionCardUtils.tsx | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/EditionDetail/Edition.tsx b/src/components/EditionDetail/Edition.tsx index 850890fb..753c5845 100644 --- a/src/components/EditionDetail/Edition.tsx +++ b/src/components/EditionDetail/Edition.tsx @@ -200,9 +200,10 @@ const Edition: React.FC<{ editionResult: EditionResult; backUrl?: string }> = ( )} {edition.instances - .filter( - (instance) => instance.instance_id !== featuredInstance.instance_id - ) + .filter((instance) => { + if (!featuredInstance) return true; + return instance.instance_id !== featuredInstance.instance_id; + }) .map((instance) => ( Date: Tue, 12 Mar 2024 14:47:20 -0400 Subject: [PATCH 28/31] define app env in yml files --- .github/workflows/build-production.yaml | 1 + .github/workflows/build-qa.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build-production.yaml b/.github/workflows/build-production.yaml index 090718a4..70239ed6 100644 --- a/.github/workflows/build-production.yaml +++ b/.github/workflows/build-production.yaml @@ -66,6 +66,7 @@ jobs: - name: Build, tag, and push image to Amazon ECR env: + APP_ENV: production ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: sfr-front-end IMAGE_TAG: ${{ github.sha }} diff --git a/.github/workflows/build-qa.yml b/.github/workflows/build-qa.yml index 3e05b4d6..423def7e 100644 --- a/.github/workflows/build-qa.yml +++ b/.github/workflows/build-qa.yml @@ -34,6 +34,7 @@ jobs: - name: Build, tag, and push image to Amazon ECR env: + APP_ENV: qa ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} ECR_REPOSITORY: sfr-front-end IMAGE_TAG: ${{ github.sha }} From 3bae05127e3d89ae626011afb26582728bcc6d00 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Tue, 12 Mar 2024 14:52:50 -0400 Subject: [PATCH 29/31] update newrelic package --- CHANGELOG.md | 1 + package-lock.json | 1693 ++++++++------------------------------------- package.json | 2 +- 3 files changed, 274 insertions(+), 1422 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f88a51d..50c6d530 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Hotfix: Update package-lock pdfjs-dist version - Remove featured edition logic from frontend - Chore: Add Krist, Jiayong, and Olivia as codeowners +- Add APP_ENV to yml files and update newrelic to v11.12.0 ## [0.17.6] diff --git a/package-lock.json b/package-lock.json index a747f136..8f4261bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "dotenv": "^16.0.3", "extract-loader": "^5.1.0", "focus-trap-react": "^10.0.0", - "newrelic": "^11.5.0", + "newrelic": "^11.12.0", "next": "^13.5.6", "next-transpile-modules": "^7.0.0", "react": "^18.2.0", @@ -86,586 +86,6 @@ "node": ">=6.0.0" } }, - "node_modules/@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/crc32/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", - "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", - "dependencies": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", - "dependencies": { - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "node_modules/@aws-crypto/util/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.468.0.tgz", - "integrity": "sha512-58OuatGnq4F2rxBUs99zxrsjQAaD+zlTYPLy7nP+f39sElMCZiOMfVLM0wd2VErMvRCjILs8SxzxVRiy/SwXaQ==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.468.0", - "@aws-sdk/core": "3.468.0", - "@aws-sdk/credential-provider-node": "3.468.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/eventstream-serde-browser": "^2.0.15", - "@smithy/eventstream-serde-config-resolver": "^2.0.15", - "@smithy/eventstream-serde-node": "^2.0.15", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-stream": "^2.0.23", - "@smithy/util-utf8": "^2.0.2", - "@smithy/util-waiter": "^2.0.15", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.468.0.tgz", - "integrity": "sha512-NabkDaiFsMP8lBR3+JzdtOVarH8kCJst30fQyBIs2PI0uMfajFJ+SK9JTg1J1YZY6aNJBxo2Bxu3dl0fjZ5N/g==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.468.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-sts": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.468.0.tgz", - "integrity": "sha512-EausH7ezv1AIgl/4rfZRNRxrFND5hChbIqkuAf8e5wZ74HUEVBMmD5Jiwfs0WRCso3ejOjsNtS8PAOA3djn28w==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.468.0", - "@aws-sdk/credential-provider-node": "3.468.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-sdk-sts": "3.468.0", - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.468.0.tgz", - "integrity": "sha512-ezUJR9VvknKoXzNZ4wvzGi1jdkmm+/1dUYQ9Sw4r8bzlJDTsUnWbyvaDlBQh81RuhLtVkaUfTnQKoec0cwlZKQ==", - "dependencies": { - "@smithy/smithy-client": "^2.1.18", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.468.0.tgz", - "integrity": "sha512-k/1WHd3KZn0EQYjadooj53FC0z24/e4dUZhbSKTULgmxyO62pwh9v3Brvw4WRa/8o2wTffU/jo54tf4vGuP/ZA==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.468.0.tgz", - "integrity": "sha512-DBYsptYBq0xC+GTh+3dN3Q9/wRZiPpsHA4yCC1mskEbJfMy7EIZZKtZ8lOkZ24NOI5oea4o3L+wFTxOeFSKntA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.468.0", - "@aws-sdk/credential-provider-process": "3.468.0", - "@aws-sdk/credential-provider-sso": "3.468.0", - "@aws-sdk/credential-provider-web-identity": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.468.0.tgz", - "integrity": "sha512-iZlWWZXp6zAH4sP3VrqF7RpAmzl8Qr8tuVkF7ubUZhzyWzKfhLVzqRJqbMYCBPGmfZLAZWjsziPHaBErYkG/5g==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.468.0", - "@aws-sdk/credential-provider-ini": "3.468.0", - "@aws-sdk/credential-provider-process": "3.468.0", - "@aws-sdk/credential-provider-sso": "3.468.0", - "@aws-sdk/credential-provider-web-identity": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.468.0.tgz", - "integrity": "sha512-OYSn1A/UsyPJ7Z8Q2cNhTf55O36shPmSsvOfND04nSfu1nPaR+VUvvsP7v+brhGpwC/GAKTIdGAo4blH31BS6A==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.468.0.tgz", - "integrity": "sha512-eIdGoIw10xyBm7TDcV5Y/W7tzNs2f4H+2G5ZdjG2XGLAELsKCoixe+9ZB662MLtLCxvm7eE1GjOjKsSua6MImQ==", - "dependencies": { - "@aws-sdk/client-sso": "3.468.0", - "@aws-sdk/token-providers": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.468.0.tgz", - "integrity": "sha512-rexymPmXjtkwCPfhnUq3EjO1rSkf39R4Jz9CqiM7OsqK2qlT5Y/V3gnMKn0ZMXsYaQOMfM3cT5xly5R+OKDHlw==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.468.0.tgz", - "integrity": "sha512-gwQ+/QhX+lhof304r6zbZ/V5l5cjhGRxLL3CjH1uJPMcOAbw9wUlMdl+ibr8UwBZ5elfKFGiB1cdW/0uMchw0w==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.468.0.tgz", - "integrity": "sha512-X5XHKV7DHRXI3f29SAhJPe/OxWRFgDWDMMCALfzhmJfCi6Jfh0M14cJKoC+nl+dk9lB+36+jKjhjETZaL2bPlA==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.468.0.tgz", - "integrity": "sha512-vch9IQib2Ng9ucSyRW2eKNQXHUPb5jUPCLA5otTW/8nGjcOU37LxQG4WrxO7uaJ9Oe8hjHO+hViE3P0KISUhtA==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.468.0.tgz", - "integrity": "sha512-xRy8NKfHbmafHwdbotdWgHBvRs0YZgk20GrhFJKp43bkqVbJ5bNlh3nQXf1DeFY9fARR84Bfotya4fwCUHWgZg==", - "dependencies": { - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.468.0.tgz", - "integrity": "sha512-s+7fSB1gdnnTj5O0aCCarX3z5Vppop8kazbNSZADdkfHIDWCN80IH4ZNjY3OWqaAz0HmR4LNNrovdR304ojb4Q==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-middleware": "^2.0.8", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.468.0.tgz", - "integrity": "sha512-lmqaEChVWK6MvNpM/LH504pRsP3p/IuZugWwxCbelKw4bGVU4IgG3mbjfATiIlHo4rW8ttHh1bTsZIGjWOqNeA==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.468.0.tgz", - "integrity": "sha512-EkDfaumuBhDJFg4lmvWiBE8Ln4BF6hYNC2YfkjKCTEuePy5BKryFedwylYZZ3CJG/uVyfr8xBy+mvoR8plpHjg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.7", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.468.0.tgz", - "integrity": "sha512-IpLbthZmFXotwtgkE1Bw4HcKjwpAsGM+6iTXs4amZJqllJClOgyV/sV5Cze+8AqanfCZoPIFTmXyg8LfJTYwbw==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.468.0.tgz", - "integrity": "sha512-rx/9uHI4inRbp2tw3Y4Ih4PNZkVj32h7WneSg3MVgVjAoVD5Zti9KhS5hkvsBxfgmQmg0AQbE+b1sy5WGAgntA==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.468.0.tgz", - "integrity": "sha512-P91EbMG2+1ZToJeTLaRkdO7qM7RI0svuMVLkIdHV9rHR7PeUKUWMpf46xh8rQsIjKC9Arf+I9ueWp3iHJt1T5w==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/util-endpoints": "^1.0.6", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.465.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.465.0.tgz", - "integrity": "sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.468.0.tgz", - "integrity": "sha512-OJyhWWsDEizR3L+dCgMXSUmaCywkiZ7HSbnQytbeKGwokIhD69HTiJcibF/sgcM5gk4k3Mq3puUhGnEZ46GIig==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.468.0.tgz", - "integrity": "sha512-9p+Zyp6xmJUkcryTNmQQwdhRK6gAC6zVEJZLomLGQhD7sWcCzstolw//mAS3AKVQFYWnCEGKrDJdgT0KObCf4g==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dependencies": { - "tslib": "^2.3.1" - } - }, "node_modules/@axe-core/react": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/@axe-core/react/-/react-4.8.2.tgz", @@ -4854,9 +4274,9 @@ } }, "node_modules/@newrelic/aws-sdk": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@newrelic/aws-sdk/-/aws-sdk-7.0.3.tgz", - "integrity": "sha512-oafBFD+DEAqXTg0w15eEu2rfoedWMS7abyW5CuOJxSb+7OWiFUx9jZPpdFblsYPVNWBehxFdws6/JEio3GklyA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@newrelic/aws-sdk/-/aws-sdk-7.2.0.tgz", + "integrity": "sha512-SiFkYBRc0ymzjTm+Ccrx5ox2slW7PbeunOzsFBDfsCxC+umFoqFZIhS10Z23gbrHwQ6wNXmwcDJdhtsxgxZANg==", "engines": { "node": ">=16.0.0" } @@ -4962,14 +4382,26 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/@newrelic/ritm": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@newrelic/ritm/-/ritm-7.2.0.tgz", + "integrity": "sha512-I4iVhm+wlTEDJXQT8EydF/U5vlR9bBHrtBGyvd/D9WCucoMtrPrCNyILQh9bZ+46E8QRE7zh6QEGyQcnc3qNMg==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/@newrelic/security-agent": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@newrelic/security-agent/-/security-agent-0.5.0.tgz", - "integrity": "sha512-ycbNl362arCjKTumkXPnnbnSUARv2SEYBBpbXOfI3p1pa6PRi5kck95W7JNBzxhw/umqwHXgzHhbK8N2uKWYgA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@newrelic/security-agent/-/security-agent-1.0.1.tgz", + "integrity": "sha512-Ao5MTULa6CzI8a2poRdQ31jJA0Exv99eyewfMHYbJGAY3H4rj6TZs08rGtrDK9ZyjNTalM/DHhyyTTDq+FJM+Q==", "dependencies": { - "@aws-sdk/client-lambda": "^3.436.0", - "axios": "1.6.0", - "check-disk-space": "3.4.0", + "axios": "^1.6.5", + "check-disk-space": "^3.4.0", "content-type": "^1.0.5", "fast-safe-stringify": "^2.1.1", "find-package-json": "^1.2.0", @@ -5019,9 +4451,9 @@ } }, "node_modules/@newrelic/security-agent/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -6307,761 +5739,187 @@ }, "node_modules/@nypl/design-system-react-components/node_modules/focus-lock": { "version": "0.9.2", - "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.9.2.tgz", - "integrity": "sha512-YtHxjX7a0IC0ZACL5wsX8QdncXofWpGPNoVMuI/nZUrPGp6LmNI6+D5j0pPj+v8Kw5EpweA+T5yImK0rnWf7oQ==", - "dependencies": { - "tslib": "^2.0.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nypl/design-system-react-components/node_modules/framesync": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/framesync/-/framesync-5.3.0.tgz", - "integrity": "sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@nypl/web-reader": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@nypl/web-reader/-/web-reader-4.3.2.tgz", - "integrity": "sha512-pzsMyzNMPLm/M6uCAFki9H3FLzfhIcYm2i4ImyGemXcYbTiGPOhmwV5CRRT3aG17ZaPCmXg2ogXDYbyM4zO+bA==", - "dependencies": { - "comlink": "^4.3.1", - "debounce": "^1.2.1", - "framer-motion": "^4.1.6", - "node-fetch": "^2.6.1", - "react-icons": "^4.3.1", - "react-intersection-observer": "^8.32.2", - "react-pdf": "^5.3.2", - "react-resize-observer": "^1.1.1" - }, - "peerDependencies": { - "@chakra-ui/react": "^1.8.7 || 2.x", - "@emotion/react": "^11.8.2", - "@emotion/styled": "^11.8.1", - "react": "^16.8.0 || 17.x || 18.x", - "react-dom": "^16.8.0 || 17.x || 18.x", - "swr": "^2.0.3" - } - }, - "node_modules/@nypl/web-reader/node_modules/react-intersection-observer": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.34.0.tgz", - "integrity": "sha512-TYKh52Zc0Uptp5/b4N91XydfSGKubEhgZRtcg1rhTKABXijc4Sdr1uTp5lJ8TN27jwUsdXxjHXtHa0kPj704sw==", - "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0" - } - }, - "node_modules/@playwright/test": { - "version": "1.40.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", - "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", - "dev": true, - "dependencies": { - "playwright": "1.40.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@prisma/prisma-fmt-wasm": { - "version": "4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085", - "resolved": "https://registry.npmjs.org/@prisma/prisma-fmt-wasm/-/prisma-fmt-wasm-4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085.tgz", - "integrity": "sha512-zYz3rFwPB82mVlHGknAPdnSY/a308dhPOblxQLcZgZTDRtDXOE1MgxoRAys+jekwR4/bm3+rZDPs1xsFMsPZig==", - "optional": true - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz", - "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@smithy/abort-controller": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.15.tgz", - "integrity": "sha512-JkS36PIS3/UCbq/MaozzV7jECeL+BTt4R75bwY8i+4RASys4xOyUS1HsRyUNSqUXFP4QyCz5aNnh3ltuaxv+pw==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.21.tgz", - "integrity": "sha512-rlLIGT+BeqjnA6C2FWumPRJS1UW07iU5ZxDHtFuyam4W65gIaOFMjkB90ofKCIh+0mLVQrQFrl/VLtQT/6FWTA==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.4.tgz", - "integrity": "sha512-cwPJN1fa1YOQzhBlTXRavABEYRRchci1X79QRwzaNLySnIMJfztyv1Zkst0iZPLMnpn8+CnHu3wOHS11J5Dr3A==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/property-provider": "^2.0.16", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-codec": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.15.tgz", - "integrity": "sha512-crjvz3j1gGPwA0us6cwS7+5gAn35CTmqu/oIxVbYJo2Qm/sGAye6zGJnMDk3BKhWZw5kcU1G4MxciTkuBpOZPg==", - "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.15.tgz", - "integrity": "sha512-WiFG5N9j3jmS5P0z5Xev6dO0c3lf7EJYC2Ncb0xDnWFvShwXNn741AF71ABr5EcZw8F4rQma0362MMjAwJeZog==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.15", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.15.tgz", - "integrity": "sha512-o65d2LRjgCbWYH+VVNlWXtmsI231SO99ZTOL4UuIPa6WTjbSHWtlXvUcJG9libhEKWmEV9DIUiH2IqyPWi7ubA==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.15.tgz", - "integrity": "sha512-9OOXiIhHq1VeOG6xdHkn2ZayfMYM3vzdUTV3zhcCnt+tMqA3BJK3XXTJFRR2BV28rtRM778DzqbBTf+hqwQPTg==", - "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.15", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.15.tgz", - "integrity": "sha512-dP8AQp/pXlWBjvL0TaPBJC3rM0GoYv7O0Uim8d/7UKZ2Wo13bFI3/BhQfY/1DeiP1m23iCHFNFtOQxfQNBB8rQ==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.15", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.3.1.tgz", - "integrity": "sha512-6MNk16fqb8EwcYY8O8WxB3ArFkLZ2XppsSNo1h7SQcFdDDwIumiJeO6wRzm7iB68xvsOQzsdQKbdtTieS3hfSQ==", - "dependencies": { - "@smithy/protocol-http": "^3.0.11", - "@smithy/querystring-builder": "^2.0.15", - "@smithy/types": "^2.7.0", - "@smithy/util-base64": "^2.0.1", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.17.tgz", - "integrity": "sha512-Il6WuBcI1nD+e2DM7tTADMf01wEPGK8PAhz4D+YmDUVaoBqlA+CaH2uDJhiySifmuKBZj748IfygXty81znKhw==", - "dependencies": { - "@smithy/types": "^2.7.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.15.tgz", - "integrity": "sha512-dlEKBFFwVfzA5QroHlBS94NpgYjXhwN/bFfun+7w3rgxNvVy79SK0w05iGc7UAeC5t+D7gBxrzdnD6hreZnDVQ==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", - "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.17.tgz", - "integrity": "sha512-OyadvMcKC7lFXTNBa8/foEv7jOaqshQZkjWS9coEXPRZnNnihU/Ls+8ZuJwGNCOrN2WxXZFmDWhegbnM4vak8w==", - "dependencies": { - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.3.tgz", - "integrity": "sha512-nYfxuq0S/xoAjdLbyn1ixeVB6cyH9wYCMtbbOCpcCRYR5u2mMtqUtVjjPAZ/DIdlK3qe0tpB0Q76szFGNuz+kQ==", - "dependencies": { - "@smithy/middleware-serde": "^2.0.15", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/shared-ini-file-loader": "^2.2.7", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-middleware": "^2.0.8", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "2.0.24", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.24.tgz", - "integrity": "sha512-q2SvHTYu96N7lYrn3VSuX3vRpxXHR/Cig6MJpGWxd0BWodUQUWlKvXpWQZA+lTaFJU7tUvpKhRd4p4MU3PbeJg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/protocol-http": "^3.0.11", - "@smithy/service-error-classification": "^2.0.8", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/util-middleware": "^2.0.8", - "@smithy/util-retry": "^2.0.8", - "tslib": "^2.5.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-retry/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.15.tgz", - "integrity": "sha512-FOZRFk/zN4AT4wzGuBY+39XWe+ZnCFd0gZtyw3f9Okn2CJPixl9GyWe98TIaljeZdqWkgrzGyPre20AcW2UMHQ==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.9.tgz", - "integrity": "sha512-bCB5dUtGQ5wh7QNL2ELxmDc6g7ih7jWU3Kx6MYH1h4mZbv9xL3WyhKHojRltThCB1arLPyTUFDi+x6fB/oabtA==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.8.tgz", - "integrity": "sha512-+w26OKakaBUGp+UG+dxYZtFb5fs3tgHg3/QrRrmUZj+rl3cIuw840vFUXX35cVPTUCQIiTqmz7CpVF7+hdINdQ==", - "dependencies": { - "@smithy/property-provider": "^2.0.16", - "@smithy/shared-ini-file-loader": "^2.2.7", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.2.1.tgz", - "integrity": "sha512-8iAKQrC8+VFHPAT8pg4/j6hlsTQh+NKOWlctJBrYtQa4ExcxX7aSg3vdQ2XLoYwJotFUurg/NLqFCmZaPRrogw==", - "dependencies": { - "@smithy/abort-controller": "^2.0.15", - "@smithy/protocol-http": "^3.0.11", - "@smithy/querystring-builder": "^2.0.15", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.16.tgz", - "integrity": "sha512-28Ky0LlOqtEjwg5CdHmwwaDRHcTWfPRzkT6HrhwOSRS2RryAvuDfJrZpM+BMcrdeCyEg1mbcgIMoqTla+rdL8Q==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.11.tgz", - "integrity": "sha512-3ziB8fHuXIRamV/akp/sqiWmNPR6X+9SB8Xxnozzj+Nq7hSpyKdFHd1FLpBkgfGFUTzzcBJQlDZPSyxzmdcx5A==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.15.tgz", - "integrity": "sha512-e1q85aT6HutvouOdN+dMsN0jcdshp50PSCvxDvo6aIM57LqeXimjfONUEgfqQ4IFpYWAtVixptyIRE5frMp/2A==", - "dependencies": { - "@smithy/types": "^2.7.0", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.15.tgz", - "integrity": "sha512-jbBvoK3cc81Cj1c1TH1qMYxNQKHrYQ2DoTntN9FBbtUWcGhc+T4FP6kCKYwRLXyU4AajwGIZstvNAmIEgUUNTQ==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.8.tgz", - "integrity": "sha512-jCw9+005im8tsfYvwwSc4TTvd29kXRFkH9peQBg5R/4DD03ieGm6v6Hpv9nIAh98GwgYg1KrztcINC1s4o7/hg==", - "dependencies": { - "@smithy/types": "^2.7.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.7.tgz", - "integrity": "sha512-0Qt5CuiogIuvQIfK+be7oVHcPsayLgfLJGkPlbgdbl0lD28nUKu4p11L+UG3SAEsqc9UsazO+nErPXw7+IgDpQ==", - "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.17.tgz", - "integrity": "sha512-ru5IUbHUAYgJ5ZqZaBi6PEsMjFT/do0Eu21Qt7b07NuRuPlwAMhlqNRDy/KE9QAF20ygehb+xe9ebmyZ26/BSA==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.15", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.18.tgz", - "integrity": "sha512-7FqdbaJiVaHJDD9IfDhmzhSDbpjyx+ZsfdYuOpDJF09rl8qlIAIlZNoSaflKrQ3cEXZN2YxGPaNWGhbYimyIRQ==", - "dependencies": { - "@smithy/middleware-stack": "^2.0.9", - "@smithy/types": "^2.7.0", - "@smithy/util-stream": "^2.0.23", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.7.0.tgz", - "integrity": "sha512-1OIFyhK+vOkMbu4aN2HZz/MomREkrAC/HqY5mlJMUJfGrPRwijJDTeiN8Rnj9zUaB8ogXAfIOtZrrgqZ4w7Wnw==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.15.tgz", - "integrity": "sha512-sADUncUj9rNbOTrdDGm4EXlUs0eQ9dyEo+V74PJoULY4jSQxS+9gwEgsPYyiu8PUOv16JC/MpHonOgqP/IEDZA==", - "dependencies": { - "@smithy/querystring-parser": "^2.0.15", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", - "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", - "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.1.tgz", - "integrity": "sha512-NXYp3ttgUlwkaug4bjBzJ5+yIbUbUx8VsSLuHZROQpoik+gRkIBeEG9MPVYfvPNpuXb/puqodeeUXcKFe7BLOQ==", - "dependencies": { - "tslib": "^2.5.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", - "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", - "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", - "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", - "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.22", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.22.tgz", - "integrity": "sha512-qcF20IHHH96FlktvBRICDXDhLPtpVmtksHmqNGtotb9B0DYWXsC6jWXrkhrrwF7tH26nj+npVTqh9isiFV1gdA==", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.9.2.tgz", + "integrity": "sha512-YtHxjX7a0IC0ZACL5wsX8QdncXofWpGPNoVMuI/nZUrPGp6LmNI6+D5j0pPj+v8Kw5EpweA+T5yImK0rnWf7oQ==", "dependencies": { - "@smithy/property-provider": "^2.0.16", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.0.3" }, "engines": { - "node": ">= 10.0.0" + "node": ">=10" } }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.29", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.29.tgz", - "integrity": "sha512-+uG/15VoUh6JV2fdY9CM++vnSuMQ1VKZ6BdnkUM7R++C/vLjnlg+ToiSR1FqKZbMmKBXmsr8c/TsDWMAYvxbxQ==", + "node_modules/@nypl/design-system-react-components/node_modules/framesync": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-5.3.0.tgz", + "integrity": "sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA==", "dependencies": { - "@smithy/config-resolver": "^2.0.21", - "@smithy/credential-provider-imds": "^2.1.4", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/property-provider": "^2.0.16", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 10.0.0" + "tslib": "^2.1.0" } }, - "node_modules/@smithy/util-endpoints": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.7.tgz", - "integrity": "sha512-Q2gEind3jxoLk6hdKWyESMU7LnXz8aamVwM+VeVjOYzYT1PalGlY/ETa48hv2YpV4+YV604y93YngyzzzQ4IIA==", + "node_modules/@nypl/web-reader": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@nypl/web-reader/-/web-reader-4.3.2.tgz", + "integrity": "sha512-pzsMyzNMPLm/M6uCAFki9H3FLzfhIcYm2i4ImyGemXcYbTiGPOhmwV5CRRT3aG17ZaPCmXg2ogXDYbyM4zO+bA==", "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "comlink": "^4.3.1", + "debounce": "^1.2.1", + "framer-motion": "^4.1.6", + "node-fetch": "^2.6.1", + "react-icons": "^4.3.1", + "react-intersection-observer": "^8.32.2", + "react-pdf": "^5.3.2", + "react-resize-observer": "^1.1.1" }, - "engines": { - "node": ">= 14.0.0" + "peerDependencies": { + "@chakra-ui/react": "^1.8.7 || 2.x", + "@emotion/react": "^11.8.2", + "@emotion/styled": "^11.8.1", + "react": "^16.8.0 || 17.x || 18.x", + "react-dom": "^16.8.0 || 17.x || 18.x", + "swr": "^2.0.3" } }, - "node_modules/@smithy/util-hex-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", - "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "node_modules/@nypl/web-reader/node_modules/react-intersection-observer": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.34.0.tgz", + "integrity": "sha512-TYKh52Zc0Uptp5/b4N91XydfSGKubEhgZRtcg1rhTKABXijc4Sdr1uTp5lJ8TN27jwUsdXxjHXtHa0kPj704sw==", + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0|| ^18.0.0" } }, - "node_modules/@smithy/util-middleware": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.8.tgz", - "integrity": "sha512-qkvqQjM8fRGGA8P2ydWylMhenCDP8VlkPn8kiNuFEaFz9xnUKC2irfqsBSJrfrOB9Qt6pQsI58r3zvvumhFMkw==", + "node_modules/@playwright/test": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", + "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", + "dev": true, "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "playwright": "1.40.1" + }, + "bin": { + "playwright": "cli.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=16" } }, - "node_modules/@smithy/util-retry": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.8.tgz", - "integrity": "sha512-cQTPnVaVFMjjS6cb44WV2yXtHVyXDC5icKyIbejMarJEApYeJWpBU3LINTxHqp/tyLI+MZOUdosr2mZ3sdziNg==", - "dependencies": { - "@smithy/service-error-classification": "^2.0.8", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">= 14.0.0" + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" } }, - "node_modules/@smithy/util-stream": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.23.tgz", - "integrity": "sha512-OJMWq99LAZJUzUwTk+00plyxX3ESktBaGPhqNIEVab+53gLULiWN9B/8bRABLg0K6R6Xg4t80uRdhk3B/LZqMQ==", + "node_modules/@prisma/prisma-fmt-wasm": { + "version": "4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085", + "resolved": "https://registry.npmjs.org/@prisma/prisma-fmt-wasm/-/prisma-fmt-wasm-4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085.tgz", + "integrity": "sha512-zYz3rFwPB82mVlHGknAPdnSY/a308dhPOblxQLcZgZTDRtDXOE1MgxoRAys+jekwR4/bm3+rZDPs1xsFMsPZig==", + "optional": true + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "dependencies": { - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/types": "^2.7.0", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" } }, - "node_modules/@smithy/util-uri-escape": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", - "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dependencies": { - "tslib": "^2.5.0" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@smithy/util-utf8": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", - "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", + "node_modules/@rushstack/eslint-patch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz", + "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==", + "dev": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "type-detect": "4.0.8" } }, - "node_modules/@smithy/util-waiter": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.15.tgz", - "integrity": "sha512-9Y+btzzB7MhLADW7xgD6SjvmoYaRkrb/9SCbNGmNdfO47v38rxb90IGXyDtAK0Shl9bMthTmLgjlfYc+vtz2Qw==", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, "dependencies": { - "@smithy/abort-controller": "^2.0.15", - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { @@ -7770,9 +6628,9 @@ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/qs": { - "version": "6.9.10", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", - "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==" + "version": "6.9.12", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.12.tgz", + "integrity": "sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==" }, "node_modules/@types/react": { "version": "18.2.42", @@ -8883,11 +7741,11 @@ } }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -9970,11 +8828,6 @@ "node": ">=8" } }, - "node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -10083,13 +8936,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10956,16 +9814,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -11273,6 +10134,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-get-iterator": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", @@ -12584,27 +11464,6 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, - "node_modules/fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", - "funding": [ - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - }, - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -12783,9 +11642,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", @@ -12988,15 +11847,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13229,11 +12092,11 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13402,9 +12265,9 @@ } }, "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", "funding": [ { "type": "github", @@ -13592,9 +12455,9 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.5.0.tgz", - "integrity": "sha512-H2hqR0jImhqe9+1k8pYewDKWJHnDeRsWZk5aSztv6MIWD5glmbEOqy1JZrMUC6SJiO1M4A+nVvUUYtWzP5wPYg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.3.tgz", + "integrity": "sha512-R2I11NRi0lI3jD2+qjqyVlVEahsejw7LDnYEbGb47QEFjczE3bZYsmWheCTQA+LFs2DzOQxR7Pms7naHW1V4bQ==", "dependencies": { "acorn": "^8.8.2", "acorn-import-assertions": "^1.9.0", @@ -13603,9 +12466,9 @@ } }, "node_modules/import-in-the-middle/node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { "acorn": "bin/acorn" }, @@ -18430,25 +17293,25 @@ "peer": true }, "node_modules/newrelic": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/newrelic/-/newrelic-11.6.0.tgz", - "integrity": "sha512-peYHffhstQlPQnjTYnXZmz/VX4rvnk8rE9n/kM0KKDbStQbcQE+COkdliDS7jg82ERf90aawu8YGWQRVD/w/GQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/newrelic/-/newrelic-11.12.0.tgz", + "integrity": "sha512-02TY9+3bp4FAmVTnajWUJyz0ESu21avajRXbsE+zYxI1XSd0tEr+DoL7z2P1BGH2KsOquoDCjR+J4rY2Q88A1A==", "dependencies": { "@grpc/grpc-js": "^1.9.4", "@grpc/proto-loader": "^0.7.5", - "@newrelic/aws-sdk": "^7.0.2", + "@newrelic/aws-sdk": "^7.1.0", "@newrelic/koa": "^8.0.1", - "@newrelic/security-agent": "0.5.0", + "@newrelic/ritm": "^7.2.0", + "@newrelic/security-agent": "^1.0.1", "@newrelic/superagent": "^7.0.1", "@tyriar/fibonacci-heap": "^2.0.7", "concat-stream": "^2.0.0", "https-proxy-agent": "^7.0.1", - "import-in-the-middle": "^1.4.2", + "import-in-the-middle": "^1.6.0", "json-bigint": "^1.0.0", "json-stringify-safe": "^5.0.0", "module-details-from-path": "^1.0.3", "readable-stream": "^3.6.1", - "require-in-the-middle": "^7.2.0", "semver": "^7.5.2", "winston-transport": "^4.5.0" }, @@ -19566,11 +18429,11 @@ ] }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", + "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -20124,19 +18987,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-in-the-middle": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", - "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", - "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -20246,9 +19096,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" }, "node_modules/rimraf": { "version": "3.0.2", @@ -20756,14 +19606,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -20820,13 +19672,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -21394,11 +20250,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - }, "node_modules/style-value-types": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-4.1.4.tgz", diff --git a/package.json b/package.json index 4673a7fc..e402e645 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "dotenv": "^16.0.3", "extract-loader": "^5.1.0", "focus-trap-react": "^10.0.0", - "newrelic": "^11.5.0", + "newrelic": "^11.12.0", "next": "^13.5.6", "next-transpile-modules": "^7.0.0", "react": "^18.2.0", From 79d3befb694af9c5020029a839de1d66517d33c3 Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Fri, 15 Mar 2024 15:03:48 -0400 Subject: [PATCH 30/31] combine publisher lists --- CHANGELOG.md | 1 + .../EditionDetailDefinitionList.tsx | 20 +++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50c6d530..698daa08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Remove featured edition logic from frontend - Chore: Add Krist, Jiayong, and Olivia as codeowners - Add APP_ENV to yml files and update newrelic to v11.12.0 +- Fix: Improve accessibility of Edition Details publishers list ## [0.17.6] diff --git a/src/components/EditionDetailDefinitionList/EditionDetailDefinitionList.tsx b/src/components/EditionDetailDefinitionList/EditionDetailDefinitionList.tsx index 29433cd1..c44f5a72 100644 --- a/src/components/EditionDetailDefinitionList/EditionDetailDefinitionList.tsx +++ b/src/components/EditionDetailDefinitionList/EditionDetailDefinitionList.tsx @@ -4,19 +4,19 @@ import { ApiEdition } from "~/src/types/EditionQuery"; import { Agent } from "~/src/types/DataModel"; // Publisher -const getPublishersList = (publishers: Agent[]): JSX.Element[] => { +const getPublishersList = (publishers: Agent[]): JSX.Element => { if (!publishers || publishers.length === 0) { - return [ - Publisher Unavailable, - ]; - } - return publishers.map((publisher: Agent) => { return ( - -
  • {publisher.name}
  • -
    + Publisher Unavailable ); - }); + } + return ( + + {publishers.map((publisher: Agent) => { + return
  • {publisher.name}
  • ; + })} +
    + ); }; export const EditionDetailDefinitionList: React.FC<{ edition: ApiEdition }> = ({ From 3bc1a72dbf2543e0a0e266f1533b7e9615514bbd Mon Sep 17 00:00:00 2001 From: Jackie Quach Date: Tue, 19 Mar 2024 15:41:50 -0400 Subject: [PATCH 31/31] update version number --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 698daa08..ea1b5b00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGE LOG -## [Pre-release] +## [0.18.0] - Add Physical Edition badge and Scan and Deliver blurb to EDD editions - Add Library Card Required and Featured Editon badges diff --git a/package-lock.json b/package-lock.json index 8f4261bf..61773b1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sfr-bookfinder-front-end", - "version": "0.17.6", + "version": "0.18.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sfr-bookfinder-front-end", - "version": "0.17.6", + "version": "0.18.0", "dependencies": { "@chakra-ui/react": "2.5.4", "@newrelic/next": "^0.7.0", diff --git a/package.json b/package.json index e402e645..1a17e8fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sfr-bookfinder-front-end", - "version": "0.17.6", + "version": "0.18.0", "private": true, "scripts": { "dev": "next dev",