Skip to content

Commit

Permalink
Merge pull request #50 from danskernesdigitalebibliotek/DDFBRA-200-an…
Browse files Browse the repository at this point in the history
…onym-og-indlogget-bruger-kan-prove-e-bog

Ddfbra 200 anonym og indlogget bruger kan prove e bog
  • Loading branch information
ThomasGross authored Nov 20, 2024
2 parents 9c187af + 94f0a0b commit 399492f
Show file tree
Hide file tree
Showing 18 changed files with 775 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
run: yarn install --frozen-lockfile

- name: Run unit tests
run: yarn test:unit
run: yarn test:unit:once
3 changes: 2 additions & 1 deletion __tests__/config.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { expect, test, vi } from "vitest"
import { expect, test } from "vitest"

import goConfig from "@/lib/config/config"
import MissingConfigurationError from "@/lib/config/errors/MissingConfigurationError"

test("That an error is thrown if we ask for unknown config", async () => {
// @ts-ignore
expect(() => goConfig("unknown.thingy")).toThrowError(MissingConfigurationError)
})

Expand Down
5 changes: 5 additions & 0 deletions __tests__/refresh-token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IronSession, getIronSession } from "iron-session"
import { testApiHandler } from "next-test-api-route-handler"
import { afterAll, beforeAll, beforeEach, expect, test, vi } from "vitest"

// @ts-ignore
import * as tokenRefreshHandler from "@/app/auth/token/refresh/route"
import { TSessionData, accessTokenShouldBeRefreshed } from "@/lib/session/session"

Expand All @@ -24,6 +25,7 @@ afterAll(() => {
})

beforeEach(() => {
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: true,
})
Expand All @@ -41,6 +43,7 @@ const sessionThatShouldBeRefreshed = () => ({

test("That the refresh endpoint redirects to the frontpage if there is no active session", async () => {
// Simulate an anonymous session.
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: false,
})
Expand All @@ -57,6 +60,7 @@ test("That the refresh endpoint redirects to the frontpage if there is no active

test("That the refresh endpoint redirects to the given endpoint after refreshing token", async () => {
// This is an authorized session that should be refreshed.
// @ts-ignore
getIronSession.mockResolvedValue(sessionThatShouldBeRefreshed())

await testApiHandler({
Expand All @@ -69,6 +73,7 @@ test("That the refresh endpoint redirects to the given endpoint after refreshing
})

// This is an authorized session that should NOT be refreshed.
// @ts-ignore
getIronSession.mockResolvedValue({
isLoggedIn: true,
expires: add(new Date(), { seconds: 300 }),
Expand Down
3 changes: 3 additions & 0 deletions __tests__/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const facets = {
} as const

beforeEach(() => {
// @ts-ignore
;(goConfig as jest.Mock).mockImplementation((key: string) => {
if (key === "search.item.limit") {
return 9 // Mocked return value for "search.item.limit"
Expand All @@ -49,6 +50,7 @@ beforeEach(() => {

describe("Facet functionality", () => {
it("getMachineNames should return all the facet machine names", () => {
// @ts-ignore
goConfig.mockReturnValue(facets)
const machineNames = getFacetMachineNames()
expect(machineNames).toStrictEqual([
Expand Down Expand Up @@ -109,6 +111,7 @@ describe("Facet functionality", () => {
})

it("getFacetTranslation should give a translated facet when given a facet machine name", () => {
// @ts-ignore
const translation = getFacetTranslation("LIX")
expect(translation).toBe("Lix")
})
Expand Down
6 changes: 3 additions & 3 deletions __tests__/url.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { expect, test, vi } from "vitest"
import { expect, test } from "vitest"

import { resolveUrl } from "../lib/helpers/helper.routes"

test("That resolveUrl can return a work url", async () => {
const workUrl = resolveUrl({ type: "work", routeParams: { id: 123 } })
const workUrl = resolveUrl({ type: "work", routeParams: { wid: 123 } })
expect(workUrl).toBe("/work/123")
})

test("That resolveUrl can return a work url with a manifestation type", async () => {
const workUrl = resolveUrl({
type: "work",
routeParams: { id: 123 },
routeParams: { wid: 123 },
queryParams: { audio: "true" },
})
expect(workUrl).toBe("/work/123?audio=true")
Expand Down
29 changes: 29 additions & 0 deletions app/work/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HydrationBoundary, dehydrate } from "@tanstack/react-query"
import React from "react"

import WorkPageLayout from "@/components/pages/workPageLayout/WorkPageLayout"
import getQueryClient from "@/lib/getQueryClient"
import { useGetMaterialQuery } from "@/lib/graphql/generated/fbi/graphql"

function Page({ params: { id } }: { params: { id: string } }) {
const queryClient = getQueryClient()

const decodedWid = decodeURIComponent(id)

queryClient.prefetchQuery({
queryKey: useGetMaterialQuery.getKey({ wid: decodedWid }),
queryFn: useGetMaterialQuery.fetcher({ wid: decodedWid }),
})

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<div>
<WorkPageLayout wid={decodedWid} />
<pre>{JSON.stringify(id, null, 2)}</pre>
Page
</div>
</HydrationBoundary>
)
}

export default Page
21 changes: 21 additions & 0 deletions components/pages/workPageLayout/WorkPageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use client"

import { useQuery } from "@tanstack/react-query"
import React from "react"

import { useGetMaterialQuery } from "@/lib/graphql/generated/fbi/graphql"

function WorkPageLayout({ wid }: { wid: string }) {
const data = useQuery({
queryKey: useGetMaterialQuery.getKey({ wid }),
queryFn: useGetMaterialQuery.fetcher({ wid }),
})

return (
<div>
<pre>{JSON.stringify({ data }, null, 2)}</pre>
</div>
)
}

export default WorkPageLayout
87 changes: 87 additions & 0 deletions components/shared/publizonReader/PublizonReader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { CSSProperties, useEffect } from "react"

import { appendAsset, readerAssets } from "./helper"

// type ReaderType = { identifier?: string; orderId?: string };

// Define mutually exclusive types for identifier and orderId
type ReaderType =
| {
identifier: string
orderId?: never
}
| {
identifier?: never
orderId: string
}

const Reader = ({ identifier, orderId }: ReaderType) => {
useEffect(() => {
readerAssets.forEach(appendAsset)
}, [identifier, orderId])

const readerStyles: CSSProperties = {
position: "absolute",
top: "0", // Padding from the top
left: "0", // Padding from the left
right: "0", // Padding from the right
bottom: "0", // Padding from the bottom
padding: "20px", // Padding for the reader
width: "100%",
maxWidth: "unset",
zIndex: 1000,
// border: "1px dotted black", // Should be removed in production
margin: "0",
}

const handleBack = () => {
window.history.back()
}

const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "Escape") {
handleBack()
}
}

if (orderId) {
return (
<div>
<p>orderId: {orderId}</p>
<div
style={readerStyles}
id="pubhub-reader"
// eslint-disable-next-line react/no-unknown-property
order-id={orderId}
role="button"
tabIndex={0}
onClick={handleBack}
onKeyDown={handleKeyDown}
aria-label="Go back"
/>
</div>
)
}

if (identifier) {
return (
<div
style={readerStyles}
id="pubhub-reader"
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line react/no-unknown-property
identifier={identifier}
role="button"
tabIndex={0}
onClick={handleBack}
onKeyDown={handleKeyDown}
aria-label="Go back"
/>
)
}

return null
}

export default Reader
41 changes: 41 additions & 0 deletions components/shared/publizonReader/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
type AssetType = {
src: string
type: "script" | "link"
}

export const readerAssets: AssetType[] = [
{
src: "https://reader.pubhub.dk/2.2.0/js/chunk-vendors.js",
type: "script",
},
{
src: "https://reader.pubhub.dk/2.2.0/js/app.js",
type: "script",
},
{
src: "https://reader.pubhub.dk/2.2.0/css/chunk-vendors.css",
type: "link",
},
{
src: "https://reader.pubhub.dk/2.2.0/css/app.css",
type: "link",
},
]

export const appendAsset = ({ src, type }: AssetType) => {
if (type === "script") {
const scriptElement = document.createElement("script")
scriptElement.src = src
scriptElement.defer = true
scriptElement.async = false
scriptElement.type = "module"
document.head.appendChild(scriptElement)
}

if (type === "link") {
const linkElement = document.createElement("link")
linkElement.href = src
linkElement.rel = "stylesheet"
document.head.appendChild(linkElement)
}
}
2 changes: 1 addition & 1 deletion components/shared/workCard/WorkCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const WorkCard = ({ work }: WorkCardProps) => {
return (
<Link
className="block space-y-3 lg:space-y-5"
href={resolveUrl({ type: "work", routeParams: { id: work.workId } })}>
href={resolveUrl({ type: "work", routeParams: { wid: work.workId } })}>
<div>
<div
key={work.workId}
Expand Down
16 changes: 8 additions & 8 deletions lib/config/resolvers/search.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { FacetFieldEnum } from "@/lib/graphql/generated/fbi/graphql"

export type TConfigSearchFacets = Record<FacetFieldEnum, { filter: string; translation: string }>

const search = {
"search.item.limit": 12,
"search.offset.initial": 0,
Expand Down Expand Up @@ -37,20 +39,18 @@ const search = {
"775130",
],
"search.facets": {
[FacetFieldEnum.Materialtypesgeneral]: {
MATERIALTYPESGENERAL: {
filter: "materialTypesGeneral",
translation: "Type",
},
[FacetFieldEnum.Mainlanguages]: {
MAINLANGUAGES: {
filter: "mainLanguages",
translation: "Sprog",
},
[FacetFieldEnum.Age]: { filter: "age", translation: "Alder" },
[FacetFieldEnum.Lix]: { filter: "lixRange", translation: "Lix" },
[FacetFieldEnum.Subjects]: { filter: "subjects", translation: "Emne" },
},
AGE: { filter: "age", translation: "Alder" },
LIX: { filter: "lixRange", translation: "Lix" },
SUBJECTS: { filter: "subjects", translation: "Emne" },
} as TConfigSearchFacets,
}

export type TConfigSearchFacets = Record<FacetFieldEnum, { filter: string; translation: string }>

export default search
Loading

0 comments on commit 399492f

Please sign in to comment.