Skip to content

Commit

Permalink
Merge pull request #480 from NYPL/SFR-1894_limited_access_error_handling
Browse files Browse the repository at this point in the history
SFR-1894: Add error modal for /fulfill errors
  • Loading branch information
jackiequach authored Feb 21, 2024
2 parents 3c96566 + ca43db0 commit 75c4a01
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
46 changes: 41 additions & 5 deletions src/components/EditionCard/DownloadLink.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -12,18 +17,48 @@ 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);

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 = (
<span>
We were unable to download your item. The system reports ‘
{errorMessage}’. <br /> Please try again or{" "}
<Link to="https://www.nypl.org/get-help/contact-us">
contact us
</Link>{" "}
for assistance.
</span>
);
const errorHeading = (
<Flex alignItems="center">
<Icon color="ui.error.primary" name="errorFilled" size="large" />
<Box paddingLeft="xs">Download failed</Box>
</Flex>
);
setModalProps({
bodyContent: errorModalMessage,
closeButtonLabel: "OK",
headingText: errorHeading,
});
onOpen();
}
}
trackCtaClick({
cta_section: `${title}`,
Expand Down Expand Up @@ -54,6 +89,7 @@ const DownloadLink: React.FC<{
/>
{linkText}
</Link>
<Modal {...modalProps}></Modal>
</Box>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/EditionCard/ScanAndDeliverBlurb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const ScanAndDeliverBlurb: React.FC = () => {
<Flex
alignItems={{ base: "start", md: "center" }}
marginTop={{ base: "s", md: "m" }}
marginBottom={{ base: "s", md: null }}
marginBottom={{ base: "s", lg: "0" }}
>
<Icon name="errorOutline" size="small" />
<Text size="caption" noSpace marginLeft="xxs">
Expand Down
2 changes: 1 addition & 1 deletion src/components/EditionCard/UpBlurb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const UpBlurb: React.FC<{ publishers: Agent[] }> = ({ publishers }) => {
<Flex
alignItems={{ base: "start", md: "center" }}
marginTop={{ base: "s", md: "m" }}
marginBottom={{ base: "s", md: null }}
marginBottom={{ base: "s", lg: "0" }}
>
<Icon name="errorOutline" size="small" />
<Text size="caption" noSpace marginLeft="xxs">
Expand Down
18 changes: 14 additions & 4 deletions src/lib/api/SearchApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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",
Expand All @@ -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;
};
6 changes: 6 additions & 0 deletions src/types/FulfillQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type FulfillResult = {
status?: number;
timestamp?: string;
responseType?: string;
data?: string;
};
12 changes: 12 additions & 0 deletions src/util/EditionCardUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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") ||
Expand All @@ -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);
Expand Down

0 comments on commit 75c4a01

Please sign in to comment.