Skip to content

Commit

Permalink
Added more pages using components
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenwf committed Feb 28, 2024
1 parent 6fe723a commit 623a02d
Show file tree
Hide file tree
Showing 17 changed files with 589 additions and 140 deletions.
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": ["prettier-plugin-tailwindcss"],
"printWidth": 120,
"trailingComma": "es5"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@ import { loadCollection } from "@/iiif";
import { Page } from "@/components/Page";
import { unstable_setRequestLocale } from "next-intl/server";

export default async function Collection({
params,
}: {
params: { collection: string; locale: string };
}) {
export default async function Collection({ params }: { params: { collection: string; locale: string } }) {
unstable_setRequestLocale(params.locale);
const { collection, meta, id } = await loadCollection(params.collection);
const { collection, meta } = await loadCollection(params.collection);

return (
<Page>
Expand Down
28 changes: 16 additions & 12 deletions apps/static-site/app/[locale]/exhibitions/[exhibition]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { client, getExhibitions, loadJson } from "@/iiif";
import { client, getExhibitions, loadImageServiceLinks, loadJson, loadRelated } from "@/iiif";
import { Page } from "@/components/Page";
import { ExhibitionPage } from "@/components/pages/ExhibitionPage";
import { unstable_setRequestLocale } from "next-intl/server";
import { ManifestLoader } from "@/app/provider";

const imageServiceLinks = await loadImageServiceLinks();

export const generateStaticParams = async () => {
const exhibitions = [];
Expand All @@ -20,23 +23,24 @@ export const generateStaticParams = async () => {
return exhibitions;
};

export default async function Exhibition({
params,
}: {
params: { exhibition: string; locale: string };
}) {
export default async function Exhibition({ params }: { params: { exhibition: string; locale: string } }) {
unstable_setRequestLocale(params.locale);
const data = await client.loadManifest(`/manifests/${params.exhibition}`);
const manifestSlug = `manifests/${params.exhibition}`;
const data = await client.loadManifest(`/${manifestSlug}`);
const meta = await loadJson(data.meta);
const manifest = await loadJson(data.manifest);
const viewObjectLinks = imageServiceLinks[manifestSlug] || [];

return (
<Page>
<ExhibitionPage
manifest={manifest as any}
meta={meta as any}
slug={params.exhibition}
/>
<ManifestLoader manifest={manifest}>
<ExhibitionPage
manifest={manifest as any}
meta={meta as any}
slug={params.exhibition}
viewObjectLinks={viewObjectLinks}
/>
</ManifestLoader>
</Page>
);
}
46 changes: 46 additions & 0 deletions apps/static-site/app/[locale]/manifests/[manifest]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Page } from "@/components/Page";
import { client, loadJson, loadRelated } from "@/iiif";
import { unstable_setRequestLocale } from "next-intl/server";
import { Manifest } from "@iiif/presentation-3";
import { ManifestPage } from "@/components/pages/ManifestPage";
import { ManifestLoader } from "@/app/provider";
import { useSearchParams } from "next/navigation";

const related = await loadRelated();

export default async function ManifestP({ params }: { params: { locale: string; manifest: string } }) {
unstable_setRequestLocale(params.locale);

const manifestSlug = `manifests/${params.manifest}`;
const { manifest, meta } = await client.loadManifest(manifestSlug);
const manifestJson = await loadJson<Manifest>(manifest);
const metaJson = await loadJson(meta);

const relatedItems = related[manifestSlug] || [];
const relatedSnippets = (
await Promise.all(
relatedItems.map(async (slug) => {
try {
const meta = await loadJson<any>((await client.loadManifest(slug)).meta);

return {
slug,
label: meta.label || "Untitled",
thumbnail: meta.thumbnail?.id,
meta,
};
} catch (e) {
return null;
}
})
)
).filter((x) => x !== null);

return (
<Page>
<ManifestLoader manifest={manifestJson}>
<ManifestPage manifest={manifestJson} meta={metaJson as any} related={relatedSnippets} />
</ManifestLoader>
</Page>
);
}
59 changes: 59 additions & 0 deletions apps/static-site/app/[locale]/search/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"use client";

import { InternationalString } from "@iiif/presentation-3";
import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter";
import { InstantSearch, SearchBox, Hits, RefinementList } from "react-instantsearch";
import { Link } from "@/navigation";

const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({
server: {
apiKey: "xyz", // Be sure to use the search-only-api-key
nodes: [
{
host: "localhost",
port: 8108,
protocol: "http",
},
],
},
// The following parameters are directly passed to Typesense's search API endpoint.
// So you can pass any parameters supported by the search endpoint below.
// queryBy is required.
additionalSearchParameters: {
query_by: "label,type,topic_material,topic_Maker",
},
});

function Hit({
hit,
}: {
hit: {
thumbnail: string;
label: string;
full_label: InternationalString;
slug: string;
};
}) {
return (
<article>
<h1>{hit.label}</h1>
<img src={hit.thumbnail} />
<Link href={hit.slug}>View</Link>
</article>
);
}

export default function SearchPage() {
return (
<div>
<h1>Search</h1>
<InstantSearch searchClient={typesenseInstantsearchAdapter.searchClient} indexName="manifests">
<SearchBox />
<RefinementList attribute="type" />
<RefinementList attribute="topic_material" />
<RefinementList attribute="topic_Maker" />
<Hits hitComponent={Hit} />
</InstantSearch>
</div>
);
}
87 changes: 82 additions & 5 deletions apps/static-site/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,32 @@ html,
body {
max-width: 100vw;
overflow-x: hidden;
font-feature-settings: "kern","liga","clig","calt";
font-feature-settings: "kern", "liga", "clig", "calt";
}

.cut-corners {
-webkit-clip-path: polygon(1rem 0,calc(100% - 1rem) 0,100% 1rem,100% calc(100% - 1rem),calc(100% - 1rem) 100%,1rem 100%,0 calc(100% - 1rem),0 1rem);
clip-path: polygon(1rem 0,calc(100% - 1rem) 0,100% 1rem,100% calc(100% - 1rem),calc(100% - 1rem) 100%,1rem 100%,0 calc(100% - 1rem),0 1rem);
-webkit-clip-path: polygon(
1rem 0,
calc(100% - 1rem) 0,
100% 1rem,
100% calc(100% - 1rem),
calc(100% - 1rem) 100%,
1rem 100%,
0 calc(100% - 1rem),
0 1rem
);
clip-path: polygon(
1rem 0,
calc(100% - 1rem) 0,
100% 1rem,
100% calc(100% - 1rem),
calc(100% - 1rem) 100%,
1rem 100%,
0 calc(100% - 1rem),
0 1rem
);
}


pb-slot.grid::part(slot-bar) {
position: absolute;
top: -40px;
Expand All @@ -36,9 +53,69 @@ pb-slot.grid::part(slot-bar) {
}

.prose hr {
background: rgba(0,0,0,.2);
background: rgba(0, 0, 0, 0.2);
border: none;
height: 1px;
margin: 0 0 calc(1.45rem - 1px);
padding: 0;
}

.iiif-link-wrapper {
display: block;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAeCAYAAABJ/8wUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpDRkQyMTBBMDMyNjIxMUUzQkJBM0QwRjI2NzMyQkY5MSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpDRkQyMTBBMTMyNjIxMUUzQkJBM0QwRjI2NzMyQkY5MSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkNGRDIxMDlFMzI2MjExRTNCQkEzRDBGMjY3MzJCRjkxIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkNGRDIxMDlGMzI2MjExRTNCQkEzRDBGMjY3MzJCRjkxIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+fU0zWQAABNFJREFUeNrEV79bHDcQnaePIuWdK5dHE1JCg10eVbqA21Dk+A9wYZzOn0s7Bc5fcLiAlJAyFS4dGlMGN1CmClu60uSNfq20e7j1wt5qJc1o5s3Mk3ZNVeVbXd3G04WK3xXBfO3bGPBk7kWXEJkZDBCVYAhenM0FumRzBsEdR94TqHf69ueuVnC/8WTCxyEV/EIFM8pzrj6b3lxd4+jsWFQPxXFU5YI/v+vb/Q9DI6hjwTFbSywYCAbw30KDl2f34nUSu/OoXNOoHZ+Muf9+e8L+S/Zt0pswBeLY8t2jnw53+PIpyGrQylfzUw7ozEk24r+N7T32n4uU8bSUUFM0bQLnYi8QJvHapJHnWQmFLvkTjHCCpMjbkwaaE5pdi/ZEsSWOTn+QshiOoxFOfJih5S8YAi5eJ21UCeufM2yLoATYtHVcMEDTQkgtNJLmTELcdPwYQ7JtembRSM3ORh2aEGHjQ+zXcttgCJuTXZFeuF44hgeWB/8gqEKvA8lfQ/vo9DGbu0EfehPS9auDm7rkyWvmSHIoTUPJpEmPlFaea4CXf8+ZB//y7SKsj4SIJlyjvu/YnCt6PTnHpjd/v5ncfOwiIpbdkIPoRoxh9le93knxv724zIFVTArvATuuNULZGxxWxxdzyLDwGpH1VYD7ZI3GnBCFHasW8zV5beX5Os24q2LKxbFDb0pF+DdWXbpDJ2x+16PoPxpi+S2AFRO3ca0Y4l7+YbXd0aAtzp6yvcX2Ou9gAD1fp+gWvZg++ny1RSUdiWmZklCYB5d87Kl68s9+kGfvlO2/mkQu7UJuanePiKop/IQXp7ecd8i7G4aCSHRQLEhKtzSIvCELGjdLw3O2l3TinjqWlJ/VhIiAQc5j12Rbg0jpgpjiV3zempe8Z4mMLq2PoTqOiyNxQZUOvY4F73PKmlFP+xSNBeBL6FOdaWMIWuiCDHlE3CyNzmtIS7XnUkaS15ojxNh6o9aPhE2TsNABIsjli6SzzWxJ9ZcL1wHFs1ItDr1EovuqymJiJwOQGZpT1hpEUu2X3WhYsUUpKlbRCiJkhu8Dr6V6Ck/lTcQ0TG6uMMoRNJtehrr2ZkDlA1aRATfY2ih0j8K2Mp5ZG1KQH1C1jthQqu2qcQTDPUebPaxljgd4JNdn85S2poZV0oNsnru0KFYehrTkxSo8akPyfgcMdPXQQmLphbxPZeM1J6tvaSA7k1BqmF9GG19lSIZVtTeqmd73p3NIIzaCD3UBxFxBPuusQM6NlaCqmLoE4q7qgHJEWCUbcggyCnETEuAroUkT6rofhykJwVXhQhuCwJoIOdNX3xhdDFJxNSKCB6o0J5mWyi66vDZzNbMzciX7pl40nvq+UjWo8sPe/XB7QsMFDaEV2ZiZ9REUlRm+Oe3Fa22UG8WN1sPshTTnzbacoyMYoIJBDmuKvtZDddXUivWBchjGus4R6c+jNQlX24Kr82mQfrUhXdnwioeo9oqWiNJvp+XkFo+JYdzrClIck9hDhLZOYZ6q7Cstb8ItbWufBjbngP6v8+R2ko6aW/FUJu846Q5wK6il8Agd4Dye+EY5kk5TdhB+5o7O7PtjT+zTUgsCNvaewhc8q96tpPHf9q+TjufUYfL2KfIlfVyZK2b0n9PPVxdD2f8FGABRh3uKJmT1VAAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-size: 23px 20px;
cursor: pointer;
width: 23px;
height: 20px;
}

/* Exhibition editorial */
.exhibition-info-block {
h2 {
@apply mb-4 text-center font-mono uppercase;
}
p {
@apply my-4;
}
}

/* Atlas styling */
.atlas-container {
min-width: 0;
min-height: 0;
--atlas-container-flex: 1 1 0px;
--atlas-background: #373737;
--atlas-container-height: 100%;
}

.canvas-preview {
--atlas-container-flex: 1;
}

div:has(> div[data-textual-content="true"]) {
display: flex;
width: 100%;
flex-direction: column;
height: 100%;
}
div[data-textual-content="true"] {
color: #fff;
padding: 30px;
width: 100%;
height: 100%;

h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
}

h2 {
font-size: 2rem;
margin-bottom: 1rem;
}

p {
font-size: 1.25rem;
}
}
7 changes: 1 addition & 6 deletions apps/static-site/components/directory.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { createDirectory } from "@page-blocks/react";
import {
CollectionBox,
ManifestBox,
PublicationBox,
ExhibitionBox,
} from "@/components/blocks/Box";
import { CollectionBox, ManifestBox, PublicationBox, ExhibitionBox } from "@/components/blocks/Box";
import { HeadingParagraph } from "@/components/blocks/HeadingParagraph";
import { CardGrid } from "@/components/blocks/CardGrid";

Expand Down
65 changes: 43 additions & 22 deletions apps/static-site/components/pages/ExhibitionPage.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,55 @@
import { Manifest } from "@iiif/presentation-3";
import { AutoLanguage } from "@/components/pages/AutoLanguage";
import { Exhibition } from "@repo/exhibition-viewer";
import { createPaintingAnnotationsHelper } from "@iiif/helpers/painting-annotations";
import { getRenderingStrategy } from "react-iiif-vault/utils";
import { TitlePanel } from "../exhibitions/TitleBlock";
import { InfoBlock } from "../exhibitions/InfoBlock";
import { ImageBlock } from "../exhibitions/ImageBlock";
import { MediaBlock } from "../exhibitions/MediaBlock";

export interface ExhibitionPageProps {
manifest: Manifest;
meta: {};
slug: string;
viewObjectLinks: Array<{ service: string; slug: string; canvasId: string; targetCanvasId: string }>;
}

export function ExhibitionPage(props: ExhibitionPageProps) {
export async function ExhibitionPage(props: ExhibitionPageProps) {
const helper = createPaintingAnnotationsHelper();
const canvas: any = props.manifest.items[0];

if (!canvas) return null;

return (
<div>
<h1 className="text-3xl font-bold underline my-4">
<AutoLanguage>{props.manifest.label}</AutoLanguage>
</h1>
<div>
<AutoLanguage lines className="mb-3">
{props.manifest.summary}
</AutoLanguage>
<AutoLanguage lines className="mb-3">
{props.manifest.requiredStatement?.label}
</AutoLanguage>
<AutoLanguage lines className="mb-3 font-bold italic">
{props.manifest.requiredStatement?.value}
</AutoLanguage>
</div>
<div>
<pre>{props.manifest.id}</pre>
<>
<div className="mt-12 auto-rows-auto grid-cols-12 content-center justify-center lg:grid">
<TitlePanel manifest={props.manifest} />

{props.manifest.items.map((canvas: any, idx) => {
const paintables = helper.getPaintables(canvas);
const strategy = getRenderingStrategy({
canvas,
loadImageService: () => void 0,
paintables,
supports: ["empty", "images", "media", "3d-model", "textual-content", "complex-timeline"],
});

const foundLinks = props.viewObjectLinks.filter((link) => link.canvasId === canvas.id);

if (strategy.type === "textual-content") {
return <InfoBlock canvas={canvas} strategy={strategy} />;
}

if (strategy.type === "images") {
return <ImageBlock canvas={canvas} index={idx} objectLinks={foundLinks} />;
}

if (strategy.type === "media") {
return <MediaBlock canvas={canvas} strategy={strategy} index={idx} />;
}

return null;
})}
</div>
<Exhibition manifest={props.manifest} />
</div>
</>
);
}
Loading

0 comments on commit 623a02d

Please sign in to comment.