Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hermod sprint 12 #1120

Merged
merged 13 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cypress/fixtures/material/open-order/open-order-accepted.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"data": {
"submitOrder": {
"status": "OWNED_ACCEPTED",
"message": "Item available at pickupAgency, order accepted",
"orderId": "1234"
"status": "NOT_OWNED_ILL_LOC",
"message": "Item not available at pickupAgency, item localised for ILL",
"orderId": "1048265231"
}
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"prop-types": "Since we use former ddb-react components that depend on prop-types we keep this. Should be removed when usage of prop-types is deprecated."
},
"dependencies": {
"@danskernesdigitalebibliotek/dpl-design-system": "^2024.16.1-0e21fc68680a131436acdeea479513ba6936c1b7",
"@danskernesdigitalebibliotek/dpl-design-system": "2024.17.0-273114be2012777935c25d074706ed6187a64e74",
"@fullcalendar/core": "^6.1.11",
"@fullcalendar/daygrid": "^6.1.11",
"@fullcalendar/interaction": "^6.1.11",
Expand Down
12 changes: 8 additions & 4 deletions src/apps/material-grid/MaterialGridSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import React from "react";
import React, { FC } from "react";
import RecommendedMaterialSkeleton from "../recommended-material/RecommendedMaterialSkeleton";

const MaterialGridSkeleton: React.FC = () => {
type MaterialGridSkeletonType = {
title?: string;
};

const MaterialGridSkeleton: FC<MaterialGridSkeletonType> = ({ title }) => {
return (
<div className="material-grid">
<div className="material-grid__title ssc-line" />
{title && <div className="material-grid__title">{title}</div>}
<div className="material-grid__items">
{[...Array(4)].map(() => (
<div className="material-grid__item">
<RecommendedMaterialSkeleton />
<RecommendedMaterialSkeleton partOfGrid />
</div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import serviceUrlArgs from "../../../core/storybook/serviceUrlArgs";
import MaterialGridAutomatic, {
MaterialGridAutomaticEntryProps
} from "./MaterialGridAutomatic.entry";
import MaterialGridSkeleton from "../MaterialGridSkeleton";

export default {
title: "Apps / Material Grid / Automatic",
Expand Down Expand Up @@ -79,3 +80,8 @@ export default {
export const App: ComponentStory<typeof MaterialGridAutomatic> = (
args: MaterialGridAutomaticEntryProps & GlobalEntryTextProps
) => <MaterialGridAutomatic {...args} />;

const SkeletonTemplate: ComponentStory<typeof MaterialGridAutomatic> = () => {
return <MaterialGridSkeleton />;
};
export const Skeleton = SkeletonTemplate.bind({});
2 changes: 1 addition & 1 deletion src/apps/material-grid/automatic/MaterialGridAutomatic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const MaterialGridAutomatic: React.FC<MaterialGridAutomaticProps> = ({
});

if (isLoading || !data) {
return <MaterialGridSkeleton />;
return <MaterialGridSkeleton title={title} />;
}

const resultWorks: Work[] = data.complexSearch.works as Work[];
Expand Down
6 changes: 6 additions & 0 deletions src/apps/material-grid/manual/MaterialGridManual.dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import serviceUrlArgs from "../../../core/storybook/serviceUrlArgs";
import MaterialGridManual, {
MaterialGridManualEntryProps
} from "./MaterialGridManual.entry";
import MaterialGridSkeleton from "../MaterialGridSkeleton";

// 31 materials. Intentionally not using 32 in order to demonstrate the
// logic for only displaying intervals of 4 materials.
Expand Down Expand Up @@ -103,3 +104,8 @@ export default {
export const App: ComponentStory<typeof MaterialGridManual> = (
args: MaterialGridManualEntryProps & GlobalEntryTextProps
) => <MaterialGridManual {...args} />;

const SkeletonTemplate: ComponentStory<typeof MaterialGridManual> = () => {
return <MaterialGridSkeleton />;
};
export const Skeleton = SkeletonTemplate.bind({});
9 changes: 7 additions & 2 deletions src/apps/material/material.dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,14 @@ export default {
defaultValue: "Reserve",
control: { type: "text" }
},
reserveWithMaterialTypeText: {
name: "Reserve",
defaultValue: "Reserve @materialType",
control: { type: "text" }
},
reservableFromAnotherLibraryText: {
name: "Reservable on another library",
defaultValue: "Reservable on another library",
defaultValue: "Ordered from another library.",
control: { type: "text" }
},
findOnBookshelfText: {
Expand Down Expand Up @@ -769,7 +774,7 @@ export default {
},
openOrderNotOwnedIllLocText: {
name: "Open order item localized for ILL text",
defaultValue: "Item not available at pickup agency but localized for ILL",
defaultValue: "Your material has been ordered from another library",
control: { type: "text" }
},
openOrderNotOwnedNoIllLocText: {
Expand Down
1 change: 1 addition & 0 deletions src/apps/material/material.entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ interface MaterialEntryTextProps {
reservationSuccesTitleText: string;
reserveBookText: string;
reserveText: string;
reserveWithMaterialTypeText: string;
reviewsText: string;
saveButtonText: string;
seeOnlineText: string;
Expand Down
4 changes: 2 additions & 2 deletions src/apps/material/open-order.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const navigateToMaterial = () => {
cy.getBySel("material-button-reservable-on-another-library")
.first()
.should("be.visible")
.and("contain", "Reservable on another library")
.and("contain", "Reserve bog")
.click();
cy.getBySel("material-description").scrollIntoView();
cy.getBySel("reservation-modal-submit-button", true)
Expand Down Expand Up @@ -45,7 +45,7 @@ describe("Open Order Functionality", () => {

cy.getBySel("open-oprder-response-status-text")
.should("be.visible")
.and("contain", "Your order is accepted");
.and("contain", "Your material has been ordered from another library");

closeModal();
});
Expand Down
10 changes: 6 additions & 4 deletions src/apps/recommended-material/RecommendedMaterial.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from "react";
import clsx from "clsx";
import { useDispatch } from "react-redux";
import { useQueryClient } from "react-query";
import ButtonFavourite, {
Expand Down Expand Up @@ -45,7 +46,7 @@ const RecommendedMaterial: React.FC<RecommendedMaterialProps> = ({
});

if (isLoading || !data?.work) {
return <RecommendedMaterialSkeleton />;
return <RecommendedMaterialSkeleton partOfGrid={partOfGrid} />;
}

const {
Expand Down Expand Up @@ -79,9 +80,10 @@ const RecommendedMaterial: React.FC<RecommendedMaterialProps> = ({

return (
<div
className={`recommended-material ${
partOfGrid && "recommended-material--in-grid "
}`}
className={clsx(
"recommended-material",
partOfGrid && "recommended-material--in-grid"
)}
>
<div className="recommended-material__icon">
<ButtonFavourite
Expand Down
19 changes: 15 additions & 4 deletions src/apps/recommended-material/RecommendedMaterialSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import React from "react";
import clsx from "clsx";
import React, { FC } from "react";

const RecommendedMaterialSkeleton = () => {
type RecommendedMaterialSkeletonType = {
partOfGrid?: boolean;
};

const RecommendedMaterialSkeleton: FC<RecommendedMaterialSkeletonType> = ({
partOfGrid
}) => {
return (
<div className="recommended-material">
<div className="ssc-square w-30" />
<div
className={clsx("recommended-material", {
"recommended-material--in-grid": partOfGrid
})}
>
<div className="ssc-square w-30 recommended-material__icon" />
<div className="ssc-square image-square" />
<div className="ssc-text-wrapper">
<div className="ssc-line" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,30 @@ import { Manifestation } from "../../../core/utils/types/entities";
import { hasCorrectAccessType } from "../material-buttons/helper";
import MaterialAvailabilityTextOnline from "./online/MaterialAvailabilityTextOnline";
import MaterialAvailabilityTextPhysical from "./physical/MaterialAvailabilityTextPhysical";
import useReservableFromAnotherLibrary from "../../../core/utils/useReservableFromAnotherLibrary";
import MaterialAvailabilityTextParagraph from "./generic/MaterialAvailabilityTextParagraph";
import { useText } from "../../../core/utils/text";

interface Props {
manifestations: Manifestation[];
}

const MaterialAvailabilityText: React.FC<Props> = ({ manifestations }) => {
const t = useText();
const materialType = head(getMaterialTypes(manifestations));
const isbns = getAllIdentifiers(manifestations);
const { materialIsReservableFromAnotherLibrary } =
useReservableFromAnotherLibrary(manifestations);

if (hasCorrectAccessType(AccessTypeCode.Physical, manifestations)) {
const pids = getAllPids(manifestations);
if (materialIsReservableFromAnotherLibrary) {
return (
<MaterialAvailabilityTextParagraph>
{t("reservableFromAnotherLibraryText")}
</MaterialAvailabilityTextParagraph>
);
}
return <MaterialAvailabilityTextPhysical pids={pids} />;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/material/material-buttons/MaterialButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ const MaterialButtons: FC<MaterialButtonsProps> = ({
// articles appear as a part of journal/periodical publications and can't be
// physically loaned for themseleves.

const reservablePidsFromAnotherLibrary =
const { materialIsReservableFromAnotherLibrary } =
useReservableFromAnotherLibrary(manifestations);

if (reservablePidsFromAnotherLibrary.length > 0) {
if (materialIsReservableFromAnotherLibrary) {
return (
<MaterialButtonReservableFromAnotherLibrary
size={size}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ const MaterialButtonPhysical: FC<MaterialButtonPhysicalProps> = ({
label={
size === "small"
? t("reserveText")
: `${t("reserveText")} ${manifestationMaterialType}`
: `${t("reserveWithMaterialTypeText", {
placeholders: { "@materialType": manifestationMaterialType }
})}`
}
buttonType="none"
variant="filled"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ const MaterialButtonReservableFromAnotherLibrary: FC<
dataCy={dataCy}
label={
size === "small"
? t("reservableFromAnotherLibraryText")
: `${t(
"reservableFromAnotherLibraryText"
)} ${manifestationMaterialType}`
? t("reserveText")
: `${t("reserveWithMaterialTypeText", {
placeholders: { "@materialType": manifestationMaterialType }
})}`
}
buttonType="none"
variant="filled"
Expand Down
40 changes: 26 additions & 14 deletions src/components/reservation/ReservationModalBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ import {
getInstantLoanBranchHoldings,
getInstantLoanBranchHoldingsAboveThreshold,
removePrefixFromBranchId,
translateOpenOrderStatus
translateOpenOrderStatus,
getFutureDateStringISO
} from "./helper";
import UseReservableManifestations from "../../core/utils/UseReservableManifestations";
import { PeriodicalEdition } from "../material/periodical/helper";
Expand Down Expand Up @@ -134,9 +135,10 @@ export const ReservationModalBody = ({
!!selectedPeriodical
);

const reservablePidsFromAnotherLibrary = useReservableFromAnotherLibrary(
selectedManifestations
);
const {
reservablePidsFromAnotherLibrary,
materialIsReservableFromAnotherLibrary
} = useReservableFromAnotherLibrary(selectedManifestations);

// If we don't have all data for displaying the view render nothing.
if (!userResponse.data || !holdingsResponse.data) {
Expand Down Expand Up @@ -185,19 +187,20 @@ export const ReservationModalBody = ({
);
}

if (reservablePidsFromAnotherLibrary?.length && patron) {
if (materialIsReservableFromAnotherLibrary && patron) {
const { patronId, name, emailAddress, preferredPickupBranch } = patron;

// Save reservation to open order.
mutateOpenOrder(
{
input: {
pids: [...reservablePidsFromAnotherLibrary],
pids: reservablePidsFromAnotherLibrary,
pickUpBranch: selectedBranch
? removePrefixFromBranchId(selectedBranch)
: removePrefixFromBranchId(preferredPickupBranch),
expires:
selectedInterest?.toString() ||
defaultInterestDaysForOpenOrder.toString(),
expires: getFutureDateStringISO(
Number(selectedInterest ?? defaultInterestDaysForOpenOrder)
),
userParameters: {
userId: patronId.toString(),
userName: name,
Expand Down Expand Up @@ -259,10 +262,14 @@ export const ReservationModalBody = ({
<div>
<div className="reservation-modal-submit">
<MaterialAvailabilityTextParagraph>
<StockAndReservationInfo
stockCount={holdings}
reservationCount={reservations}
/>
{materialIsReservableFromAnotherLibrary ? (
t("reservableFromAnotherLibraryText")
) : (
<StockAndReservationInfo
stockCount={holdings}
reservationCount={reservations}
/>
)}
</MaterialAvailabilityTextParagraph>
<Button
dataCy="reservation-modal-submit-button"
Expand Down Expand Up @@ -303,7 +310,12 @@ export const ReservationModalBody = ({
branches={branches}
selectedBranch={selectedBranch}
selectBranchHandler={setSelectedBranch}
selectedInterest={selectedInterest}
selectedInterest={
materialIsReservableFromAnotherLibrary &&
selectedInterest === null
? Number(defaultInterestDaysForOpenOrder)
: selectedInterest
}
setSelectedInterest={setSelectedInterest}
/>
)}
Expand Down
6 changes: 6 additions & 0 deletions src/components/reservation/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export const getFutureDateString = (num: number) => {
const futureDate = dayjs().add(num, "day").format("YYYY-MM-DD");
return futureDate;
};

export const getFutureDateStringISO = (num: number) => {
const futureDate = dayjs().add(num, "day").format("YYYY-MM-DDTHH:mm:ssZ");
return futureDate;
};

type Periodical = Pick<PeriodicalEdition, "volumeNumber" | "volumeYear">;

const constructReservation = ({
Expand Down
21 changes: 18 additions & 3 deletions src/core/utils/useReservableFromAnotherLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { Pid } from "./types/ids";

const useReservableFromAnotherLibrary = (
manifestations: Manifestation[]
): Pid[] => {
): {
reservablePidsFromAnotherLibrary: Pid[];
materialIsReservableFromAnotherLibrary: boolean;
} => {
const config = useConfig();
const { data: holdingsData } = useGetHoldings({
faustIds: getAllFaustIds(manifestations),
Expand All @@ -17,14 +20,26 @@ const useReservableFromAnotherLibrary = (
// If there is no holdings data or if there are holdings that are reservable, we return an empty array.
// Because we use the array length to determine if we should show the button or not.
if (holdingsData?.some(({ reservable }) => reservable === true)) {
return [];
return {
reservablePidsFromAnotherLibrary: [],
materialIsReservableFromAnotherLibrary: false
};
}

return manifestations
const reservablePidsFromAnotherLibrary = manifestations
.filter(({ catalogueCodes }) =>
catalogueCodes?.otherCatalogues.some((code) => code.startsWith("OVE"))
)
.map(({ pid }) => pid);

const materialIsReservableFromAnotherLibrary = Boolean(
reservablePidsFromAnotherLibrary.length
);

return {
reservablePidsFromAnotherLibrary,
materialIsReservableFromAnotherLibrary
};
};

export default useReservableFromAnotherLibrary;
Loading
Loading