From 4d1a2e8a8896c588e5bfe0ade9e5871246df16e0 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Thu, 11 Apr 2024 13:49:41 +0200 Subject: [PATCH 01/24] Choosing bestRepresentation pid as cover pid It is an experiment to see if we can get more covers shown. --- src/apps/material/material.tsx | 4 ++-- .../card-item-list/card-list-item/card-list-item.tsx | 4 ++-- src/components/material/MaterialHeader.tsx | 5 +++-- src/components/simple-material/SimpleMaterial.tsx | 11 ++++------- src/core/utils/helpers/general.ts | 6 +++--- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/apps/material/material.tsx b/src/apps/material/material.tsx index 68abb8ebaa..88ab94e004 100644 --- a/src/apps/material/material.tsx +++ b/src/apps/material/material.tsx @@ -22,7 +22,6 @@ import { isParallelReservation } from "./helper"; import { Manifestation, Work } from "../../core/utils/types/entities"; -import { getManifestationPid } from "../../core/utils/helpers/general"; import { PeriodicalEdition } from "../../components/material/periodical/helper"; import InfomediaModal from "../../components/material/infomedia/InfomediaModal"; import { useStatistics } from "../../core/statistics/useStatistics"; @@ -38,6 +37,7 @@ import { isAnonymous, isBlocked } from "../../core/utils/helpers/user"; import ReservationFindOnShelfModals from "./ReservationFindOnShelfModals"; import { usePatronData } from "../../core/utils/helpers/usePatronData"; import { useGetWork } from "../../core/utils/useGetWork"; +import { getWorkPid } from "../../core/utils/helpers/general"; export interface MaterialProps { wid: WorkId; @@ -137,7 +137,7 @@ const Material: React.FC = ({ wid }) => { } } = data as { work: Work }; - const pid = getManifestationPid(manifestations); + const pid = getWorkPid(work); const detailsListData = getDetailsListData({ manifestation: selectedManifestations[0], work, diff --git a/src/components/card-item-list/card-list-item/card-list-item.tsx b/src/components/card-item-list/card-list-item/card-list-item.tsx index 23cd355996..9e1e194449 100644 --- a/src/components/card-item-list/card-list-item/card-list-item.tsx +++ b/src/components/card-item-list/card-list-item/card-list-item.tsx @@ -13,7 +13,7 @@ import Link from "../../atoms/links/Link"; import { creatorsToString, flattenCreators, - getManifestationPid, + getWorkPid, getReleaseYearSearchResult, materialIsFiction } from "../../../core/utils/helpers/general"; @@ -73,7 +73,7 @@ const CardListItem: React.FC = ({ const dispatch = useDispatch(); const queryClient = useQueryClient(); const author = creatorsToString(flattenCreators(creators), t); - const manifestationPid = getManifestationPid(manifestations); + const manifestationPid = getWorkPid(item); const firstItemInSeries = getNumberedSeries(series).shift(); const materialFullUrl = constructMaterialUrl( materialUrl, diff --git a/src/components/material/MaterialHeader.tsx b/src/components/material/MaterialHeader.tsx index 45d5044fb4..8eb6742352 100644 --- a/src/components/material/MaterialHeader.tsx +++ b/src/components/material/MaterialHeader.tsx @@ -9,7 +9,7 @@ import { creatorsToString, flattenCreators, getMaterialTypes, - getManifestationPid + getWorkPid } from "../../core/utils/helpers/general"; import { useText } from "../../core/utils/text"; import { WorkId } from "../../core/utils/types/ids"; @@ -51,6 +51,7 @@ const MaterialHeader: React.FC = ({ mainLanguages, workId: wid }, + work, selectedManifestations, setSelectedManifestations, selectedPeriodical, @@ -84,7 +85,7 @@ const MaterialHeader: React.FC = ({ .map((language) => language.display) .join(", "); const title = containsDanish ? fullTitle : `${fullTitle} (${allLanguages})`; - const pid = getManifestationPid(manifestations); + const pid = getWorkPid(work); const { track } = useStatistics(); // This is used to track whether the user is changing between material types or just clicking the same button over const manifestationMaterialTypes = getMaterialTypes(selectedManifestations); diff --git a/src/components/simple-material/SimpleMaterial.tsx b/src/components/simple-material/SimpleMaterial.tsx index 8d94a32547..ca4b32aa6c 100644 --- a/src/components/simple-material/SimpleMaterial.tsx +++ b/src/components/simple-material/SimpleMaterial.tsx @@ -7,10 +7,7 @@ import ButtonFavourite, { } from "../button-favourite/button-favourite"; import { Cover } from "../cover/cover"; import { Work } from "../../core/utils/types/entities"; -import { - getContributors, - getManifestationPid -} from "../../core/utils/helpers/general"; +import { getContributors, getWorkPid } from "../../core/utils/helpers/general"; import { TypedDispatch } from "../../core/store"; import { guardedRequest } from "../../core/guardedRequests.slice"; import { constructMaterialUrl } from "../../core/utils/helpers/url"; @@ -29,9 +26,9 @@ const SimpleMaterial: FC = ({ work: { titles: { full: fullTitle }, creators, - workId, - manifestations: { all: manifestations } + workId }, + work, app }) => { const u = useUrls(); @@ -49,7 +46,7 @@ const SimpleMaterial: FC = ({ } // For retrieving cover - const manifestationPid = getManifestationPid(manifestations); + const manifestationPid = getWorkPid(work); const addToListRequest = (id: ButtonFavouriteId) => { dispatch( diff --git a/src/core/utils/helpers/general.ts b/src/core/utils/helpers/general.ts index f56135d25b..b6b085d171 100644 --- a/src/core/utils/helpers/general.ts +++ b/src/core/utils/helpers/general.ts @@ -96,9 +96,9 @@ export const getFirstPublishedYear = (manifestations: Manifestation[]) => { ); }; -export const getManifestationPid = (manifestations: Manifestation[]) => { - const ordered = orderManifestationsByYear(manifestations); - return ordered[0].pid; +// This function is used to find the most representative pid of a work. +export const getWorkPid = (work: Work) => { + return work.manifestations.bestRepresentation.pid || null; }; export const getCoverTint = (index: number) => { From abd187c578f2c382131be2259775befbe32bf263 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Mon, 15 Apr 2024 15:36:36 +0200 Subject: [PATCH 02/24] Add manifestations.all to autosuggest query In order to be able to use them with the new cover fetchings strategy that lets the cover service pick the covers for us, --- .../autosuggest/autosuggest.graphql | 3 + .../dbc-gateway/generated/graphql.schema.json | 102 +++++++++++++++++- src/core/dbc-gateway/generated/graphql.tsx | 28 ++++- 3 files changed, 130 insertions(+), 3 deletions(-) diff --git a/src/components/autosuggest/autosuggest.graphql b/src/components/autosuggest/autosuggest.graphql index 7ef0e915e8..a85e1f6a55 100644 --- a/src/components/autosuggest/autosuggest.graphql +++ b/src/components/autosuggest/autosuggest.graphql @@ -12,6 +12,9 @@ query suggestionsFromQueryString($q: String!) { display } manifestations { + all { + pid + } bestRepresentation { pid ...WithLanguages diff --git a/src/core/dbc-gateway/generated/graphql.schema.json b/src/core/dbc-gateway/generated/graphql.schema.json index defb4cd069..6f6b03dfa3 100644 --- a/src/core/dbc-gateway/generated/graphql.schema.json +++ b/src/core/dbc-gateway/generated/graphql.schema.json @@ -257,6 +257,18 @@ "name": "Audience", "description": null, "fields": [ + { + "name": "PEGI", + "description": "PEGI age rating for games ", + "args": [], + "type": { + "kind": "OBJECT", + "name": "PEGI", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "ages", "description": "Range of numbers with either beginning of range or end of range or both e.g. 6-10, 1980-1999", @@ -365,6 +377,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "mediaCouncilAgeRestriction", + "description": "Media council age recommendation", + "args": [], + "type": { + "kind": "OBJECT", + "name": "MediaCouncilAgeRestriction", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "players", "description": "Number of players in the game.", @@ -5255,6 +5279,41 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "MediaCouncilAgeRestriction", + "description": null, + "fields": [ + { + "name": "display", + "description": "Display string for minimum age", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "minimumAge", + "description": "Minimum age", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Mood", @@ -5760,6 +5819,41 @@ ], "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "PEGI", + "description": null, + "fields": [ + { + "name": "display", + "description": "Display string for PEGI minimum age", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "minimumAge", + "description": "Minimum age to play the game. PEGI rating", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "SCALAR", "name": "PaginationLimit", @@ -9999,6 +10093,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "MOOD_CHILDREN", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "MUSICAL_INSTRUMENTATION", "description": null, @@ -10205,7 +10305,7 @@ }, { "name": "expires", - "description": null, + "description": "expires is required to be iso 8601 dateTime eg. \"2024-03-15T12:24:32Z\"", "type": { "kind": "SCALAR", "name": "String", diff --git a/src/core/dbc-gateway/generated/graphql.tsx b/src/core/dbc-gateway/generated/graphql.tsx index a9ee1b4b5a..d15cb02a0c 100644 --- a/src/core/dbc-gateway/generated/graphql.tsx +++ b/src/core/dbc-gateway/generated/graphql.tsx @@ -76,6 +76,8 @@ export enum AccessUrlType { export type Audience = { __typename?: "Audience"; + /** PEGI age rating for games */ + PEGI?: Maybe; /** Range of numbers with either beginning of range or end of range or both e.g. 6-10, 1980-1999 */ ages: Array; /** Is this material for children or adults */ @@ -88,6 +90,8 @@ export type Audience = { libraryRecommendation?: Maybe; /** Lix number of this manifestion, defines the reability level, Lix stands for læsbarhedsindex */ lix?: Maybe; + /** Media council age recommendation */ + mediaCouncilAgeRestriction?: Maybe; /** Number of players in the game. */ players?: Maybe; /** Primary target audience for this manifestation */ @@ -820,6 +824,14 @@ export type MaterialType = { specific: Scalars["String"]; }; +export type MediaCouncilAgeRestriction = { + __typename?: "MediaCouncilAgeRestriction"; + /** Display string for minimum age */ + display?: Maybe; + /** Minimum age */ + minimumAge?: Maybe; +}; + export type Mood = Subject & { __typename?: "Mood"; display: Scalars["String"]; @@ -897,6 +909,14 @@ export enum OrderType { StackRetrieval = "STACK_RETRIEVAL" } +export type Pegi = { + __typename?: "PEGI"; + /** Display string for PEGI minimum age */ + display?: Maybe; + /** Minimum age to play the game. PEGI rating */ + minimumAge?: Maybe; +}; + export type PeriodicaArticleOrder = { authorOfComponent?: InputMaybe; pagination?: InputMaybe; @@ -1435,6 +1455,7 @@ export enum SubjectType { Location = "LOCATION", MedicalSubjectHeading = "MEDICAL_SUBJECT_HEADING", Mood = "MOOD", + MoodChildren = "MOOD_CHILDREN", MusicalInstrumentation = "MUSICAL_INSTRUMENTATION", MusicCountryOfOrigin = "MUSIC_COUNTRY_OF_ORIGIN", MusicTimePeriod = "MUSIC_TIME_PERIOD", @@ -1465,6 +1486,7 @@ export type SubmitOrderInput = { author?: InputMaybe; authorOfComponent?: InputMaybe; exactEdition?: InputMaybe; + /** expires is required to be iso 8601 dateTime eg. "2024-03-15T12:24:32Z" */ expires?: InputMaybe; key?: InputMaybe; orderType?: InputMaybe; @@ -1738,8 +1760,6 @@ export enum WorkType { Track = "TRACK" } -// TODO: DBC needs to fix the schema. -// The `ComplexSearchFacetsNew`type is named like this, manually, to avoid conflicts with the `ComplexSearchFacets` type. /** The facets to ask for */ export type ComplexSearchFacetsNew = { facetLimit: Scalars["Int"]; @@ -4222,6 +4242,7 @@ export type SuggestionsFromQueryStringQuery = { >; manifestations: { __typename?: "Manifestations"; + all: Array<{ __typename?: "Manifestation"; pid: string }>; bestRepresentation: { __typename?: "Manifestation"; pid: string; @@ -6154,6 +6175,9 @@ export const SuggestionsFromQueryStringDocument = ` display } manifestations { + all { + pid + } bestRepresentation { pid ...WithLanguages From df29cfd62a6af65073c107d6296a723d1dd57693 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Mon, 15 Apr 2024 15:38:57 +0200 Subject: [PATCH 03/24] Do not force multi value params in cover service fetcher to be split into multiple params --- src/core/cover-service-api/mutator/fetcher.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/core/cover-service-api/mutator/fetcher.ts b/src/core/cover-service-api/mutator/fetcher.ts index 4ed1be77e4..107435bb4c 100644 --- a/src/core/cover-service-api/mutator/fetcher.ts +++ b/src/core/cover-service-api/mutator/fetcher.ts @@ -1,5 +1,5 @@ import FetchFailedError from "../../fetchers/FetchFailedError"; -import { getServiceUrlWithParams } from "../../fetchers/helpers"; +import { FetchParams } from "../../fetchers/types"; import { getToken, TOKEN_LIBRARY_KEY } from "../../token"; import { getServiceBaseUrl, @@ -7,6 +7,19 @@ import { } from "../../utils/reduxMiddleware/extractServiceBaseUrls"; import CoverServiceHttpError from "./CoverServiceHttpError"; +export const getServiceUrlWithParams = ({ + baseUrl, + url, + params +}: { + baseUrl: string; + url: string; + params: unknown; +}) => { + const urlParams = new URLSearchParams(params as FetchParams); + return `${baseUrl}${url}?${urlParams}`; +}; + export const fetcher = async ({ url, method, From 2c4cd80ef806b2e2fcddcb03b81de0db9c477968 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Mon, 15 Apr 2024 15:40:22 +0200 Subject: [PATCH 04/24] Change cover fetching strategy We send all the relevant manifestations to the cover service in hope for getting more hits. --- src/apps/fee-list/stackable-fees/fee-info.tsx | 2 +- .../materials/stackable-material/material-info.tsx | 2 +- .../recommended-material/RecommendedMaterial.tsx | 2 +- .../autosuggest-material/autosuggest-material.tsx | 14 +++++++------- .../card-list-item/card-list-item-cover.tsx | 4 ++-- .../card-list-item/card-list-item.tsx | 8 ++++---- src/components/cover/cover.tsx | 6 +++--- src/components/instant-loan/InstantLoanSummary.tsx | 2 +- src/components/material/MaterialHeader.tsx | 4 +++- .../material/MaterialMainfestationItem.tsx | 2 +- .../modal-details-header/modal-details-header.tsx | 4 ++-- .../reservation/ReservationModalBody.tsx | 2 +- src/components/simple-material/SimpleMaterial.tsx | 2 +- 13 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/apps/fee-list/stackable-fees/fee-info.tsx b/src/apps/fee-list/stackable-fees/fee-info.tsx index d22b315d2d..7d8a033e84 100644 --- a/src/apps/fee-list/stackable-fees/fee-info.tsx +++ b/src/apps/fee-list/stackable-fees/fee-info.tsx @@ -29,7 +29,7 @@ const FeeInfo: FC = ({
= ({
= ({ />
= ({ getManifestationLanguageIsoCode([ item.work.manifestations.bestRepresentation ]); + const coverPids = getManifestationsPids( + (item.work?.manifestations.all ?? []) as Manifestation[] + ); return (
  • = ({ {/* eslint-enable react/jsx-props-no-spreading */}
    {item.work && ( - + )}
    ; const CardListItemCover: React.FC = ({ - id, + ids, alt, url, tint, @@ -12,7 +12,7 @@ const CardListItemCover: React.FC = ({ return ( = ({ const dispatch = useDispatch(); const queryClient = useQueryClient(); const author = creatorsToString(flattenCreators(creators), t); - const manifestationPid = getWorkPid(item); + const manifestationPids = getManifestationsPids(manifestations); const firstItemInSeries = getNumberedSeries(series).shift(); const materialFullUrl = constructMaterialUrl( materialUrl, @@ -133,7 +133,7 @@ const CardListItem: React.FC = ({
    {showItem && ( = ({ return (
    - +

    {t("instantLoanTitleText")} diff --git a/src/components/material/MaterialHeader.tsx b/src/components/material/MaterialHeader.tsx index 8eb6742352..7415a0bdce 100644 --- a/src/components/material/MaterialHeader.tsx +++ b/src/components/material/MaterialHeader.tsx @@ -8,6 +8,7 @@ import { convertPostIdToFaustId, creatorsToString, flattenCreators, + getManifestationsPids, getMaterialTypes, getWorkPid } from "../../core/utils/helpers/general"; @@ -86,6 +87,7 @@ const MaterialHeader: React.FC = ({ .join(", "); const title = containsDanish ? fullTitle : `${fullTitle} (${allLanguages})`; const pid = getWorkPid(work); + const coverPids = getManifestationsPids(selectedManifestations); const { track } = useStatistics(); // This is used to track whether the user is changing between material types or just clicking the same button over const manifestationMaterialTypes = getMaterialTypes(selectedManifestations); @@ -115,7 +117,7 @@ const MaterialHeader: React.FC = ({ return (
    - +
    = ({ />
    - +

    = ({ series, children }) => { - const coverId = pid || isbnForCover; + const coverIds = [pid || isbnForCover]; return (
    @@ -35,7 +35,7 @@ const ModalDetailsHeader: FC = ({
    - +
    {getMaterialTypes(selectedManifestations)[0]} diff --git a/src/components/simple-material/SimpleMaterial.tsx b/src/components/simple-material/SimpleMaterial.tsx index ca4b32aa6c..a6bcfefa36 100644 --- a/src/components/simple-material/SimpleMaterial.tsx +++ b/src/components/simple-material/SimpleMaterial.tsx @@ -65,7 +65,7 @@ const SimpleMaterial: FC = ({ className={`simple-material ${bright ? " simple-material--bright" : ""}`} >
    - +
    Date: Tue, 16 Apr 2024 09:37:44 +0200 Subject: [PATCH 05/24] Update the removeModalIdFromUrl function to use the URL API for more accurate parameter handling. --- src/core/modal.slice.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/core/modal.slice.ts b/src/core/modal.slice.ts index a40fbd084a..6dc836c892 100644 --- a/src/core/modal.slice.ts +++ b/src/core/modal.slice.ts @@ -31,12 +31,19 @@ const returnFocusElement = () => { return element; }; +// Removes the 'modal' parameter from the browser's address bar. +// If state.modalIds is not empty, adds the last modal ID as the 'modal' parameter. const removeModalIdFromUrl = (state: StateProps) => { - let newModalParam = "?"; - if (state.modalIds?.toString() !== "") { - newModalParam = `?modal=${state.modalIds.toString()}`; + const currentUrl = new URL(window.location.href); + + if (state.modalIds && state.modalIds.length > 0) { + const lastModalId = state.modalIds[state.modalIds.length - 1]; + currentUrl.searchParams.set("modal", lastModalId); + } else { + currentUrl.searchParams.delete("modal"); } - window.history.pushState("", "", newModalParam); + + window.history.pushState({}, "", currentUrl); }; const modalSlice = createSlice({ @@ -75,6 +82,7 @@ const modalSlice = createSlice({ }, closeModal(state: StateProps, action: PayloadProps) { const modalId = state.modalIds.pop(); + // Check if the modalId from action payload exists in state.modalIds; if so, remove it: if (state.modalIds.indexOf(action.payload.modalId) > -1) { state.modalIds.splice( state.modalIds.indexOf(action.payload.modalId), From 2e64b8abe29f4428052665c58f330b43b177d292 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 16 Apr 2024 09:41:12 +0200 Subject: [PATCH 06/24] Cleaning up some work properties Instead of long chains of properties and double checking of work when it is not necessarry --- .../autosuggest-material/autosuggest-material.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/components/autosuggest-material/autosuggest-material.tsx b/src/components/autosuggest-material/autosuggest-material.tsx index 5ed0f027f4..5f76357bfd 100644 --- a/src/components/autosuggest-material/autosuggest-material.tsx +++ b/src/components/autosuggest-material/autosuggest-material.tsx @@ -42,18 +42,21 @@ const AutosuggestMaterial: React.FC = ({ if (!work) { return null; } - const { creators } = work; + const { + workId, + titles, + creators, + manifestations: { all: allManifestations, bestRepresentation } + } = work; const authors = flattenCreators( creators as WorkSmallFragment["creators"] ); const manifestationLanguageIsoCode = - item.work?.manifestations.bestRepresentation && - getManifestationLanguageIsoCode([ - item.work.manifestations.bestRepresentation - ]); + bestRepresentation && + getManifestationLanguageIsoCode([bestRepresentation]); const coverPids = getManifestationsPids( - (item.work?.manifestations.all ?? []) as Manifestation[] + (allManifestations ?? []) as Manifestation[] ); return ( From 4bb102d49a834b9372ff173020362c86a5b5e95d Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 16 Apr 2024 09:44:16 +0200 Subject: [PATCH 07/24] Adding bestRepresentation logic to cover resolving In order to try to get more cover hits at the cover service we introduce a list of prioritized efforts in order to get a cover from the cover service. --- .../autosuggest-material.tsx | 14 +++-- .../card-list-item/card-list-item-cover.tsx | 2 + .../card-list-item/card-list-item.tsx | 1 + src/components/cover/cover.tsx | 58 ++++++++++++++++++- src/components/material/MaterialHeader.tsx | 10 +++- 5 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/components/autosuggest-material/autosuggest-material.tsx b/src/components/autosuggest-material/autosuggest-material.tsx index 5f76357bfd..a61a3581f0 100644 --- a/src/components/autosuggest-material/autosuggest-material.tsx +++ b/src/components/autosuggest-material/autosuggest-material.tsx @@ -67,21 +67,25 @@ const AutosuggestMaterial: React.FC = ({ "autosuggest__material-item--highlight": highlightedIndex === index })} - key={item.work?.workId} + key={workId} {...getItemProps({ item, index })} data-cy={dataCy} > {/* eslint-enable react/jsx-props-no-spreading */}
    - {item.work && ( - - )} +
    - {item.work?.titles.main[0]} + {titles.main[0]}
    {creatorsToString(authors, t)} diff --git a/src/components/card-item-list/card-list-item/card-list-item-cover.tsx b/src/components/card-item-list/card-list-item/card-list-item-cover.tsx index 375115af97..a1f51da8a6 100644 --- a/src/components/card-item-list/card-list-item/card-list-item-cover.tsx +++ b/src/components/card-item-list/card-list-item/card-list-item-cover.tsx @@ -4,6 +4,7 @@ import { Cover, CoverProps } from "../../cover/cover"; type CardListItemCoverProps = Omit; const CardListItemCover: React.FC = ({ ids, + bestRepresentation, alt, url, tint, @@ -13,6 +14,7 @@ const CardListItemCover: React.FC = ({ = ({ {showItem && ( + cover.imageUrls?.[size]?.url; + +const getCoverUrl = ({ + coverData, + bestRepresentation, + size +}: { + coverData: CoverType[] | null | undefined; + bestRepresentation: CoverProps["bestRepresentation"]; + size: CoverServiceSizes; +}) => { + if (!coverData) { + return null; + } + + const firstCover = first(coverData); + + if (!bestRepresentation && firstCover && getUrl(firstCover, size)) { + return getUrl(firstCover, size); + } + + const bestRepresentationCover = first( + coverData.filter( + (item: CoverType) => + bestRepresentation && item.id === bestRepresentation.pid + ) + ); + + if (bestRepresentationCover && getUrl(bestRepresentationCover, size)) { + return getUrl(bestRepresentationCover, size); + } + + if (firstCover && getUrl(firstCover, size)) { + return getUrl(firstCover, size); + } + + return null; +}; + export const Cover = ({ url, alt, @@ -25,6 +74,7 @@ export const Cover = ({ animate, tint, ids, + bestRepresentation, idType = "pid", shadow, linkAriaLabelledBy @@ -47,7 +97,11 @@ export const Cover = ({ sizes: [dataSize] }); - const coverSrc = data?.[0]?.imageUrls?.[`${dataSize}`]?.url; + const coverSrc = getCoverUrl({ + coverData: data, + bestRepresentation, + size: dataSize + }); type TintClassesType = { [key: string]: string; diff --git a/src/components/material/MaterialHeader.tsx b/src/components/material/MaterialHeader.tsx index 7415a0bdce..e836f93a7f 100644 --- a/src/components/material/MaterialHeader.tsx +++ b/src/components/material/MaterialHeader.tsx @@ -48,7 +48,7 @@ const MaterialHeader: React.FC = ({ work: { titles: { full: fullTitle }, creators, - manifestations: { all: manifestations }, + manifestations: { all: manifestations, bestRepresentation }, mainLanguages, workId: wid }, @@ -117,7 +117,13 @@ const MaterialHeader: React.FC = ({ return (
    - +
    Date: Tue, 16 Apr 2024 09:52:30 +0200 Subject: [PATCH 08/24] Move getUrl functionality to separate helper file To keep the component a bit more tidy --- src/components/cover/cover.tsx | 50 ++-------------------------------- src/components/cover/helper.ts | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 48 deletions(-) create mode 100644 src/components/cover/helper.ts diff --git a/src/components/cover/cover.tsx b/src/components/cover/cover.tsx index d6babb569a..717fdb0e82 100644 --- a/src/components/cover/cover.tsx +++ b/src/components/cover/cover.tsx @@ -1,18 +1,12 @@ import React, { useCallback, useState } from "react"; import clsx from "clsx"; -import { first } from "lodash"; import { useGetCoverCollection } from "../../core/cover-service-api/cover-service"; -import { - Cover as CoverType, - CoverImageUrls, - GetCoverCollectionType -} from "../../core/cover-service-api/model"; +import { GetCoverCollectionType } from "../../core/cover-service-api/model"; import { Pid } from "../../core/utils/types/ids"; import LinkNoStyle from "../atoms/links/LinkNoStyle"; import CoverImage from "./cover-image"; import { Manifestation } from "../../core/utils/types/entities"; - -type CoverServiceSizes = keyof CoverImageUrls; +import { getCoverUrl } from "./helper"; export type CoverProps = { animate: boolean; @@ -27,46 +21,6 @@ export type CoverProps = { linkAriaLabelledBy?: string; }; -const getUrl = (cover: CoverType, size: CoverServiceSizes) => - cover.imageUrls?.[size]?.url; - -const getCoverUrl = ({ - coverData, - bestRepresentation, - size -}: { - coverData: CoverType[] | null | undefined; - bestRepresentation: CoverProps["bestRepresentation"]; - size: CoverServiceSizes; -}) => { - if (!coverData) { - return null; - } - - const firstCover = first(coverData); - - if (!bestRepresentation && firstCover && getUrl(firstCover, size)) { - return getUrl(firstCover, size); - } - - const bestRepresentationCover = first( - coverData.filter( - (item: CoverType) => - bestRepresentation && item.id === bestRepresentation.pid - ) - ); - - if (bestRepresentationCover && getUrl(bestRepresentationCover, size)) { - return getUrl(bestRepresentationCover, size); - } - - if (firstCover && getUrl(firstCover, size)) { - return getUrl(firstCover, size); - } - - return null; -}; - export const Cover = ({ url, alt, diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts new file mode 100644 index 0000000000..566de95fce --- /dev/null +++ b/src/components/cover/helper.ts @@ -0,0 +1,50 @@ +import { first } from "lodash"; +import { + CoverImageUrls, + Cover as CoverType +} from "../../core/cover-service-api/model"; +import { CoverProps } from "./cover"; + +type CoverServiceSizes = keyof CoverImageUrls; + +const getUrl = (cover: CoverType, size: CoverServiceSizes) => + cover.imageUrls?.[size]?.url; + +export const getCoverUrl = ({ + coverData, + bestRepresentation, + size +}: { + coverData: CoverType[] | null | undefined; + bestRepresentation: CoverProps["bestRepresentation"]; + size: CoverServiceSizes; +}) => { + if (!coverData) { + return null; + } + + const firstCover = first(coverData); + + if (!bestRepresentation && firstCover && getUrl(firstCover, size)) { + return getUrl(firstCover, size); + } + + const bestRepresentationCover = first( + coverData.filter( + (item: CoverType) => + bestRepresentation && item.id === bestRepresentation.pid + ) + ); + + if (bestRepresentationCover && getUrl(bestRepresentationCover, size)) { + return getUrl(bestRepresentationCover, size); + } + + if (firstCover && getUrl(firstCover, size)) { + return getUrl(firstCover, size); + } + + return null; +}; + +export default {}; From 871a65f204d6ef01420de4f08e1bd8cb5a432506 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 16 Apr 2024 13:26:43 +0200 Subject: [PATCH 09/24] Fix dependency cycle problem --- src/components/cover/helper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts index 566de95fce..921047961f 100644 --- a/src/components/cover/helper.ts +++ b/src/components/cover/helper.ts @@ -3,7 +3,7 @@ import { CoverImageUrls, Cover as CoverType } from "../../core/cover-service-api/model"; -import { CoverProps } from "./cover"; +import { Manifestation } from "../../core/utils/types/entities"; type CoverServiceSizes = keyof CoverImageUrls; @@ -16,7 +16,7 @@ export const getCoverUrl = ({ size }: { coverData: CoverType[] | null | undefined; - bestRepresentation: CoverProps["bestRepresentation"]; + bestRepresentation?: Manifestation; size: CoverServiceSizes; }) => { if (!coverData) { From 37dc10665b2582969917041cedaadeeea00dc556 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 16 Apr 2024 13:27:44 +0200 Subject: [PATCH 10/24] Add getCoverUrl unit tests To get a bit of hold of the logic and the precedence of it. --- src/components/cover/helper.ts | 112 +++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts index 921047961f..5539a3feda 100644 --- a/src/components/cover/helper.ts +++ b/src/components/cover/helper.ts @@ -48,3 +48,115 @@ export const getCoverUrl = ({ }; export default {}; + +// ************** VITEST *************** +if (import.meta.vitest) { + const { describe, expect, it } = import.meta.vitest; + const coverData = [ + { + id: "1-somestring:2", + imageUrls: { + small: { + url: "url1" + }, + large: { + url: null + } + } + }, + { + id: "3-somestring:4", + imageUrls: { + small: { + url: "url2" + } + } + }, + { + id: "4-somestring:5", + imageUrls: { + small: { + url: null + } + } + } + ]; + + describe("Testing getCoverUrl function with no best representation given", () => { + it("Should show first cover if cover is available in size given", () => { + const url = getCoverUrl({ + coverData, + size: "small" + }); + expect(url).toBe("url1"); + }); + + it("Should return null if the size is available but the url is null", () => { + const url = getCoverUrl({ + coverData, + size: "large" + }); + expect(url).toBe(null); + }); + + it("Should return null if the size does not exist", () => { + const url = getCoverUrl({ + coverData, + size: "medium" + }); + expect(url).toBe(null); + }); + it("Should return null if there are no covvers in data", () => { + const url = getCoverUrl({ + coverData: [], + size: "small" + }); + expect(url).toBe(null); + }); + }); + + describe("Testing getCoverUrl function with a best representation given", () => { + it("Should show the best representation cover if size matches", () => { + type GetCoverUrlParams = Parameters[0]; + const bestRepresentation = { + genreAndForm: ["Book"], + pid: "3-somestring:4" + }; + + const url = getCoverUrl({ + coverData, + size: "small", + bestRepresentation + } as GetCoverUrlParams); + expect(url).toBe("url2"); + }); + it("Should show the first cover if size matches the best representation cover but url is null", () => { + type GetCoverUrlParams = Parameters[0]; + const bestRepresentation = { + genreAndForm: ["Book"], + pid: "4-somestring:5" + }; + + const url = getCoverUrl({ + coverData, + size: "small", + bestRepresentation + } as GetCoverUrlParams); + expect(url).toBe("url1"); + }); + it("Should show the first cover if size matches the best representation cover but url is null", () => { + type GetCoverUrlParams = Parameters[0]; + const bestRepresentation = { + genreAndForm: ["Book"], + pid: "4-somestring:5" + }; + + const url = getCoverUrl({ + coverData, + size: "small", + bestRepresentation + } as GetCoverUrlParams); + expect(url).toBe("url1"); + }); + }); +} From 982e76034edb6f24971aa3b84d6a2bb7f1cfc40d Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Tue, 16 Apr 2024 18:43:20 +0200 Subject: [PATCH 11/24] Use toBeNull test functions To emphasize that we are asserting null outputs --- src/components/cover/helper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts index 5539a3feda..e533c98267 100644 --- a/src/components/cover/helper.ts +++ b/src/components/cover/helper.ts @@ -96,7 +96,7 @@ if (import.meta.vitest) { coverData, size: "large" }); - expect(url).toBe(null); + expect(url).toBeNull(); }); it("Should return null if the size does not exist", () => { @@ -111,7 +111,7 @@ if (import.meta.vitest) { coverData: [], size: "small" }); - expect(url).toBe(null); + expect(url).toBeNull(); }); }); From 1286c896d54264fd99dc0ba6a343b6288a5e19d7 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Wed, 17 Apr 2024 15:24:31 +0200 Subject: [PATCH 12/24] Prioritize book covers in search results Even though we get a bestRepresentation that is something else --- src/apps/material/helper.ts | 6 ++++++ .../card-item-list/card-list-item/card-list-item.tsx | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/apps/material/helper.ts b/src/apps/material/helper.ts index 3625b07470..467d7d8a9e 100644 --- a/src/apps/material/helper.ts +++ b/src/apps/material/helper.ts @@ -346,6 +346,12 @@ export const getManifestationsWithMaterialType = ( }); }; +export const getFirstBookManifestation = (manifestations: Manifestation[]) => { + const dividedManifestations = + divideManifestationsByMaterialType(manifestations); + return first(dividedManifestations[ManifestationMaterialType.book]) ?? null; +}; + export const isABook = (manifestations: Manifestation[]) => { return manifestations.some((manifestation) => { return manifestation.materialTypes.some( diff --git a/src/components/card-item-list/card-list-item/card-list-item.tsx b/src/components/card-item-list/card-list-item/card-list-item.tsx index a1330c22be..ace3d8e5f4 100644 --- a/src/components/card-item-list/card-list-item/card-list-item.tsx +++ b/src/components/card-item-list/card-list-item/card-list-item.tsx @@ -32,6 +32,7 @@ import { useStatistics } from "../../../core/statistics/useStatistics"; import { statistics } from "../../../core/statistics/statistics"; import { useItemHasBeenVisible } from "../../../core/utils/helpers/lazy-load"; import { + getFirstBookManifestation, getManifestationLanguageIsoCode, getNumberedSeries } from "../../../apps/material/helper"; @@ -69,6 +70,7 @@ const CardListItem: React.FC = ({ filters, manifestations ); + const bookManifestation = getFirstBookManifestation(manifestations); const dispatch = useDispatch(); const queryClient = useQueryClient(); @@ -134,7 +136,8 @@ const CardListItem: React.FC = ({ {showItem && ( Date: Wed, 17 Apr 2024 15:25:43 +0200 Subject: [PATCH 13/24] Small refactor just more clear naming --- src/components/cover/helper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts index e533c98267..9da080257c 100644 --- a/src/components/cover/helper.ts +++ b/src/components/cover/helper.ts @@ -31,8 +31,8 @@ export const getCoverUrl = ({ const bestRepresentationCover = first( coverData.filter( - (item: CoverType) => - bestRepresentation && item.id === bestRepresentation.pid + (cover: CoverType) => + bestRepresentation && cover.id === bestRepresentation.pid ) ); From c9d9ba3244350b289e042c620ab86c7e19de87f3 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Thu, 18 Apr 2024 09:51:53 +0200 Subject: [PATCH 14/24] Filter out covers that does NOT have a cover url in the given size. In order to be able to hande fallback covers better. --- src/components/cover/helper.ts | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts index 9da080257c..3cd6a1d6d1 100644 --- a/src/components/cover/helper.ts +++ b/src/components/cover/helper.ts @@ -6,10 +6,27 @@ import { import { Manifestation } from "../../core/utils/types/entities"; type CoverServiceSizes = keyof CoverImageUrls; +type CoverData = CoverType[] | null | undefined; const getUrl = (cover: CoverType, size: CoverServiceSizes) => cover.imageUrls?.[size]?.url; +const coverDataRemoveEmptyCovers = ({ + coverData, + size +}: { + coverData: CoverData; + size: CoverServiceSizes; +}) => { + if (!coverData) { + return []; + } + + return coverData.filter((cover: CoverType) => { + return getUrl(cover, size); + }); +}; + export const getCoverUrl = ({ coverData, bestRepresentation, @@ -23,27 +40,35 @@ export const getCoverUrl = ({ return null; } - const firstCover = first(coverData); + // Make sure we only have covers in our data that has an url in the given size. + const covers = coverDataRemoveEmptyCovers({ coverData, size }); + // Get the first cover which we can use as a fallback cover. + const firstCover = first(covers); + // If no best representation has been given use first cover if available. if (!bestRepresentation && firstCover && getUrl(firstCover, size)) { return getUrl(firstCover, size); } + // See if we can find a cover that has same id as the best representation id. const bestRepresentationCover = first( - coverData.filter( + covers.filter( (cover: CoverType) => bestRepresentation && cover.id === bestRepresentation.pid ) ); + // If we have a best representation cover in the given size use that. if (bestRepresentationCover && getUrl(bestRepresentationCover, size)) { return getUrl(bestRepresentationCover, size); } + // If the best representation method failed we try the first cover. if (firstCover && getUrl(firstCover, size)) { return getUrl(firstCover, size); } + // Everything else failed. We don't know what to do 🤷. return null; }; From 11f41b271d1df5d162c596c5d7107e9e6ba17ef3 Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Thu, 18 Apr 2024 12:28:11 +0200 Subject: [PATCH 15/24] Update design system package to sprint/brahma-15 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index cae9f4094d..af93ca32f0 100644 --- a/package.json +++ b/package.json @@ -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": "0.0.0-02a3c10f532a1887c52d9ad04b3d4e651cb096f3", "@fullcalendar/core": "^6.1.11", "@fullcalendar/daygrid": "^6.1.11", "@fullcalendar/interaction": "^6.1.11", diff --git a/yarn.lock b/yarn.lock index 55b5428ddd..9b2232fb22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1533,10 +1533,10 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@danskernesdigitalebibliotek/dpl-design-system@^2024.16.1-0e21fc68680a131436acdeea479513ba6936c1b7": - version "2024.16.1-0e21fc68680a131436acdeea479513ba6936c1b7" - resolved "https://npm.pkg.github.com/download/@danskernesdigitalebibliotek/dpl-design-system/2024.16.1-0e21fc68680a131436acdeea479513ba6936c1b7/90b336d7b23715b4312d20286a378de384064f63#90b336d7b23715b4312d20286a378de384064f63" - integrity sha512-8vsn4wTEi/+5fCoaGvod1JhjuHUPfJcemO4kU54MYPseTz9JmVloRaBbGF+0Dgb2tXPdwSopiLsTWgyYSs4oPQ== +"@danskernesdigitalebibliotek/dpl-design-system@0.0.0-02a3c10f532a1887c52d9ad04b3d4e651cb096f3": + version "0.0.0-02a3c10f532a1887c52d9ad04b3d4e651cb096f3" + resolved "https://npm.pkg.github.com/download/@danskernesdigitalebibliotek/dpl-design-system/0.0.0-02a3c10f532a1887c52d9ad04b3d4e651cb096f3/4e2ecd34b784892b438318fc817b49aba05eda1c#4e2ecd34b784892b438318fc817b49aba05eda1c" + integrity sha512-D7gjmmwlay1lv3UIPmTvCW7QfoZEVyDrHiL+pxRCxKC4nKBxomTBqkugJSWO0zxpUG8LmLCtISIdw14lUJCeFQ== "@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3": version "0.5.7" From 97e0b20169d4bb09d5330a1c6e4f936dce23e189 Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Thu, 18 Apr 2024 14:50:59 +0200 Subject: [PATCH 16/24] Typo corrected --- src/components/cover/helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/cover/helper.ts b/src/components/cover/helper.ts index 3cd6a1d6d1..3f593804f0 100644 --- a/src/components/cover/helper.ts +++ b/src/components/cover/helper.ts @@ -40,7 +40,7 @@ export const getCoverUrl = ({ return null; } - // Make sure we only have covers in our data that has an url in the given size. + // Make sure we only have covers in our data that has a url in the given size. const covers = coverDataRemoveEmptyCovers({ coverData, size }); // Get the first cover which we can use as a fallback cover. const firstCover = first(covers); From 3ed3875d684b8dd08b31fad580860b2114f528fd Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Fri, 19 Apr 2024 11:48:50 +0200 Subject: [PATCH 17/24] Provide a unique key to each autosuggest category item so it rerenders --- src/components/autosuggest-category/autosuggest-category.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/autosuggest-category/autosuggest-category.tsx b/src/components/autosuggest-category/autosuggest-category.tsx index edd524311e..9f92d4a32c 100644 --- a/src/components/autosuggest-category/autosuggest-category.tsx +++ b/src/components/autosuggest-category/autosuggest-category.tsx @@ -40,7 +40,7 @@ const AutosuggestCategory: FC = ({ "autosuggest__text-item--highlight": highlightedIndex === index } )} - key={item.term + (item.work?.workId || "")} + key={`${item.term}-${index}`} {...getItemProps({ item, index })} data-cy={dataCy} > From 013e9de6d84fc23d4bb1d92a12506c9b3f441eec Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Mon, 22 Apr 2024 10:53:01 +0200 Subject: [PATCH 18/24] No longer show notification dot in the corner of notifications On dashboard & in the user menu. --- .../dashboard/dashboard-notification-list/Notifications.tsx | 2 -- .../dashboard-notification/dashboard-notification.tsx | 3 --- 2 files changed, 5 deletions(-) diff --git a/src/apps/dashboard/dashboard-notification-list/Notifications.tsx b/src/apps/dashboard/dashboard-notification-list/Notifications.tsx index a2c92220f9..25deeb7bbc 100644 --- a/src/apps/dashboard/dashboard-notification-list/Notifications.tsx +++ b/src/apps/dashboard/dashboard-notification-list/Notifications.tsx @@ -49,14 +49,12 @@ const Notifications: FC = ({ header: headerNotification, color, notificationClickEvent, - showNotificationDot, badge, dataCy }) => ( = ({ dataCy, notificationColor, notificationClickEvent, - showNotificationDot, showStatusLabel = false, badge }) => { @@ -53,7 +51,6 @@ const DashboardNotification: FC = ({ {notificationColor === "info" && } )} - {showNotificationDot &&
    }
    From 947ccf84c5b7eb9cde5867532010c31697d17da4 Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Mon, 22 Apr 2024 10:53:33 +0200 Subject: [PATCH 19/24] Adjust cypress tests not to look for notification dots anymore The business doesn't wish to show these anymore at all. --- src/apps/dashboard/dashboard.test.tsx | 37 ++++++++++++--------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/apps/dashboard/dashboard.test.tsx b/src/apps/dashboard/dashboard.test.tsx index 343bb27698..c6716d615b 100644 --- a/src/apps/dashboard/dashboard.test.tsx +++ b/src/apps/dashboard/dashboard.test.tsx @@ -1380,23 +1380,23 @@ describe("Dashboard", () => { // Notification - handed in too later // Red icon - cy.getBySel("physical-loans-overdue") - .should("have.text", "6Returned too lateExpired") - .find(".list-dashboard__dot") - .should("exist"); + cy.getBySel("physical-loans-overdue").should( + "have.text", + "6Returned too lateExpired" + ); // Notification - hand in soon. // Red icon - cy.getBySel("physical-loans-soon-overdue") - .should("have.text", "22To be returned soonExpires soon") - .find(".list-dashboard__dot") - .should("exist"); + cy.getBySel("physical-loans-soon-overdue").should( + "have.text", + "22To be returned soonExpires soon" + ); // Notification - hand in in a long time. - cy.getBySel("loans-not-overdue") - .should("have.text", "14Longer return time") - .find(".list-dashboard__dot") - .should("not.exist"); + cy.getBySel("loans-not-overdue").should( + "have.text", + "14Longer return time" + ); // Header "Reservations" with link to loans page cy.getBySel("dashboard-reservations-header") @@ -1407,17 +1407,14 @@ describe("Dashboard", () => { // Notification - reservations ready // Red icon - cy.getBySel("reservations-ready") - .should("have.text", "2Ready for youReady for pickup") - .find(".list-dashboard__dot") - .should("exist"); + cy.getBySel("reservations-ready").should( + "have.text", + "2Ready for youReady for pickup" + ); // Notification - reservations queued // Red icon - cy.getBySel("reservations-queued") - .should("have.text", "9Still in queue") - .find(".list-dashboard__dot") - .should("not.exist"); + cy.getBySel("reservations-queued").should("have.text", "9Still in queue"); }); it("Can go trough renewal flow of soon overdue loans", () => { From 286ed4dee51c392d62269378515be47fac3dab6b Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Mon, 22 Apr 2024 13:44:10 +0200 Subject: [PATCH 20/24] Add searchHeaderLoginText & searchHeaderFavoritesText to menu app --- src/apps/menu/menu.dev.tsx | 8 ++++++++ src/apps/menu/menu.entry.tsx | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/apps/menu/menu.dev.tsx b/src/apps/menu/menu.dev.tsx index f0607c77d4..91ef84343c 100644 --- a/src/apps/menu/menu.dev.tsx +++ b/src/apps/menu/menu.dev.tsx @@ -165,6 +165,14 @@ export default { expirationWarningDaysBeforeConfig: { defaultValue: "6", control: { type: "text" } + }, + searchHeaderLoginText: { + defaultValue: "Login", + control: { type: "text" } + }, + searchHeaderFavoritesText: { + defaultValue: "Liked", + control: { type: "text" } } } } as ComponentMeta; diff --git a/src/apps/menu/menu.entry.tsx b/src/apps/menu/menu.entry.tsx index dea04fcab2..e4b902e622 100644 --- a/src/apps/menu/menu.entry.tsx +++ b/src/apps/menu/menu.entry.tsx @@ -44,6 +44,8 @@ export interface MenuProps { menuNotAuthenticatedModalDescriptionText: string; physicalLoansUrl: string; reservationsUrl: string; + searchHeaderLoginText: string; + searchHeaderFavoritesText: string; } export interface MenuEntryProps From 9aad0343d397bd7dd30491a2741640eea5aa496d Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Mon, 22 Apr 2024 13:44:35 +0200 Subject: [PATCH 21/24] Add "Login" text under user profile icon when user isn't logged in --- src/apps/menu/menu.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/menu/menu.tsx b/src/apps/menu/menu.tsx index bd3ad9cf29..36f363da22 100644 --- a/src/apps/menu/menu.tsx +++ b/src/apps/menu/menu.tsx @@ -60,6 +60,11 @@ const Menu: FC = ({ pageSize }) => { )} + {!userData?.patron?.name && ( + + {t("searchHeaderLoginText")} + + )} {userData?.patron?.name && ( {userData.patron.name} )} From 2723ce6e669b360c50d640f4a8ff84cfd1e5a616 Mon Sep 17 00:00:00 2001 From: Adam Antal Date: Mon, 22 Apr 2024 13:45:17 +0200 Subject: [PATCH 22/24] Add "Login" under user icon for story-header storybook file --- src/components/search-bar/story-header.dev.inc.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/search-bar/story-header.dev.inc.tsx b/src/components/search-bar/story-header.dev.inc.tsx index fa66173aee..e43f8b6bdf 100644 --- a/src/components/search-bar/story-header.dev.inc.tsx +++ b/src/components/search-bar/story-header.dev.inc.tsx @@ -107,11 +107,13 @@ const StoryHeader: React.FC = ({ search, userProfile }) => { {userProfile || (
    Profile + Login
    )} From a75eba39eeadd48b14dc4022af527fa1eab4c76b Mon Sep 17 00:00:00 2001 From: Mikkel Jakobsen Date: Wed, 1 May 2024 13:12:52 +0200 Subject: [PATCH 23/24] Set design dep to release 15 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2c6ed23676..085c67d35c 100644 --- a/package.json +++ b/package.json @@ -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.18.0-d02b9076284ebf6320a0c838eccdc62087aa2ff5", + "@danskernesdigitalebibliotek/dpl-design-system": "0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d", "@fullcalendar/core": "^6.1.11", "@fullcalendar/daygrid": "^6.1.11", "@fullcalendar/interaction": "^6.1.11", diff --git a/yarn.lock b/yarn.lock index dd3704e4d8..84423a48ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1533,10 +1533,10 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@danskernesdigitalebibliotek/dpl-design-system@2024.18.0-d02b9076284ebf6320a0c838eccdc62087aa2ff5": - version "2024.18.0-d02b9076284ebf6320a0c838eccdc62087aa2ff5" - resolved "https://npm.pkg.github.com/download/@danskernesdigitalebibliotek/dpl-design-system/2024.18.0-d02b9076284ebf6320a0c838eccdc62087aa2ff5/f1d5da5b17e3ac3e7763c72b9a7a88d79ba31442#f1d5da5b17e3ac3e7763c72b9a7a88d79ba31442" - integrity sha512-ve+ANGj9pphqRcFDxYanAA+2mv9y91PsvzhlOlvNXjULgwp9wHIz/lvt/Frz5i6zvE47NbX9LmbkQIy/OmzJ7A== +"@danskernesdigitalebibliotek/dpl-design-system@0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d": + version "0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d" + resolved "https://npm.pkg.github.com/download/@danskernesdigitalebibliotek/dpl-design-system/0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d/418ba80f5f67c58c4ab1d7c3d7e96e9092d5333b#418ba80f5f67c58c4ab1d7c3d7e96e9092d5333b" + integrity sha512-wnaXv6vbySYq+ZkQW56Zad9c2Gxh1JGHaC8u1/qIw2uppEZRMoRaCgxVWf55O7o1utT2Syq0pdo0Po5UG4P0Hw== "@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3": version "0.5.7" From 8acde821da66e8eb433aba687790a2900204d48b Mon Sep 17 00:00:00 2001 From: Andreas Nielsen Date: Thu, 2 May 2024 15:20:50 +0200 Subject: [PATCH 24/24] Use release 2024.18.1 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 085c67d35c..a7535fc110 100644 --- a/package.json +++ b/package.json @@ -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": "0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d", + "@danskernesdigitalebibliotek/dpl-design-system": "^2024.18.1-7e3b588f0ecdffd93b6e570b09b83369a18f8677", "@fullcalendar/core": "^6.1.11", "@fullcalendar/daygrid": "^6.1.11", "@fullcalendar/interaction": "^6.1.11", diff --git a/yarn.lock b/yarn.lock index 84423a48ef..ca2ebae79f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1533,10 +1533,10 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@danskernesdigitalebibliotek/dpl-design-system@0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d": - version "0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d" - resolved "https://npm.pkg.github.com/download/@danskernesdigitalebibliotek/dpl-design-system/0.0.0-1f45241bfc10036fa87660eadfb8bf7697467e5d/418ba80f5f67c58c4ab1d7c3d7e96e9092d5333b#418ba80f5f67c58c4ab1d7c3d7e96e9092d5333b" - integrity sha512-wnaXv6vbySYq+ZkQW56Zad9c2Gxh1JGHaC8u1/qIw2uppEZRMoRaCgxVWf55O7o1utT2Syq0pdo0Po5UG4P0Hw== +"@danskernesdigitalebibliotek/dpl-design-system@^2024.18.1-7e3b588f0ecdffd93b6e570b09b83369a18f8677": + version "2024.18.1-7e3b588f0ecdffd93b6e570b09b83369a18f8677" + resolved "https://npm.pkg.github.com/download/@danskernesdigitalebibliotek/dpl-design-system/2024.18.1-7e3b588f0ecdffd93b6e570b09b83369a18f8677/d06f3a0b18fc2aafdf4c1f7230c14da4fdb58f45#d06f3a0b18fc2aafdf4c1f7230c14da4fdb58f45" + integrity sha512-6rtiZ65yBPAHthg8WmEe/3cV6++E1VYiVSWGn/nc+A02NTUSFOdSi5FFAQcYRHyorf5KF5jqJVSYt+sdmFuLIA== "@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3": version "0.5.7"