Skip to content

Commit

Permalink
Merge pull request #1366 from danskernesdigitalebibliotek/develop
Browse files Browse the repository at this point in the history
Release 2024.32.1
  • Loading branch information
spaceo authored Aug 6, 2024
2 parents e876a29 + a51c07b commit b42f7a8
Show file tree
Hide file tree
Showing 22 changed files with 3,871 additions and 1,125 deletions.
15 changes: 6 additions & 9 deletions dbc-gateway.codegen.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
overwrite: true
schema:
- "https://fbi-api.dbc.dk/${CODEGEN_SCHEMA_PROFILE}/graphql":
headers:
Authorization: "Bearer ${STORYBOOK_LIBRARY_TOKEN}"
headers:
Authorization: "Bearer ${STORYBOOK_LIBRARY_TOKEN}"
documents: "src/**/*.graphql"
generates:
src/core/dbc-gateway/generated/graphql.tsx:
config:
fetcher:
func: '../graphql-fetcher#fetcher'
namingConvention:
typeNames: change-case-all#pascalCase
transformUnderscore: true
func: "../graphql-fetcher#fetcher"
namingConvention: "./scripts/dbc-gateway.codegen.naming"
defaultScalarType: unknown
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-query"
hooks:
afterOneFileWrite:
- yarn post-process-generated-graphql
- yarn eslint --fix
- yarn post-process-generated-graphql
- yarn eslint --fix
src/core/dbc-gateway/generated/graphql.schema.json:
plugins:
- "introspection"

29 changes: 15 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@
"post-process-generated-graphql": "ts-node ./scripts/post-process-generated-graphql.ts"
},
"devDependencies": {
"@babel/core": "^7.24.7",
"@babel/core": "^7.24.8",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/preset-env": "^7.24.7",
"@babel/preset-env": "^7.24.8",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@csstools/postcss-sass": "^5.1.1",
Expand Down Expand Up @@ -81,14 +81,15 @@
"@types/react-flatpickr": "^3.8.11",
"@types/react-redux": "^7.1.24",
"@typescript-eslint/eslint-plugin": "^5.23.0",
"@typescript-eslint/parser": "^7.15.0",
"@vitest/coverage-istanbul": "^1.6.0",
"@typescript-eslint/parser": "^7.16.0",
"@vitest/coverage-istanbul": "^2.0.3",
"autoprefixer": "^10.4.19",
"babel-loader": "^9.1.3",
"babel-plugin-istanbul": "^7.0.0",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"caniuse-lite": "^1.0.30001640",
"caniuse-lite": "^1.0.30001642",
"change-case-all": "^2.1.0",
"chokidar-cli": "^3.0.0",
"concurrently": "^8.2.2",
"core-js": "^3.37.1",
Expand All @@ -106,7 +107,7 @@
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react": "^7.34.4",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-webpack-plugin": "^4.2.0",
"glob": "^8.0.1",
Expand All @@ -122,20 +123,20 @@
"postcss-scss": "^4.0.9",
"prettier": "^2.6.2",
"replace-in-file": "^6.3.2",
"sass": "^1.77.6",
"sass": "^1.77.8",
"source-map-support": "^0.5.21",
"style-loader": "^4.0.0",
"stylelint": "^15.11.0",
"stylelint-config-prettier": "^9.0.5",
"stylelint-config-recommended-scss": "^6.0.0",
"stylelint-prettier": "^2.0.0",
"stylelint-scss": "^6.3.2",
"stylelint-scss": "^6.4.1",
"stylelint-webpack-plugin": "^5.0.1",
"svg-url-loader": "^8.0.0",
"ts-node": "^10.9.2",
"typescript": "^4.6.4",
"vitest": "^0.28.5",
"webpack": "^5.92.1",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4",
"webpack-version-file-plugin": "^0.4.0"
},
Expand All @@ -145,11 +146,11 @@
},
"dependencies": {
"@danskernesdigitalebibliotek/dpl-design-system": "^2024.28.0-100e48a2a38f735862212d267438eeb6dc86e31b",
"@fullcalendar/core": "^6.1.14",
"@fullcalendar/daygrid": "^6.1.14",
"@fullcalendar/interaction": "^6.1.14",
"@fullcalendar/react": "^6.1.14",
"@fullcalendar/timegrid": "^6.1.14",
"@fullcalendar/core": "^6.1.15",
"@fullcalendar/daygrid": "^6.1.15",
"@fullcalendar/interaction": "^6.1.15",
"@fullcalendar/react": "^6.1.15",
"@fullcalendar/timegrid": "^6.1.15",
"@reach/alert": "^0.17.0",
"@reach/dialog": "^0.18.0",
"@reduxjs/toolkit": "^1.9.7",
Expand Down
29 changes: 29 additions & 0 deletions scripts/dbc-gateway.codegen.naming.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* This file is used to convert the typescript symbols generated
* by the graphql-codegen tool into pascal case.
*/

// Todo: Find out to format this file correctly. Possibly as a ts file.
// eslint-disable-next-line import/no-extraneous-dependencies
const { pascalCase } = require("change-case-all");

/**
* This function is used to convert the typescript symbols to pascal case
* Since the graphql schema is not consequent in naming, we need to fix some of the names.
*
* @param {string*} str
* @return {string}
*/
function PascalCaseMostly(str) {
if (str === "moodSuggestResponse") {
str = "MoodSuggestResponseElement";
}
if (str === "ComplexSearchFacets") {
str = "ComplexSearchFacetTypes";
}

// If possible return the pascal case otherwise return the original string.
return pascalCase(str) || str;
}

module.exports = PascalCaseMostly;
22 changes: 18 additions & 4 deletions scripts/post-process-generated-graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,32 @@ if (!pathToGeneratedFile) {
throw new Error("Missing path to generated file!");
}

// Graphql code generator leaves some names with underscore and a number.
// This removes the underscores:
// Remove deprecated enum values because eslint is complaining over duplicate keys:
replaceInFile({
files: pathToGeneratedFile,
from: /_([0-9]+)/g,
to: "$1"
from: /export enum SortOrder \{([\s\S]*?)\/\*\* @deprecated No longer supported \*\/[^}]+}/g,
to: "export enum SortOrder {$1}"
})
.then((results: unknown) => {
console.log("Replacement results:", results);
})
.catch((error: unknown) => {
console.error("Error occurred:", error);
})
.finally(() => {
// Graphql code generator leaves some names with underscore and a number.
// This removes the underscores:
replaceInFile({
files: pathToGeneratedFile,
from: /_([0-9]+)/g,
to: "$1"
})
.then((results: unknown) => {
console.log("Replacement results:", results);
})
.catch((error: unknown) => {
console.error("Error occurred:", error);
});
});

export {};
6 changes: 6 additions & 0 deletions src/apps/material-grid/MaterialGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ const MaterialGrid: React.FC<MaterialGridProps> = ({
setShowAllMaterials(!showAllMaterials);
}

if (!materials.length) {
// eslint-disable-next-line no-console
console.warn(`No materials to show for MaterialGrid: ${title}`);
return null;
}

const titleClasses = clsx("material-grid__title", {
"material-grid__title--no-description": !description
});
Expand Down
61 changes: 44 additions & 17 deletions src/apps/material/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,32 +475,59 @@ export const isParallelReservation = (manifestations: Manifestation[]) =>
hasCorrectAccessType(AccessTypeCode.Physical, manifestations) &&
!isArticle(manifestations);

type BlacklistType = "availability" | "pickup" | "both";

const formatBranches = (branches: string[][]) => {
return branches.flat().length ? { exclude: branches.flat() } : {};
};

const branchesFromConfig = (
blacklist: BlacklistType,
config: UseConfigFunction
) => {
const configMap: Record<Exclude<BlacklistType, "both">, string> = {
availability: "blacklistedAvailabilityBranchesConfig",
pickup: "blacklistedPickupBranchesConfig"
};

type ConfigMapKey = keyof typeof configMap;

if (!configMap[blacklist as ConfigMapKey]) {
return [];
}

return config(configMap[blacklist as ConfigMapKey], {
transformer: "stringToArray"
}).filter((branch) => branch);
};

// Because we need to exclude the branches that are blacklisted, we need to
// use a custom hook to prevent duplicate code
export const getBlacklistedQueryArgs = (
faustIds: FaustId[],
config: UseConfigFunction,
blacklist: "availability" | "pickup" | "both"
blacklistType: BlacklistType
) => {
const configKey = {
availability: "blacklistedAvailabilityBranchesConfig",
pickup: "blacklistedPickupBranchesConfig",
both: "blacklistedAvailabilityBranchesConfig"
// Fixed arguments for the query.
const args = {
recordid: faustIds
};
let blacklistBranches = config(configKey[blacklist], {
transformer: "stringToArray"
});
// If we want to blacklist both availability and pickup branches we now add the
// complimentary blacklist
if (blacklist === "both") {
const additionalBlacklistBranches = config(configKey.pickup, {
transformer: "stringToArray"
});
blacklistBranches = blacklistBranches.concat(additionalBlacklistBranches);
// Return query args with the either availability or pickup branches excluded.
if (blacklistType !== "both") {
return {
...args,
...formatBranches([branchesFromConfig(blacklistType, config)])
};
}

// If we want to blacklist both availability and pickup branches
// return query args with both blacklist types excluded.
return {
recordid: faustIds,
...(blacklistBranches ? { exclude: blacklistBranches } : {})
...args,
...formatBranches([
branchesFromConfig("availability", config),
branchesFromConfig("pickup", config)
])
};
};

Expand Down
5 changes: 5 additions & 0 deletions src/apps/material/material.dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,11 @@ export default {
defaultValue: "Error missing municipality agency ID",
control: { type: "text" }
},
orderDigitalCopyFeedbackInternalErrorText: {
name: "Internal error text",
defaultValue: "Internal error",
control: { type: "text" }
},
authUrl: {
name: "Url where user can authenticate",
defaultValue: "",
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 @@ -139,6 +139,7 @@ interface MaterialEntryTextProps {
orderDigitalCopyModalCloseModalAriaLabelText: string;
orderDigitalCopyModalScreenReaderModalDescriptionText: string;
orderDigitalCopyFeedbackErrorMissingMunicipalityagencyidText: string;
orderDigitalCopyFeedbackInternalErrorText: string;
orderDigitalCopyTitleText: string;
outOfText: string;
periodicalSelectEditionText: string;
Expand Down
68 changes: 35 additions & 33 deletions src/apps/material/material.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
import React, { useEffect, useState } from "react";
import VariousIcon from "@danskernesdigitalebibliotek/dpl-design-system/build/icons/collection/Various.svg";
import CreateIcon from "@danskernesdigitalebibliotek/dpl-design-system/build/icons/collection/Create.svg";
import Receipt from "@danskernesdigitalebibliotek/dpl-design-system/build/icons/collection/Receipt.svg";
import VariousIcon from "@danskernesdigitalebibliotek/dpl-design-system/build/icons/collection/Various.svg";
import React, { useEffect, useState } from "react";
import { useDeepCompareEffect } from "react-use";
import { WorkId } from "../../core/utils/types/ids";
import DisclosureControllable from "../../components/Disclosures/DisclosureControllable";
import DisclosureSummary from "../../components/Disclosures/DisclosureSummary";
import DigitalModal from "../../components/material/digital-modal/DigitalModal";
import InfomediaModal from "../../components/material/infomedia/InfomediaModal";
import { hasCorrectAccess } from "../../components/material/material-buttons/helper";
import MaterialDescription from "../../components/material/MaterialDescription";
import { MaterialReviews } from "../../components/material/MaterialReviews";
import MaterialMainfestationItem from "../../components/material/MaterialMainfestationItem";
import { useText } from "../../core/utils/text";
import MaterialDetailsList from "../../components/material/MaterialDetailsList";
import MaterialHeader from "../../components/material/MaterialHeader";
import MaterialMainfestationItem from "../../components/material/MaterialMainfestationItem";
import { MaterialReviews } from "../../components/material/MaterialReviews";
import MaterialSkeleton from "../../components/material/MaterialSkeleton";
import { PeriodicalEdition } from "../../components/material/periodical/helper";
import { statistics } from "../../core/statistics/statistics";
import { useStatistics } from "../../core/statistics/useStatistics";
import { getWorkPid } from "../../core/utils/helpers/general";
import {
getUrlQueryParam,
setQueryParametersInUrl
} from "../../core/utils/helpers/url";
import { usePatronData } from "../../core/utils/helpers/usePatronData";
import { isAnonymous, isBlocked } from "../../core/utils/helpers/user";
import { useText } from "../../core/utils/text";
import { Manifestation, Work } from "../../core/utils/types/entities";
import { WorkId } from "../../core/utils/types/ids";
import { useGetWork } from "../../core/utils/useGetWork";
import {
getDetailsListData,
getInfomediaIds,
divideManifestationsByMaterialType,
getBestMaterialTypeForWork,
getDetailsListData,
getInfomediaIds,
getManifestationsOrderByTypeAndYear,
isParallelReservation
} from "./helper";
import { Manifestation, Work } from "../../core/utils/types/entities";
import { PeriodicalEdition } from "../../components/material/periodical/helper";
import InfomediaModal from "../../components/material/infomedia/InfomediaModal";
import { useStatistics } from "../../core/statistics/useStatistics";
import { statistics } from "../../core/statistics/statistics";
import DisclosureControllable from "../../components/Disclosures/DisclosureControllable";
import DigitalModal from "../../components/material/digital-modal/DigitalModal";
import { hasCorrectAccess } from "../../components/material/material-buttons/helper";
import MaterialHeader from "../../components/material/MaterialHeader";
import MaterialSkeleton from "../../components/material/MaterialSkeleton";
import DisclosureSummary from "../../components/Disclosures/DisclosureSummary";
import MaterialDisclosure from "./MaterialDisclosure";
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;
Expand Down Expand Up @@ -104,25 +104,27 @@ const Material: React.FC<MaterialProps> = ({ wid }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data]);

// This useEffect selects the current manifestation.
useEffect(() => {
if (!data?.work) return;
const { work } = data as { work: Work };
const type = getUrlQueryParam("type");

const urlType = getUrlQueryParam("type");
const manifestationsByMaterialType = divideManifestationsByMaterialType(
work.manifestations.all
);
// If there is no type in the url, we select one.
if (!type) {

const urlTypeIsPresentInManifestations =
urlType && manifestationsByMaterialType[urlType]?.length > 0;

if (urlTypeIsPresentInManifestations) {
// Use the type from the URL if it's present in the manifestations
setSelectedManifestations(manifestationsByMaterialType[urlType]);
} else {
// Otherwise, fallback to the best material type for the work
const bestMaterialType = getBestMaterialTypeForWork(work);
setSelectedManifestations(manifestationsByMaterialType[bestMaterialType]);
setQueryParametersInUrl({
type: bestMaterialType
});
return;
setQueryParametersInUrl({ type: bestMaterialType });
}
// If there is a type, use it to select a group of manifestations.
setSelectedManifestations(manifestationsByMaterialType[type]);
}, [data]);

if (isLoading || !data?.work || !selectedManifestations) {
Expand Down
Loading

0 comments on commit b42f7a8

Please sign in to comment.