Use graphql-codegen and replace all types from queries
This commit is contained in:
parent
acf92d6fc1
commit
125421de0f
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
/testing_logs/*
|
/testing_logs/*
|
||||||
|
|
||||||
|
# Generated content
|
||||||
|
src/graphql/generated.ts
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
/.pnp
|
/.pnp
|
||||||
|
|
|
@ -25,9 +25,10 @@
|
||||||
#### [Front](https://github.com/Accords-Library/accords-library.com) (this repository)
|
#### [Front](https://github.com/Accords-Library/accords-library.com) (this repository)
|
||||||
|
|
||||||
- Language: [TypeScript](https://www.typescriptlang.org/)
|
- Language: [TypeScript](https://www.typescriptlang.org/)
|
||||||
- Queries: [GraphQL](https://graphql.org/)
|
- Queries: [GraphQL Code Generator](https://www.graphql-code-generator.com/)
|
||||||
- [GraphQL Code Generator](https://www.graphql-code-generator.com/) to automatically generated types for the operations variables and responses
|
- Fetch the GraphQL schema from the GraphQL back-end endpoint
|
||||||
- The operations are stored in a graphql file and then retrieved and wrap as an actual TypeScript function
|
- Read the operations and fragments stored as graphql files in the `src/graphql` folder
|
||||||
|
- Automatically generates a typesafe ready to use SDK using [graphql-request](https://www.npmjs.com/package/graphql-request) as the GraphQL client
|
||||||
- Markdown: [markdown-to-jsx](https://www.npmjs.com/package/markdown-to-jsx)
|
- Markdown: [markdown-to-jsx](https://www.npmjs.com/package/markdown-to-jsx)
|
||||||
- Support for Arbitrary React Components and Component Props!
|
- Support for Arbitrary React Components and Component Props!
|
||||||
- Autogenerated multi-level table of content and anchor links for the different headers
|
- Autogenerated multi-level table of content and anchor links for the different headers
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
const { loadEnvConfig } = require("@next/env");
|
||||||
|
loadEnvConfig(process.cwd());
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
overwrite: true,
|
||||||
|
schema: {
|
||||||
|
[process.env.URL_GRAPHQL]: {
|
||||||
|
headers: { Authorization: `Bearer ${process.env.ACCESS_TOKEN}` },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
documents: ["src/graphql/operations/*.graphql", "src/graphql/fragments/*.graphql"],
|
||||||
|
generates: {
|
||||||
|
"src/graphql/generated.ts": {
|
||||||
|
plugins: [
|
||||||
|
"typescript",
|
||||||
|
"typescript-operations",
|
||||||
|
"typescript-graphql-request",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,8 @@
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"postbuild": "next-sitemap",
|
"postbuild": "next-sitemap",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"generate": "graphql-codegen --config graphql-codegen.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/material-icons": "^4.5.4",
|
"@fontsource/material-icons": "^4.5.4",
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
"@fontsource/vollkorn": "^4.5.6",
|
"@fontsource/vollkorn": "^4.5.6",
|
||||||
"@fontsource/zen-maru-gothic": "^4.5.8",
|
"@fontsource/zen-maru-gothic": "^4.5.8",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
|
"graphql-request": "^4.2.0",
|
||||||
"markdown-to-jsx": "^7.1.7",
|
"markdown-to-jsx": "^7.1.7",
|
||||||
"next": "^12.1.2",
|
"next": "^12.1.2",
|
||||||
"nodemailer": "^6.7.3",
|
"nodemailer": "^6.7.3",
|
||||||
|
@ -25,6 +27,10 @@
|
||||||
"turndown": "^7.1.1"
|
"turndown": "^7.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@graphql-codegen/cli": "^2.6.2",
|
||||||
|
"@graphql-codegen/typescript": "2.4.8",
|
||||||
|
"@graphql-codegen/typescript-graphql-request": "^4.4.4",
|
||||||
|
"@graphql-codegen/typescript-operations": "^2.3.5",
|
||||||
"@types/node": "17.0.23",
|
"@types/node": "17.0.23",
|
||||||
"@types/nodemailer": "^6.4.4",
|
"@types/nodemailer": "^6.4.4",
|
||||||
"@types/react": "17.0.43",
|
"@types/react": "17.0.43",
|
||||||
|
@ -34,6 +40,7 @@
|
||||||
"@typescript-eslint/parser": "^5.17.0",
|
"@typescript-eslint/parser": "^5.17.0",
|
||||||
"eslint": "^8.12.0",
|
"eslint": "^8.12.0",
|
||||||
"eslint-config-next": "12.1.2",
|
"eslint-config-next": "12.1.2",
|
||||||
|
"graphql": "^14.7.0",
|
||||||
"next-sitemap": "^2.5.14",
|
"next-sitemap": "^2.5.14",
|
||||||
"prettier-plugin-organize-imports": "^2.3.4",
|
"prettier-plugin-organize-imports": "^2.3.4",
|
||||||
"tailwindcss": "^3.0.23",
|
"tailwindcss": "^3.0.23",
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
npx next build
|
npm run generate
|
||||||
|
npm run build
|
||||||
|
npm run postbuild
|
|
@ -1,11 +1,16 @@
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { StrapiImage } from "graphql/operations-types";
|
import { UploadImageFragment } from "graphql/generated";
|
||||||
import { useMediaMobile } from "hooks/useMediaQuery";
|
import { useMediaMobile } from "hooks/useMediaQuery";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getOgImage, OgImage, prettyLanguage } from "queries/helpers";
|
import {
|
||||||
|
getOgImage,
|
||||||
|
OgImage,
|
||||||
|
prettyLanguage,
|
||||||
|
prettySlug,
|
||||||
|
} from "queries/helpers";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useSwipeable } from "react-swipeable";
|
import { useSwipeable } from "react-swipeable";
|
||||||
import { ImageQuality } from "./Img";
|
import { ImageQuality } from "./Img";
|
||||||
|
@ -18,8 +23,8 @@ interface AppLayoutProps extends AppStaticProps {
|
||||||
subPanelIcon?: string;
|
subPanelIcon?: string;
|
||||||
contentPanel?: React.ReactNode;
|
contentPanel?: React.ReactNode;
|
||||||
title?: string;
|
title?: string;
|
||||||
navTitle: string;
|
navTitle: string | null | undefined;
|
||||||
thumbnail?: StrapiImage;
|
thumbnail?: UploadImageFragment;
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,11 +66,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
height: 630,
|
height: 630,
|
||||||
alt: "Accord's Library Logo",
|
alt: "Accord's Library Logo",
|
||||||
};
|
};
|
||||||
const ogTitle = props.title ? props.title : props.navTitle;
|
const ogTitle =
|
||||||
|
props.title ?? props.navTitle ?? prettySlug(router.asPath.split("/").pop());
|
||||||
|
|
||||||
const metaDescription = props.description
|
const metaDescription = props.description ?? langui.default_description ?? "";
|
||||||
? props.description
|
|
||||||
: langui.default_description;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.getElementsByTagName("html")[0].style.fontSize = `${
|
document.getElementsByTagName("html")[0].style.fontSize = `${
|
||||||
|
@ -73,9 +77,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
}%`;
|
}%`;
|
||||||
}, [appLayout.fontSize]);
|
}, [appLayout.fontSize]);
|
||||||
|
|
||||||
const currencyOptions = currencies.map(
|
const currencyOptions: string[] = [];
|
||||||
(currency) => currency.attributes.code
|
currencies.map((currency) => {
|
||||||
);
|
if (currency.attributes?.code) currencyOptions.push(currency.attributes.code);
|
||||||
|
});
|
||||||
const [currencySelect, setCurrencySelect] = useState<number>(-1);
|
const [currencySelect, setCurrencySelect] = useState<number>(-1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -127,7 +132,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
></meta>
|
></meta>
|
||||||
|
|
||||||
<meta name="description" content={metaDescription} />
|
<meta name="description" content={metaDescription} />
|
||||||
<meta name="twitter:description" content={metaDescription}></meta>
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content={metaDescription}
|
||||||
|
></meta>
|
||||||
|
|
||||||
<meta property="og:image" content={metaImage.image}></meta>
|
<meta property="og:image" content={metaImage.image}></meta>
|
||||||
<meta property="og:image:secure_url" content={metaImage.image}></meta>
|
<meta property="og:image:secure_url" content={metaImage.image}></meta>
|
||||||
|
@ -220,12 +228,12 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
</span>
|
</span>
|
||||||
<p
|
<p
|
||||||
className={`font-black font-headers text-center overflow-hidden ${
|
className={`font-black font-headers text-center overflow-hidden ${
|
||||||
props.navTitle?.length > 30
|
ogTitle && ogTitle.length > 30
|
||||||
? "text-xl max-h-14"
|
? "text-xl max-h-14"
|
||||||
: "text-2xl max-h-16"
|
: "text-2xl max-h-16"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{props.navTitle}
|
{ogTitle}
|
||||||
</p>
|
</p>
|
||||||
<span
|
<span
|
||||||
className="material-icons mt-[.1em] cursor-pointer"
|
className="material-icons mt-[.1em] cursor-pointer"
|
||||||
|
|
|
@ -3,14 +3,17 @@ import ToolTip from "components/ToolTip";
|
||||||
import {
|
import {
|
||||||
Enum_Componenttranslationschronologyitem_Status,
|
Enum_Componenttranslationschronologyitem_Status,
|
||||||
GetChronologyItemsQuery,
|
GetChronologyItemsQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
} from "graphql/generated";
|
||||||
} from "graphql/operations-types";
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getStatusDescription } from "queries/helpers";
|
import { getStatusDescription } from "queries/helpers";
|
||||||
|
|
||||||
export type ChronologyItemComponentProps = {
|
export type ChronologyItemComponentProps = {
|
||||||
item: GetChronologyItemsQuery["chronologyItems"]["data"][number];
|
item: Exclude<
|
||||||
|
GetChronologyItemsQuery["chronologyItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number];
|
||||||
displayYear: boolean;
|
displayYear: boolean;
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: AppStaticProps["langui"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ChronologyItemComponent(
|
export default function ChronologyItemComponent(
|
||||||
|
@ -18,22 +21,29 @@ export default function ChronologyItemComponent(
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const { langui } = props;
|
const { langui } = props;
|
||||||
|
|
||||||
function generateAnchor(year: number, month: number, day: number): string {
|
function generateAnchor(
|
||||||
|
year: number | undefined,
|
||||||
|
month: number | null | undefined,
|
||||||
|
day: number | null | undefined
|
||||||
|
): string {
|
||||||
let result = "";
|
let result = "";
|
||||||
result += year;
|
if (year) result += year;
|
||||||
if (month) result += `- ${month.toString().padStart(2, "0")}`;
|
if (month) result += `- ${month.toString().padStart(2, "0")}`;
|
||||||
if (day) result += `- ${day.toString().padStart(2, "0")}`;
|
if (day) result += `- ${day.toString().padStart(2, "0")}`;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateYear(displayed_date: string, year: number): string {
|
function generateYear(
|
||||||
if (displayed_date) {
|
displayed_date: string | null | undefined,
|
||||||
return displayed_date;
|
year: number | undefined
|
||||||
}
|
): string {
|
||||||
return year.toString();
|
return displayed_date ?? year?.toString() ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateDate(month: number, day: number): string {
|
function generateDate(
|
||||||
|
month: number | null | undefined,
|
||||||
|
day: number | null | undefined
|
||||||
|
): string {
|
||||||
const lut = [
|
const lut = [
|
||||||
"Jan",
|
"Jan",
|
||||||
"Feb",
|
"Feb",
|
||||||
|
@ -50,7 +60,7 @@ export default function ChronologyItemComponent(
|
||||||
];
|
];
|
||||||
|
|
||||||
let result = "";
|
let result = "";
|
||||||
if (month) {
|
if (month && month >= 1 && month <= 12) {
|
||||||
result += lut[month - 1];
|
result += lut[month - 1];
|
||||||
if (day) {
|
if (day) {
|
||||||
result += ` ${day}`;
|
result += ` ${day}`;
|
||||||
|
@ -60,78 +70,98 @@ export default function ChronologyItemComponent(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
if (props.item.attributes) {
|
||||||
<div
|
return (
|
||||||
className="grid place-content-start grid-rows-[auto_1fr] grid-cols-[4em] py-4 px-8 rounded-2xl target:bg-mid target:py-8 target:my-4"
|
<div
|
||||||
id={generateAnchor(
|
className="grid place-content-start grid-rows-[auto_1fr] grid-cols-[4em] py-4 px-8 rounded-2xl target:bg-mid target:py-8 target:my-4"
|
||||||
props.item.attributes.year,
|
id={generateAnchor(
|
||||||
props.item.attributes.month,
|
props.item.attributes.year,
|
||||||
props.item.attributes.day
|
props.item.attributes.month,
|
||||||
)}
|
props.item.attributes.day
|
||||||
>
|
)}
|
||||||
{props.displayYear && (
|
>
|
||||||
<p className="text-lg mt-[-.2em] font-bold">
|
{props.displayYear && (
|
||||||
{generateYear(
|
<p className="text-lg mt-[-.2em] font-bold">
|
||||||
props.item.attributes.displayed_date,
|
{generateYear(
|
||||||
props.item.attributes.year
|
props.item.attributes.displayed_date,
|
||||||
)}
|
props.item.attributes.year
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<p className="col-start-1 text-dark text-sm">
|
||||||
|
{generateDate(props.item.attributes.month, props.item.attributes.day)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
|
||||||
|
|
||||||
<p className="col-start-1 text-dark text-sm">
|
<div className="col-start-2 row-start-1 row-span-2 grid gap-4">
|
||||||
{generateDate(props.item.attributes.month, props.item.attributes.day)}
|
{props.item.attributes.events?.map((event) => (
|
||||||
</p>
|
<>
|
||||||
|
{event && (
|
||||||
|
<div className="m-0" key={event.id}>
|
||||||
|
{event.translations?.map((translation) => (
|
||||||
|
<>
|
||||||
|
{translation && (
|
||||||
|
<>
|
||||||
|
<div className="place-items-start place-content-start grid grid-flow-col gap-2">
|
||||||
|
{translation.status !==
|
||||||
|
Enum_Componenttranslationschronologyitem_Status.Done && (
|
||||||
|
<ToolTip
|
||||||
|
content={getStatusDescription(
|
||||||
|
translation.status,
|
||||||
|
langui
|
||||||
|
)}
|
||||||
|
maxWidth={"20rem"}
|
||||||
|
>
|
||||||
|
<Chip>{translation.status}</Chip>
|
||||||
|
</ToolTip>
|
||||||
|
)}
|
||||||
|
{translation.title ? (
|
||||||
|
<h3>{translation.title}</h3>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="col-start-2 row-start-1 row-span-2 grid gap-4">
|
{translation.description && (
|
||||||
{props.item.attributes.events.map((event) => (
|
<p
|
||||||
<div className="m-0" key={event.id}>
|
className={
|
||||||
{event.translations.map((translation) => (
|
event.translations &&
|
||||||
<>
|
event.translations.length > 1
|
||||||
<div className="place-items-start place-content-start grid grid-flow-col gap-2">
|
? "before:content-['-'] before:text-dark before:inline-block before:w-4 before:ml-[-1em] mt-2 whitespace-pre-line"
|
||||||
{translation.status !==
|
: "whitespace-pre-line"
|
||||||
Enum_Componenttranslationschronologyitem_Status.Done && (
|
}
|
||||||
<ToolTip
|
>
|
||||||
content={getStatusDescription(translation.status, langui)}
|
{translation.description}
|
||||||
maxWidth={"20rem"}
|
</p>
|
||||||
>
|
)}
|
||||||
<Chip>{translation.status}</Chip>
|
{translation.note ? (
|
||||||
</ToolTip>
|
<em>{`Notes: ${translation.note}`}</em>
|
||||||
)}
|
) : (
|
||||||
{translation.title ? <h3>{translation.title}</h3> : ""}
|
""
|
||||||
</div>
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
|
||||||
{translation.description && (
|
<p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1">
|
||||||
<p
|
{event.source?.data ? (
|
||||||
className={
|
`(${event.source.data.attributes?.name})`
|
||||||
event.translations.length > 1
|
) : (
|
||||||
? "before:content-['-'] before:text-dark before:inline-block before:w-4 before:ml-[-1em] mt-2 whitespace-pre-line"
|
<>
|
||||||
: "whitespace-pre-line"
|
<span className="material-icons !text-sm">warning</span>
|
||||||
}
|
No sources!
|
||||||
>
|
</>
|
||||||
{translation.description}
|
)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
</div>
|
||||||
{translation.note ? (
|
|
||||||
<em>{`Notes: ${translation.note}`}</em>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1">
|
|
||||||
{event.source.data ? (
|
|
||||||
`(${event.source.data.attributes.name})`
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<span className="material-icons !text-sm">warning</span>No
|
|
||||||
sources!
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</p>
|
</>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import ChronologyItemComponent from "components/Chronology/ChronologyItemComponent";
|
import ChronologyItemComponent from "components/Chronology/ChronologyItemComponent";
|
||||||
import {
|
import { GetChronologyItemsQuery } from "graphql/generated";
|
||||||
GetChronologyItemsQuery,
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
|
|
||||||
type ChronologyYearComponentProps = {
|
type ChronologyYearComponentProps = {
|
||||||
year: number;
|
year: number;
|
||||||
items: GetChronologyItemsQuery["chronologyItems"]["data"][number][];
|
items: Exclude<
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
GetChronologyItemsQuery["chronologyItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number][];
|
||||||
|
langui: AppStaticProps["langui"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ChronologyYearComponent(
|
export default function ChronologyYearComponent(
|
||||||
|
|
|
@ -1,21 +1,31 @@
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
import Img, { ImageQuality } from "components/Img";
|
import Img, { ImageQuality } from "components/Img";
|
||||||
import InsetBox from "components/InsetBox";
|
import InsetBox from "components/InsetBox";
|
||||||
import {
|
import { GetContentQuery, UploadImageFragment } from "graphql/generated";
|
||||||
GetContentQuery,
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers";
|
import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers";
|
||||||
|
|
||||||
export type ThumbnailHeaderProps = {
|
export type ThumbnailHeaderProps = {
|
||||||
pre_title?: string;
|
pre_title?: string | null | undefined;
|
||||||
title: string;
|
title: string | null | undefined;
|
||||||
subtitle?: string;
|
subtitle?: string | null | undefined;
|
||||||
description?: string;
|
description?: string | null | undefined;
|
||||||
type?: GetContentQuery["contents"]["data"][number]["attributes"]["type"];
|
type?: Exclude<
|
||||||
categories?: GetContentQuery["contents"]["data"][number]["attributes"]["categories"];
|
Exclude<
|
||||||
thumbnail?: GetContentQuery["contents"]["data"][number]["attributes"]["thumbnail"]["data"]["attributes"];
|
GetContentQuery["contents"],
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
null | undefined
|
||||||
|
>["data"][number]["attributes"],
|
||||||
|
null | undefined
|
||||||
|
>["type"];
|
||||||
|
categories?: Exclude<
|
||||||
|
Exclude<
|
||||||
|
GetContentQuery["contents"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"],
|
||||||
|
null | undefined
|
||||||
|
>["categories"];
|
||||||
|
thumbnail?: UploadImageFragment | null | undefined;
|
||||||
|
langui: AppStaticProps["langui"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ThumbnailHeader(
|
export default function ThumbnailHeader(
|
||||||
|
@ -60,13 +70,14 @@ export default function ThumbnailHeader(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-flow-col gap-8">
|
<div className="grid grid-flow-col gap-8">
|
||||||
{type?.data && (
|
{type?.data?.attributes && (
|
||||||
<div className="flex flex-col place-items-center gap-2">
|
<div className="flex flex-col place-items-center gap-2">
|
||||||
<h3 className="text-xl">{langui.type}</h3>
|
<h3 className="text-xl">{langui.type}</h3>
|
||||||
<div className="flex flex-row flex-wrap">
|
<div className="flex flex-row flex-wrap">
|
||||||
<Chip>
|
<Chip>
|
||||||
{type.data.attributes.titles.length > 0
|
{type.data.attributes.titles &&
|
||||||
? type.data.attributes.titles[0].title
|
type.data.attributes.titles.length > 0
|
||||||
|
? type.data.attributes.titles[0]?.title
|
||||||
: prettySlug(type.data.attributes.slug)}
|
: prettySlug(type.data.attributes.slug)}
|
||||||
</Chip>
|
</Chip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +89,7 @@ export default function ThumbnailHeader(
|
||||||
<h3 className="text-xl">{langui.categories}</h3>
|
<h3 className="text-xl">{langui.categories}</h3>
|
||||||
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||||
{categories.data.map((category) => (
|
{categories.data.map((category) => (
|
||||||
<Chip key={category.id}>{category.attributes.name}</Chip>
|
<Chip key={category.id}>{category.attributes?.name}</Chip>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { StrapiImage } from "graphql/operations-types";
|
import { UploadImageFragment } from "graphql/generated";
|
||||||
import Image, { ImageProps } from "next/image";
|
import Image, { ImageProps } from "next/image";
|
||||||
|
|
||||||
export enum ImageQuality {
|
export enum ImageQuality {
|
||||||
|
@ -51,7 +51,7 @@ export function getImgSizesByQuality(
|
||||||
|
|
||||||
type ImgProps = {
|
type ImgProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
image?: StrapiImage;
|
image?: UploadImageFragment;
|
||||||
quality?: ImageQuality;
|
quality?: ImageQuality;
|
||||||
alt?: ImageProps["alt"];
|
alt?: ImageProps["alt"];
|
||||||
layout?: ImageProps["layout"];
|
layout?: ImageProps["layout"];
|
||||||
|
@ -61,11 +61,11 @@ type ImgProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Img(props: ImgProps): JSX.Element {
|
export default function Img(props: ImgProps): JSX.Element {
|
||||||
if (props.image) {
|
if (props.image?.width && props.image?.height) {
|
||||||
const imgSize = getImgSizesByQuality(
|
const imgSize = getImgSizesByQuality(
|
||||||
props.image.width,
|
props.image.width,
|
||||||
props.image.height,
|
props.image.height,
|
||||||
props.quality ? props.quality : ImageQuality.Small
|
props.quality ?? ImageQuality.Small
|
||||||
);
|
);
|
||||||
|
|
||||||
if (props.rawImg) {
|
if (props.rawImg) {
|
||||||
|
@ -75,9 +75,9 @@ export default function Img(props: ImgProps): JSX.Element {
|
||||||
className={props.className}
|
className={props.className}
|
||||||
src={getAssetURL(
|
src={getAssetURL(
|
||||||
props.image.url,
|
props.image.url,
|
||||||
props.quality ? props.quality : ImageQuality.Small
|
props.quality ?? ImageQuality.Small
|
||||||
)}
|
)}
|
||||||
alt={props.alt ? props.alt : props.image.alternativeText}
|
alt={props.alt ?? props.image.alternativeText ?? ""}
|
||||||
width={imgSize.width}
|
width={imgSize.width}
|
||||||
height={imgSize.height}
|
height={imgSize.height}
|
||||||
/>
|
/>
|
||||||
|
@ -90,7 +90,7 @@ export default function Img(props: ImgProps): JSX.Element {
|
||||||
props.image.url,
|
props.image.url,
|
||||||
props.quality ? props.quality : ImageQuality.Small
|
props.quality ? props.quality : ImageQuality.Small
|
||||||
)}
|
)}
|
||||||
alt={props.alt ? props.alt : props.image.alternativeText}
|
alt={props.alt ?? props.image.alternativeText ?? ""}
|
||||||
width={props.layout === "fill" ? undefined : imgSize.width}
|
width={props.layout === "fill" ? undefined : imgSize.width}
|
||||||
height={props.layout === "fill" ? undefined : imgSize.height}
|
height={props.layout === "fill" ? undefined : imgSize.height}
|
||||||
layout={props.layout}
|
layout={props.layout}
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
import {
|
|
||||||
GetLanguagesQuery,
|
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { prettyLanguage } from "queries/helpers";
|
import { prettyLanguage } from "queries/helpers";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
|
||||||
type HorizontalLineProps = {
|
type HorizontalLineProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
locales: string[];
|
locales: (string | undefined)[];
|
||||||
languages: GetLanguagesQuery["languages"]["data"];
|
languages: AppStaticProps["languages"];
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: AppStaticProps["langui"];
|
||||||
href?: string;
|
href?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,14 +23,18 @@ export default function HorizontalLine(
|
||||||
<p>{langui.language_switch_message}</p>
|
<p>{langui.language_switch_message}</p>
|
||||||
<div className="flex flex-wrap flex-row gap-2">
|
<div className="flex flex-wrap flex-row gap-2">
|
||||||
{locales.map((locale, index) => (
|
{locales.map((locale, index) => (
|
||||||
<Button
|
<>
|
||||||
key={index}
|
{locale && (
|
||||||
active={locale === router.locale}
|
<Button
|
||||||
href={href}
|
key={index}
|
||||||
locale={locale}
|
active={locale === router.locale}
|
||||||
>
|
href={href}
|
||||||
{prettyLanguage(locale, props.languages)}
|
locale={locale}
|
||||||
</Button>
|
>
|
||||||
|
{prettyLanguage(locale, props.languages)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
import {
|
import { GetLibraryItemQuery } from "graphql/generated";
|
||||||
GetLibraryItemQuery,
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
type ContentTOCLineProps = {
|
type ContentTOCLineProps = {
|
||||||
content: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]["contents"]["data"][number];
|
content: Exclude<
|
||||||
|
Exclude<
|
||||||
|
Exclude<
|
||||||
|
GetLibraryItemQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"],
|
||||||
|
null | undefined
|
||||||
|
>["contents"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number];
|
||||||
parentSlug: string;
|
parentSlug: string;
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: AppStaticProps["langui"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ContentTOCLine(
|
export default function ContentTOCLine(
|
||||||
|
@ -20,82 +27,91 @@ export default function ContentTOCLine(
|
||||||
|
|
||||||
const [opened, setOpened] = useState(false);
|
const [opened, setOpened] = useState(false);
|
||||||
|
|
||||||
return (
|
if (content.attributes) {
|
||||||
<div
|
return (
|
||||||
className={`grid gap-2 px-4 rounded-lg ${
|
|
||||||
opened && "bg-mid shadow-inner-sm shadow-shade h-auto py-3 my-2"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="grid gap-4 place-items-center grid-cols-[auto_auto_1fr_auto_12ch] thin:grid-cols-[auto_auto_1fr_auto]">
|
|
||||||
<a>
|
|
||||||
<h3 className="cursor-pointer" onClick={() => setOpened(!opened)}>
|
|
||||||
{content.attributes.content.data &&
|
|
||||||
content.attributes.content.data.attributes.titles.length > 0
|
|
||||||
? prettyinlineTitle(
|
|
||||||
content.attributes.content.data.attributes.titles[0]
|
|
||||||
.pre_title,
|
|
||||||
content.attributes.content.data.attributes.titles[0].title,
|
|
||||||
content.attributes.content.data.attributes.titles[0].subtitle
|
|
||||||
)
|
|
||||||
: prettySlug(content.attributes.slug, props.parentSlug)}
|
|
||||||
</h3>
|
|
||||||
</a>
|
|
||||||
<div className="flex flex-row flex-wrap gap-1">
|
|
||||||
{content.attributes.content.data?.attributes.categories.data.map(
|
|
||||||
(category) => (
|
|
||||||
<Chip key={category.id}>{category.attributes.short}</Chip>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<p className="border-b-2 h-4 w-full border-black border-dotted opacity-30"></p>
|
|
||||||
<p>
|
|
||||||
{content.attributes.range[0].__typename === "ComponentRangePageRange"
|
|
||||||
? content.attributes.range[0].starting_page
|
|
||||||
: ""}
|
|
||||||
</p>
|
|
||||||
{content.attributes.content.data && (
|
|
||||||
<Chip className="justify-self-end thin:hidden">
|
|
||||||
{content.attributes.content.data.attributes.type.data.attributes
|
|
||||||
.titles.length > 0
|
|
||||||
? content.attributes.content.data.attributes.type.data.attributes
|
|
||||||
.titles[0].title
|
|
||||||
: prettySlug(
|
|
||||||
content.attributes.content.data.attributes.type.data
|
|
||||||
.attributes.slug
|
|
||||||
)}
|
|
||||||
</Chip>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
className={`grid-flow-col place-content-start place-items-center gap-2 ${
|
className={`grid gap-2 px-4 rounded-lg ${
|
||||||
opened ? "grid" : "hidden"
|
opened && "bg-mid shadow-inner-sm shadow-shade h-auto py-3 my-2"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span className="material-icons text-dark">
|
<div className="grid gap-4 place-items-center grid-cols-[auto_auto_1fr_auto_12ch] thin:grid-cols-[auto_auto_1fr_auto]">
|
||||||
subdirectory_arrow_right
|
<a>
|
||||||
</span>
|
<h3 className="cursor-pointer" onClick={() => setOpened(!opened)}>
|
||||||
|
{content.attributes.content?.data?.attributes?.titles?.[0]
|
||||||
|
? prettyinlineTitle(
|
||||||
|
content.attributes.content.data.attributes.titles[0]
|
||||||
|
?.pre_title,
|
||||||
|
content.attributes.content.data.attributes.titles[0]?.title,
|
||||||
|
content.attributes.content.data.attributes.titles[0]
|
||||||
|
?.subtitle
|
||||||
|
)
|
||||||
|
: prettySlug(content.attributes.slug, props.parentSlug)}
|
||||||
|
</h3>
|
||||||
|
</a>
|
||||||
|
<div className="flex flex-row flex-wrap gap-1">
|
||||||
|
{content.attributes.content?.data?.attributes?.categories?.data.map(
|
||||||
|
(category) => (
|
||||||
|
<Chip key={category.id}>{category.attributes?.short}</Chip>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p className="border-b-2 h-4 w-full border-black border-dotted opacity-30"></p>
|
||||||
|
<p>
|
||||||
|
{content.attributes.range[0]?.__typename ===
|
||||||
|
"ComponentRangePageRange"
|
||||||
|
? content.attributes.range[0].starting_page
|
||||||
|
: ""}
|
||||||
|
</p>
|
||||||
|
{content.attributes.content?.data?.attributes?.type?.data
|
||||||
|
?.attributes && (
|
||||||
|
<Chip className="justify-self-end thin:hidden">
|
||||||
|
{content.attributes.content.data.attributes.type.data.attributes
|
||||||
|
.titles &&
|
||||||
|
content.attributes.content.data.attributes.type.data.attributes
|
||||||
|
.titles.length > 0
|
||||||
|
? content.attributes.content.data.attributes.type.data
|
||||||
|
.attributes.titles[0]?.title
|
||||||
|
: prettySlug(
|
||||||
|
content.attributes.content.data.attributes.type.data
|
||||||
|
.attributes.slug
|
||||||
|
)}
|
||||||
|
</Chip>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`grid-flow-col place-content-start place-items-center gap-2 ${
|
||||||
|
opened ? "grid" : "hidden"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<span className="material-icons text-dark">
|
||||||
|
subdirectory_arrow_right
|
||||||
|
</span>
|
||||||
|
|
||||||
{content.attributes.scan_set.length > 0 && (
|
{content.attributes.scan_set &&
|
||||||
<Button
|
content.attributes.scan_set.length > 0 && (
|
||||||
href={`/library/${parentSlug}/scans#${content.attributes.slug}`}
|
<Button
|
||||||
>
|
href={`/library/${parentSlug}/scans#${content.attributes.slug}`}
|
||||||
{langui.view_scans}
|
>
|
||||||
</Button>
|
{langui.view_scans}
|
||||||
)}
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
{content.attributes.content.data && (
|
{content.attributes.content?.data && (
|
||||||
<Button
|
<Button
|
||||||
href={`/contents/${content.attributes.content.data.attributes.slug}`}
|
href={`/contents/${content.attributes.content.data.attributes?.slug}`}
|
||||||
>
|
>
|
||||||
{langui.open_content}
|
{langui.open_content}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content.attributes.scan_set.length === 0 &&
|
{content.attributes.scan_set &&
|
||||||
!content.attributes.content.data
|
content.attributes.scan_set.length === 0 &&
|
||||||
? "The content is not available"
|
!content.attributes.content?.data
|
||||||
: ""}
|
? "The content is not available"
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
import Img, { ImageQuality } from "components/Img";
|
import Img, { ImageQuality } from "components/Img";
|
||||||
import { GetContentsQuery } from "graphql/operations-types";
|
import { GetContentsQuery } from "graphql/generated";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { prettySlug } from "queries/helpers";
|
import { prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
export type LibraryContentPreviewProps = {
|
export type LibraryContentPreviewProps = {
|
||||||
item: {
|
item: Exclude<
|
||||||
slug: GetContentsQuery["contents"]["data"][number]["attributes"]["slug"];
|
GetContentsQuery["contents"],
|
||||||
thumbnail: GetContentsQuery["contents"]["data"][number]["attributes"]["thumbnail"];
|
null | undefined
|
||||||
titles: GetContentsQuery["contents"]["data"][number]["attributes"]["titles"];
|
>["data"][number]["attributes"];
|
||||||
categories: GetContentsQuery["contents"]["data"][number]["attributes"]["categories"];
|
|
||||||
type: GetContentsQuery["contents"]["data"][number]["attributes"]["type"];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function LibraryContentPreview(
|
export default function LibraryContentPreview(
|
||||||
|
@ -20,9 +17,9 @@ export default function LibraryContentPreview(
|
||||||
const { item } = props;
|
const { item } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/contents/${item.slug}`} passHref>
|
<Link href={`/contents/${item?.slug}`} passHref>
|
||||||
<div className="drop-shadow-shade-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
|
<div className="drop-shadow-shade-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
|
||||||
{item.thumbnail.data ? (
|
{item?.thumbnail?.data?.attributes ? (
|
||||||
<Img
|
<Img
|
||||||
className="rounded-md coarse:rounded-b-none"
|
className="rounded-md coarse:rounded-b-none"
|
||||||
image={item.thumbnail.data.attributes}
|
image={item.thumbnail.data.attributes}
|
||||||
|
@ -33,29 +30,29 @@ export default function LibraryContentPreview(
|
||||||
)}
|
)}
|
||||||
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute coarse:rounded-b-md bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
|
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute coarse:rounded-b-md bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
|
||||||
<div className="grid grid-flow-col gap-1 overflow-hidden place-content-start">
|
<div className="grid grid-flow-col gap-1 overflow-hidden place-content-start">
|
||||||
{item.type.data && (
|
{item?.type?.data?.attributes && (
|
||||||
<Chip>
|
<Chip>
|
||||||
{item.type.data.attributes.titles.length > 0
|
{item.type.data.attributes.titles?.[0]
|
||||||
? item.type.data.attributes.titles[0].title
|
? item.type.data.attributes.titles[0]?.title
|
||||||
: prettySlug(item.type.data.attributes.slug)}
|
: prettySlug(item.type.data.attributes.slug)}
|
||||||
</Chip>
|
</Chip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{item.titles.length > 0 ? (
|
{item?.titles?.[0] ? (
|
||||||
<>
|
<>
|
||||||
<p>{item.titles[0].pre_title}</p>
|
<p>{item.titles[0].pre_title}</p>
|
||||||
<h1 className="text-lg">{item.titles[0].title}</h1>
|
<h1 className="text-lg">{item.titles[0].title}</h1>
|
||||||
<h2>{item.titles[0].subtitle}</h2>
|
<h2>{item.titles[0].subtitle}</h2>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<h1 className="text-lg">{prettySlug(item.slug)}</h1>
|
<h1 className="text-lg">{prettySlug(item?.slug)}</h1>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start">
|
<div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start">
|
||||||
{item.categories.data.map((category) => (
|
{item?.categories?.data.map((category) => (
|
||||||
<Chip key={category.id} className="text-sm">
|
<Chip key={category.id} className="text-sm">
|
||||||
{category.attributes.short}
|
{category.attributes?.short}
|
||||||
</Chip>
|
</Chip>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,25 +2,31 @@ import Chip from "components/Chip";
|
||||||
import Img, { ImageQuality } from "components/Img";
|
import Img, { ImageQuality } from "components/Img";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import {
|
import {
|
||||||
GetCurrenciesQuery,
|
GetLibraryItemQuery,
|
||||||
GetLibraryItemsPreviewQuery,
|
GetLibraryItemsPreviewQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/generated";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { prettyDate, prettyItemSubType, prettyPrice } from "queries/helpers";
|
import { prettyDate, prettyItemSubType, prettyPrice } from "queries/helpers";
|
||||||
|
|
||||||
export type LibraryItemsPreviewProps = {
|
export type LibraryItemsPreviewProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
item: {
|
item:
|
||||||
slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"];
|
| Exclude<
|
||||||
thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"];
|
Exclude<
|
||||||
title: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["title"];
|
Exclude<
|
||||||
subtitle: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["subtitle"];
|
GetLibraryItemQuery["libraryItems"],
|
||||||
price?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"];
|
null | undefined
|
||||||
categories: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["categories"];
|
>["data"][number]["attributes"],
|
||||||
release_date?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"];
|
null | undefined
|
||||||
metadata?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"];
|
>["subitems"],
|
||||||
};
|
null | undefined
|
||||||
currencies?: GetCurrenciesQuery["currencies"]["data"];
|
>["data"][number]["attributes"]
|
||||||
|
| Exclude<
|
||||||
|
GetLibraryItemsPreviewQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
currencies: AppStaticProps["currencies"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function LibraryItemsPreview(
|
export default function LibraryItemsPreview(
|
||||||
|
@ -30,11 +36,11 @@ export default function LibraryItemsPreview(
|
||||||
const appLayout = useAppLayout();
|
const appLayout = useAppLayout();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/library/${item.slug}`} passHref>
|
<Link href={`/library/${item?.slug}`} passHref>
|
||||||
<div
|
<div
|
||||||
className={`drop-shadow-shade-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
|
className={`drop-shadow-shade-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
|
||||||
>
|
>
|
||||||
{item.thumbnail.data ? (
|
{item?.thumbnail?.data?.attributes ? (
|
||||||
<Img
|
<Img
|
||||||
image={item.thumbnail.data.attributes}
|
image={item.thumbnail.data.attributes}
|
||||||
quality={ImageQuality.Small}
|
quality={ImageQuality.Small}
|
||||||
|
@ -44,26 +50,26 @@ export default function LibraryItemsPreview(
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute place-items-start bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
|
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute place-items-start bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
|
||||||
{item.metadata && item.metadata.length > 0 && (
|
{item?.metadata && item.metadata.length > 0 && item.metadata[0] && (
|
||||||
<div className="flex flex-row gap-1">
|
<div className="flex flex-row gap-1">
|
||||||
<Chip>{prettyItemSubType(item.metadata[0])}</Chip>
|
<Chip>{prettyItemSubType(item.metadata[0])}</Chip>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2 className="mobile:text-sm text-lg leading-5">{item.title}</h2>
|
<h2 className="mobile:text-sm text-lg leading-5">{item?.title}</h2>
|
||||||
<h3 className="mobile:text-xs leading-3">{item.subtitle}</h3>
|
<h3 className="mobile:text-xs leading-3">{item?.subtitle}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:h-0 [scrollbar-width:none] place-content-start">
|
<div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:h-0 [scrollbar-width:none] place-content-start">
|
||||||
{item.categories.data.map((category) => (
|
{item?.categories?.data.map((category) => (
|
||||||
<Chip key={category.id} className="text-sm">
|
<Chip key={category.id} className="text-sm">
|
||||||
{category.attributes.short}
|
{category.attributes?.short}
|
||||||
</Chip>
|
</Chip>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(item.release_date || item.price) && (
|
{(item?.release_date || item?.price) && (
|
||||||
<div className="grid grid-flow-col w-full">
|
<div className="grid grid-flow-col w-full">
|
||||||
{item.release_date && (
|
{item.release_date && (
|
||||||
<p className="mobile:text-xs text-sm">
|
<p className="mobile:text-xs text-sm">
|
||||||
|
@ -73,7 +79,7 @@ export default function LibraryItemsPreview(
|
||||||
{prettyDate(item.release_date)}
|
{prettyDate(item.release_date)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{item.price && props.currencies && (
|
{item.price && (
|
||||||
<p className="mobile:text-xs text-sm justify-self-end">
|
<p className="mobile:text-xs text-sm justify-self-end">
|
||||||
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
||||||
shopping_cart
|
shopping_cart
|
||||||
|
|
|
@ -69,7 +69,7 @@ export type TOC = {
|
||||||
export function getTocFromMarkdawn(text: string, title?: string): TOC {
|
export function getTocFromMarkdawn(text: string, title?: string): TOC {
|
||||||
const toc: TOC = {
|
const toc: TOC = {
|
||||||
title: title ?? "Return to top",
|
title: title ?? "Return to top",
|
||||||
slug: slugify(title) ?? "",
|
slug: slugify(title),
|
||||||
children: [],
|
children: [],
|
||||||
};
|
};
|
||||||
let h2 = -1;
|
let h2 = -1;
|
||||||
|
|
|
@ -1,26 +1,23 @@
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
import Img, { ImageQuality } from "components/Img";
|
import Img, { ImageQuality } from "components/Img";
|
||||||
import { GetPostsPreviewQuery } from "graphql/operations-types";
|
import { GetPostsPreviewQuery } from "graphql/generated";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { prettyDate, prettySlug } from "queries/helpers";
|
import { prettyDate, prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
export type PostPreviewProps = {
|
export type PostPreviewProps = {
|
||||||
post: {
|
post: Exclude<
|
||||||
slug: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["slug"];
|
GetPostsPreviewQuery["posts"],
|
||||||
thumbnail: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["thumbnail"];
|
null | undefined
|
||||||
translations: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["translations"];
|
>["data"][number]["attributes"];
|
||||||
categories: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["categories"];
|
|
||||||
date: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["date"];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function PostPreview(props: PostPreviewProps): JSX.Element {
|
export default function PostPreview(props: PostPreviewProps): JSX.Element {
|
||||||
const { post } = props;
|
const { post } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/news/${post.slug}`} passHref>
|
<Link href={`/news/${post?.slug}`} passHref>
|
||||||
<div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] transition-transform">
|
<div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] transition-transform">
|
||||||
{post.thumbnail.data ? (
|
{post?.thumbnail?.data?.attributes ? (
|
||||||
<Img
|
<Img
|
||||||
className="rounded-md rounded-b-none"
|
className="rounded-md rounded-b-none"
|
||||||
image={post.thumbnail.data.attributes}
|
image={post.thumbnail.data.attributes}
|
||||||
|
@ -30,30 +27,31 @@ export default function PostPreview(props: PostPreviewProps): JSX.Element {
|
||||||
<div className="w-full aspect-[3/2] bg-light rounded-lg"></div>
|
<div className="w-full aspect-[3/2] bg-light rounded-lg"></div>
|
||||||
)}
|
)}
|
||||||
<div className="linearbg-obi fine:drop-shadow-shade-lg rounded-b-md top-full transition-opacity z-20 grid p-4 gap-2">
|
<div className="linearbg-obi fine:drop-shadow-shade-lg rounded-b-md top-full transition-opacity z-20 grid p-4 gap-2">
|
||||||
<div className="grid grid-flow-col w-full">
|
{post?.date && (
|
||||||
{post.date && (
|
<div className="grid grid-flow-col w-full">
|
||||||
<p className="mobile:text-xs text-sm">
|
<p className="mobile:text-xs text-sm">
|
||||||
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
||||||
event
|
event
|
||||||
</span>
|
</span>
|
||||||
{prettyDate(post.date)}
|
{prettyDate(post.date)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{post.translations.length > 0 ? (
|
{post?.translations?.[0] ? (
|
||||||
<>
|
<>
|
||||||
<h1 className="text-xl">{post.translations[0].title}</h1>
|
<h1 className="text-xl">{post.translations[0].title}</h1>
|
||||||
<p>{post.translations[0].excerpt}</p>
|
<p>{post.translations[0].excerpt}</p>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<h1 className="text-lg">{prettySlug(post.slug)}</h1>
|
<h1 className="text-lg">{prettySlug(post?.slug)}</h1>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start">
|
<div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start">
|
||||||
{post.categories.data.map((category) => (
|
{post?.categories?.data.map((category) => (
|
||||||
<Chip key={category.id} className="text-sm">
|
<Chip key={category.id} className="text-sm">
|
||||||
{category.attributes.short}
|
{category.attributes?.short}
|
||||||
</Chip>
|
</Chip>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,8 +5,8 @@ import { MouseEventHandler } from "react";
|
||||||
type NavOptionProps = {
|
type NavOptionProps = {
|
||||||
url: string;
|
url: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
title: string;
|
title: string | null | undefined;
|
||||||
subtitle?: string;
|
subtitle?: string | null | undefined;
|
||||||
border?: boolean;
|
border?: boolean;
|
||||||
reduced?: boolean;
|
reduced?: boolean;
|
||||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||||
|
|
|
@ -2,8 +2,8 @@ import HorizontalLine from "components/HorizontalLine";
|
||||||
|
|
||||||
type PanelHeaderProps = {
|
type PanelHeaderProps = {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
title: string;
|
title: string | null | undefined;
|
||||||
description?: string;
|
description?: string | null | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function PanelHeader(props: PanelHeaderProps): JSX.Element {
|
export default function PanelHeader(props: PanelHeaderProps): JSX.Element {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import HorizontalLine from "components/HorizontalLine";
|
import HorizontalLine from "components/HorizontalLine";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
|
||||||
type ReturnButtonProps = {
|
type ReturnButtonProps = {
|
||||||
href: string;
|
href: string;
|
||||||
title: string;
|
title: string | null | undefined;
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: AppStaticProps["langui"];
|
||||||
displayOn: ReturnButtonType;
|
displayOn: ReturnButtonType;
|
||||||
horizontalLine?: boolean;
|
horizontalLine?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
|
@ -3,14 +3,14 @@ import HorizontalLine from "components/HorizontalLine";
|
||||||
import NavOption from "components/PanelComponents/NavOption";
|
import NavOption from "components/PanelComponents/NavOption";
|
||||||
import ToolTip from "components/ToolTip";
|
import ToolTip from "components/ToolTip";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
|
||||||
import { useMediaDesktop } from "hooks/useMediaQuery";
|
import { useMediaDesktop } from "hooks/useMediaQuery";
|
||||||
import Markdown from "markdown-to-jsx";
|
import Markdown from "markdown-to-jsx";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
|
||||||
type MainPanelProps = {
|
type MainPanelProps = {
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: AppStaticProps["langui"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MainPanel(props: MainPanelProps): JSX.Element {
|
export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
|
|
|
@ -1,68 +1,67 @@
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
import {
|
import { RecorderChipFragment } from "graphql/generated";
|
||||||
GetContentTextQuery,
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
import Img, { ImageQuality } from "./Img";
|
import Img, { ImageQuality } from "./Img";
|
||||||
import ToolTip from "./ToolTip";
|
import ToolTip from "./ToolTip";
|
||||||
|
|
||||||
type RecorderChipProps = {
|
type RecorderChipProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
recorder: GetContentTextQuery["contents"]["data"][number]["attributes"]["text_set"][number]["transcribers"]["data"][number];
|
recorder: RecorderChipFragment;
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: AppStaticProps["langui"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RecorderChip(props: RecorderChipProps): JSX.Element {
|
export default function RecorderChip(props: RecorderChipProps): JSX.Element {
|
||||||
const { recorder, langui } = props;
|
const { recorder, langui } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolTip
|
<ToolTip
|
||||||
content={
|
content={
|
||||||
<div className="text-left p-2 py-5 grid gap-8">
|
<div className="text-left p-2 py-5 grid gap-8">
|
||||||
<div className="grid grid-flow-col gap-6 place-items-center place-content-start">
|
<div className="grid grid-flow-col gap-6 place-items-center place-content-start">
|
||||||
{recorder.attributes.avatar.data && (
|
{recorder.avatar?.data?.attributes && (
|
||||||
<Img
|
<Img
|
||||||
className="w-20 rounded-full border-4 border-mid"
|
className="w-20 rounded-full border-4 border-mid"
|
||||||
image={recorder.attributes.avatar.data.attributes}
|
image={recorder.avatar?.data.attributes}
|
||||||
quality={ImageQuality.Small}
|
quality={ImageQuality.Small}
|
||||||
rawImg
|
rawImg
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<h3 className=" text-2xl">{recorder.attributes.username}</h3>
|
<h3 className=" text-2xl">{recorder.username}</h3>
|
||||||
{recorder.attributes.languages.data.length > 0 && (
|
{recorder.languages?.data && recorder.languages.data.length > 0 && (
|
||||||
<div className="flex flex-row flex-wrap gap-1">
|
<div className="flex flex-row flex-wrap gap-1">
|
||||||
<p>{langui.languages}:</p>
|
<p>{langui.languages}:</p>
|
||||||
{recorder.attributes.languages.data.map((language) => (
|
{recorder.languages.data.map((language) => (
|
||||||
<Chip key={language.attributes.code}>
|
<>
|
||||||
{language.attributes.code.toUpperCase()}
|
{language.attributes && (
|
||||||
</Chip>
|
<Chip key={language.attributes.code}>
|
||||||
|
{language.attributes.code.toUpperCase()}
|
||||||
|
</Chip>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{recorder.attributes.pronouns && (
|
{recorder.pronouns && (
|
||||||
<div className="flex flex-row flex-wrap gap-1">
|
<div className="flex flex-row flex-wrap gap-1">
|
||||||
<p>{langui.pronouns}:</p>
|
<p>{langui.pronouns}:</p>
|
||||||
<Chip>{recorder.attributes.pronouns}</Chip>
|
<Chip>{recorder.pronouns}</Chip>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{recorder.attributes.bio.length > 0 && (
|
{recorder.bio?.[0] && <p>{recorder.bio[0].bio}</p>}
|
||||||
<p>{recorder.attributes.bio[0].bio}</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Button className="cursor-not-allowed">View profile</Button>
|
<Button className="cursor-not-allowed">View profile</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<Chip key={recorder.id}>
|
<Chip key={recorder.anonymous_code}>
|
||||||
{recorder.attributes.anonymize
|
{recorder.anonymize
|
||||||
? `Recorder#${recorder.attributes.anonymous_code}`
|
? `Recorder#${recorder.anonymous_code}`
|
||||||
: recorder.attributes.username}
|
: recorder.username}
|
||||||
</Chip>
|
</Chip>
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
fragment datePicker on ComponentBasicsDatepicker {
|
||||||
|
year
|
||||||
|
month
|
||||||
|
day
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
fragment pricePicker on ComponentBasicsPrice {
|
||||||
|
amount
|
||||||
|
currency {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
symbol
|
||||||
|
code
|
||||||
|
rate_to_usd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
fragment recorderChip on Recorder {
|
||||||
|
username
|
||||||
|
anonymize
|
||||||
|
anonymous_code
|
||||||
|
pronouns
|
||||||
|
bio(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
bio
|
||||||
|
}
|
||||||
|
languages {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avatar {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
fragment uploadImage on UploadFile {
|
||||||
|
name
|
||||||
|
alternativeText
|
||||||
|
caption
|
||||||
|
width
|
||||||
|
height
|
||||||
|
url
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,178 +0,0 @@
|
||||||
import { readFileSync } from "fs";
|
|
||||||
import {
|
|
||||||
GetChronologyItemsQuery,
|
|
||||||
GetChronologyItemsQueryVariables,
|
|
||||||
GetContentQuery,
|
|
||||||
GetContentQueryVariables,
|
|
||||||
GetContentsQuery,
|
|
||||||
GetContentsQueryVariables,
|
|
||||||
GetContentsSlugsQuery,
|
|
||||||
GetContentsSlugsQueryVariables,
|
|
||||||
GetContentTextQuery,
|
|
||||||
GetContentTextQueryVariables,
|
|
||||||
GetCurrenciesQuery,
|
|
||||||
GetCurrenciesQueryVariables,
|
|
||||||
GetErasQuery,
|
|
||||||
GetErasQueryVariables,
|
|
||||||
GetLanguagesQuery,
|
|
||||||
GetLanguagesQueryVariables,
|
|
||||||
GetLibraryItemQuery,
|
|
||||||
GetLibraryItemQueryVariables,
|
|
||||||
GetLibraryItemScansQuery,
|
|
||||||
GetLibraryItemScansQueryVariables,
|
|
||||||
GetLibraryItemsPreviewQuery,
|
|
||||||
GetLibraryItemsPreviewQueryVariables,
|
|
||||||
GetLibraryItemsSlugsQuery,
|
|
||||||
GetLibraryItemsSlugsQueryVariables,
|
|
||||||
GetPostQuery,
|
|
||||||
GetPostQueryVariables,
|
|
||||||
GetPostsPreviewQuery,
|
|
||||||
GetPostsPreviewQueryVariables,
|
|
||||||
GetPostsSlugsQuery,
|
|
||||||
GetPostsSlugsQueryVariables,
|
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
GetWebsiteInterfaceQueryVariables,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
|
|
||||||
async function graphQL(query: string, variables?: string) {
|
|
||||||
const res = await fetch(`${process.env.URL_GRAPHQL}`, {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
query: query,
|
|
||||||
variables: variables,
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/json",
|
|
||||||
Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return (await res.json()).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getQueryFromOperations(queryName: string): string {
|
|
||||||
const operations = readFileSync("./src/graphql/operation.graphql", "utf8");
|
|
||||||
let startingIndex = -1;
|
|
||||||
let endingIndex = -1;
|
|
||||||
const lines = operations.split("\n");
|
|
||||||
lines.map((line, index) => {
|
|
||||||
if (startingIndex === -1) {
|
|
||||||
if (line.startsWith(`query ${queryName}(`)) startingIndex = index;
|
|
||||||
if (line.startsWith(`query ${queryName} {`)) startingIndex = index;
|
|
||||||
} else if (endingIndex === -1) {
|
|
||||||
if (line.startsWith("query")) endingIndex = index;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return lines.slice(startingIndex, endingIndex).join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getWebsiteInterface(
|
|
||||||
variables: GetWebsiteInterfaceQueryVariables
|
|
||||||
): Promise<GetWebsiteInterfaceQuery> {
|
|
||||||
const query = getQueryFromOperations("getWebsiteInterface");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getEras(
|
|
||||||
variables: GetErasQueryVariables
|
|
||||||
): Promise<GetErasQuery> {
|
|
||||||
const query = getQueryFromOperations("getEras");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getChronologyItems(
|
|
||||||
variables: GetChronologyItemsQueryVariables
|
|
||||||
): Promise<GetChronologyItemsQuery> {
|
|
||||||
const query = getQueryFromOperations("getChronologyItems");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getLibraryItemsPreview(
|
|
||||||
variables: GetLibraryItemsPreviewQueryVariables
|
|
||||||
): Promise<GetLibraryItemsPreviewQuery> {
|
|
||||||
const query = getQueryFromOperations("getLibraryItemsPreview");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getLibraryItemsSlugs(
|
|
||||||
variables: GetLibraryItemsSlugsQueryVariables
|
|
||||||
): Promise<GetLibraryItemsSlugsQuery> {
|
|
||||||
const query = getQueryFromOperations("getLibraryItemsSlugs");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getLibraryItem(
|
|
||||||
variables: GetLibraryItemQueryVariables
|
|
||||||
): Promise<GetLibraryItemQuery> {
|
|
||||||
const query = getQueryFromOperations("getLibraryItem");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getContentsSlugs(
|
|
||||||
variables: GetContentsSlugsQueryVariables
|
|
||||||
): Promise<GetContentsSlugsQuery> {
|
|
||||||
const query = getQueryFromOperations("getContentsSlugs");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getContents(
|
|
||||||
variables: GetContentsQueryVariables
|
|
||||||
): Promise<GetContentsQuery> {
|
|
||||||
const query = getQueryFromOperations("getContents");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getContent(
|
|
||||||
variables: GetContentQueryVariables
|
|
||||||
): Promise<GetContentQuery> {
|
|
||||||
const query = getQueryFromOperations("getContent");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getContentText(
|
|
||||||
variables: GetContentTextQueryVariables
|
|
||||||
): Promise<GetContentTextQuery> {
|
|
||||||
const query = getQueryFromOperations("getContentText");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getCurrencies(
|
|
||||||
variables: GetCurrenciesQueryVariables
|
|
||||||
): Promise<GetCurrenciesQuery> {
|
|
||||||
const query = getQueryFromOperations("getCurrencies");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getLanguages(
|
|
||||||
variables: GetLanguagesQueryVariables
|
|
||||||
): Promise<GetLanguagesQuery> {
|
|
||||||
const query = getQueryFromOperations("getLanguages");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getPost(
|
|
||||||
variables: GetPostQueryVariables
|
|
||||||
): Promise<GetPostQuery> {
|
|
||||||
const query = getQueryFromOperations("getPost");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getPostsSlugs(
|
|
||||||
variables: GetPostsSlugsQueryVariables
|
|
||||||
): Promise<GetPostsSlugsQuery> {
|
|
||||||
const query = getQueryFromOperations("getPostsSlugs");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getPostsPreview(
|
|
||||||
variables: GetPostsPreviewQueryVariables
|
|
||||||
): Promise<GetPostsPreviewQuery> {
|
|
||||||
const query = getQueryFromOperations("getPostsPreview");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getLibraryItemScans(
|
|
||||||
variables: GetLibraryItemScansQueryVariables
|
|
||||||
): Promise<GetLibraryItemScansQuery> {
|
|
||||||
const query = getQueryFromOperations("getLibraryItemScans");
|
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
query getChronologyItems($language_code: String) {
|
||||||
|
chronologyItems(
|
||||||
|
pagination: { limit: -1 }
|
||||||
|
sort: ["year:asc", "month:asc", "day:asc"]
|
||||||
|
) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
year
|
||||||
|
month
|
||||||
|
day
|
||||||
|
displayed_date
|
||||||
|
events {
|
||||||
|
id
|
||||||
|
source {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translations(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
description
|
||||||
|
note
|
||||||
|
status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
query getContent($slug: String, $language_code: String) {
|
||||||
|
contents(filters: { slug: { eq: $slug } }) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
pre_title
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
description
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ranged_contents {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
scan_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
library_item {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
video_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
audio_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
query getContentText($slug: String, $language_code: String) {
|
||||||
|
contents(filters: { slug: { eq: $slug } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
pre_title
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
description
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ranged_contents {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
scan_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
library_item {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_set_languages: text_set {
|
||||||
|
language {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_set(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
status
|
||||||
|
text
|
||||||
|
source_language {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transcribers {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translators {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proofreaders {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notes
|
||||||
|
}
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
query getContents($language_code: String) {
|
||||||
|
contents(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
pre_title
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ranged_contents {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
scan_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
library_item {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
video_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
audio_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
query getContentsSlugs {
|
||||||
|
contents(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
query getCurrencies {
|
||||||
|
currencies {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
symbol
|
||||||
|
rate_to_usd
|
||||||
|
display_decimals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
query getEras($language_code: String) {
|
||||||
|
chronologyEras(sort: "starting_year") {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
starting_year
|
||||||
|
ending_year
|
||||||
|
title(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
title
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
query getLanguages {
|
||||||
|
languages {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
code
|
||||||
|
localized_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,387 @@
|
||||||
|
query getLibraryItem($slug: String, $language_code: String) {
|
||||||
|
libraryItems(filters: { slug: { eq: $slug } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
slug
|
||||||
|
root_item
|
||||||
|
primary
|
||||||
|
digital
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gallery {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_date {
|
||||||
|
...datePicker
|
||||||
|
}
|
||||||
|
price {
|
||||||
|
...pricePicker
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size {
|
||||||
|
width
|
||||||
|
height
|
||||||
|
thickness
|
||||||
|
}
|
||||||
|
descriptions(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
description
|
||||||
|
}
|
||||||
|
metadata {
|
||||||
|
__typename
|
||||||
|
... on ComponentMetadataBooks {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding_type
|
||||||
|
page_count
|
||||||
|
page_order
|
||||||
|
languages {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataVideo {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataGame {
|
||||||
|
platforms {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audio_languages {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sub_languages {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
interface_languages {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataAudio {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataGroup {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subitems_type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subitem_of {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subitems {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
slug
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_date {
|
||||||
|
...datePicker
|
||||||
|
}
|
||||||
|
price {
|
||||||
|
...pricePicker
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadata {
|
||||||
|
__typename
|
||||||
|
... on ComponentMetadataBooks {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: {
|
||||||
|
language: { code: { eq: $language_code } }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataGame {
|
||||||
|
platforms {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataVideo {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: {
|
||||||
|
language: { code: { eq: $language_code } }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataAudio {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: {
|
||||||
|
language: { code: { eq: $language_code } }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataGroup {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: {
|
||||||
|
language: { code: { eq: $language_code } }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subitems_type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: {
|
||||||
|
language: { code: { eq: $language_code } }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
submerchs {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contents(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
range {
|
||||||
|
__typename
|
||||||
|
... on ComponentRangePageRange {
|
||||||
|
starting_page
|
||||||
|
ending_page
|
||||||
|
}
|
||||||
|
... on ComponentRangeTimeRange {
|
||||||
|
starting_time
|
||||||
|
ending_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scan_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
content {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: {
|
||||||
|
language: { code: { eq: $language_code } }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
pre_title
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
}
|
||||||
|
text_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
video_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
audio_set {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
query getLibraryItemScans($slug: String, $language_code: String) {
|
||||||
|
libraryItems(filters: { slug: { eq: $slug } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contents(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
range {
|
||||||
|
__typename
|
||||||
|
... on ComponentRangePageRange {
|
||||||
|
starting_page
|
||||||
|
ending_page
|
||||||
|
}
|
||||||
|
... on ComponentRangeTimeRange {
|
||||||
|
starting_time
|
||||||
|
ending_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scan_set_languages: scan_set {
|
||||||
|
language {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scan_set(
|
||||||
|
filters: {
|
||||||
|
or: [
|
||||||
|
{ language: { code: { eq: "xx" } } }
|
||||||
|
{ language: { code: { eq: $language_code } } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
status
|
||||||
|
source_language {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scanners {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleaners {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typesetters {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notes
|
||||||
|
pages(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
query getLibraryItemsPreview($language_code: String) {
|
||||||
|
libraryItems(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
title
|
||||||
|
subtitle
|
||||||
|
slug
|
||||||
|
root_item
|
||||||
|
primary
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_date {
|
||||||
|
...datePicker
|
||||||
|
}
|
||||||
|
price {
|
||||||
|
...pricePicker
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadata {
|
||||||
|
__typename
|
||||||
|
... on ComponentMetadataBooks {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataGame {
|
||||||
|
platforms {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataVideo {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataAudio {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
... on ComponentMetadataGroup {
|
||||||
|
subtype {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subitems_type {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
titles(
|
||||||
|
filters: { language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
query getLibraryItemsSlugs {
|
||||||
|
libraryItems(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
query getPost($slug: String, $language_code: String) {
|
||||||
|
posts(filters: { slug: { eq: $slug } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
updatedAt
|
||||||
|
date {
|
||||||
|
...datePicker
|
||||||
|
}
|
||||||
|
authors {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
...recorderChip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hidden
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translations_languages: translations {
|
||||||
|
language {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translations(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
status
|
||||||
|
title
|
||||||
|
excerpt
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
query getPostsPreview($language_code: String) {
|
||||||
|
posts(filters: { hidden: { eq: false } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
date {
|
||||||
|
...datePicker
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
translations(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
title
|
||||||
|
excerpt
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
...uploadImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
query getPostsSlugs {
|
||||||
|
posts(filters: { hidden: { eq: false } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
query getWebsiteInterface($language_code: String) {
|
||||||
|
websiteInterfaces(
|
||||||
|
filters: { ui_language: { code: { eq: $language_code } } }
|
||||||
|
) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
library
|
||||||
|
contents
|
||||||
|
wiki
|
||||||
|
chronicles
|
||||||
|
library_short_description
|
||||||
|
contents_short_description
|
||||||
|
wiki_short_description
|
||||||
|
chronicles_short_description
|
||||||
|
news
|
||||||
|
merch
|
||||||
|
gallery
|
||||||
|
archives
|
||||||
|
about_us
|
||||||
|
licensing_notice
|
||||||
|
copyright_notice
|
||||||
|
contents_description
|
||||||
|
type
|
||||||
|
category
|
||||||
|
categories
|
||||||
|
size
|
||||||
|
release_date
|
||||||
|
release_year
|
||||||
|
details
|
||||||
|
price
|
||||||
|
width
|
||||||
|
height
|
||||||
|
thickness
|
||||||
|
subitem
|
||||||
|
subitems
|
||||||
|
subitem_of
|
||||||
|
variant
|
||||||
|
variants
|
||||||
|
variant_of
|
||||||
|
summary
|
||||||
|
audio
|
||||||
|
video
|
||||||
|
textual
|
||||||
|
game
|
||||||
|
other
|
||||||
|
return_to
|
||||||
|
left_to_right
|
||||||
|
right_to_left
|
||||||
|
page
|
||||||
|
pages
|
||||||
|
page_order
|
||||||
|
binding
|
||||||
|
type_information
|
||||||
|
front_matter
|
||||||
|
back_matter
|
||||||
|
open_content
|
||||||
|
read_content
|
||||||
|
watch_content
|
||||||
|
listen_content
|
||||||
|
view_scans
|
||||||
|
paperback
|
||||||
|
hardcover
|
||||||
|
languages
|
||||||
|
select_language
|
||||||
|
language
|
||||||
|
library_description
|
||||||
|
wiki_description
|
||||||
|
chronicles_description
|
||||||
|
news_description
|
||||||
|
merch_description
|
||||||
|
gallery_description
|
||||||
|
archives_description
|
||||||
|
about_us_description
|
||||||
|
page_not_found
|
||||||
|
default_description
|
||||||
|
name
|
||||||
|
show_subitems
|
||||||
|
show_primary_items
|
||||||
|
show_secondary_items
|
||||||
|
no_type
|
||||||
|
no_year
|
||||||
|
order_by
|
||||||
|
group_by
|
||||||
|
select_option_sidebar
|
||||||
|
group
|
||||||
|
settings
|
||||||
|
theme
|
||||||
|
light
|
||||||
|
auto
|
||||||
|
dark
|
||||||
|
font_size
|
||||||
|
player_name
|
||||||
|
currency
|
||||||
|
font
|
||||||
|
calculated
|
||||||
|
status_incomplete
|
||||||
|
status_draft
|
||||||
|
status_review
|
||||||
|
status_done
|
||||||
|
incomplete
|
||||||
|
draft
|
||||||
|
review
|
||||||
|
done
|
||||||
|
status
|
||||||
|
transcribers
|
||||||
|
translators
|
||||||
|
proofreaders
|
||||||
|
transcript_notice
|
||||||
|
translation_notice
|
||||||
|
source_language
|
||||||
|
pronouns
|
||||||
|
no_category
|
||||||
|
item
|
||||||
|
items
|
||||||
|
content
|
||||||
|
result
|
||||||
|
results
|
||||||
|
language_switch_message
|
||||||
|
open_settings
|
||||||
|
change_language
|
||||||
|
open_search
|
||||||
|
chronology
|
||||||
|
accords_handbook
|
||||||
|
legality
|
||||||
|
members
|
||||||
|
sharing_policy
|
||||||
|
contact_us
|
||||||
|
email
|
||||||
|
email_gdpr_notice
|
||||||
|
message
|
||||||
|
send
|
||||||
|
response_invalid_code
|
||||||
|
response_invalid_email
|
||||||
|
response_email_success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
||||||
|
import { GraphQLClient } from "graphql-request";
|
||||||
|
import { getSdk, UploadFile } from "graphql/generated";
|
||||||
|
|
||||||
|
export function getReadySdk() {
|
||||||
|
const client = new GraphQLClient(process.env.URL_GRAPHQL ?? "", {
|
||||||
|
headers: { Authorization: `Bearer ${process.env.ACCESS_TOKEN}` },
|
||||||
|
});
|
||||||
|
return getSdk(client);
|
||||||
|
}
|
|
@ -7,23 +7,27 @@ import ReturnButton, {
|
||||||
} from "components/PanelComponents/ReturnButton";
|
} from "components/PanelComponents/ReturnButton";
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { getPost } from "graphql/operations";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { GetPostQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
interface AccordsHandbookProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
post: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AccordsHandbook(
|
export default function AccordsHandbook(props: Props): JSX.Element {
|
||||||
props: AccordsHandbookProps
|
|
||||||
): JSX.Element {
|
|
||||||
const { langui, post } = props;
|
const { langui, post } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const locales = getLocalesFromLanguages(post.translations_languages);
|
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||||
|
|
||||||
|
const body = post?.translations?.[0]?.body ?? "";
|
||||||
|
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
@ -34,12 +38,7 @@ export default function AccordsHandbook(
|
||||||
title={langui.about_us}
|
title={langui.about_us}
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
{post.translations.length > 0 && post.translations[0].body && (
|
<TOC text={body} title={title} />
|
||||||
<TOC
|
|
||||||
text={post.translations[0].body}
|
|
||||||
title={post.translations[0].title}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ export default function AccordsHandbook(
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
<Markdawn text={post.translations[0].body} />
|
<Markdawn text={body} />
|
||||||
) : (
|
) : (
|
||||||
<LanguageSwitcher
|
<LanguageSwitcher
|
||||||
locales={locales}
|
locales={locales}
|
||||||
|
@ -66,11 +65,7 @@ export default function AccordsHandbook(
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={
|
navTitle={title}
|
||||||
post.translations.length > 0
|
|
||||||
? post.translations[0].title
|
|
||||||
: prettySlug(post.slug)
|
|
||||||
}
|
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -80,16 +75,17 @@ export default function AccordsHandbook(
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: AccordsHandbookProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
const slug = "accords-handbook";
|
const slug = "accords-handbook";
|
||||||
const props: AccordsHandbookProps = {
|
const post = await sdk.getPost({
|
||||||
|
slug: slug,
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!post.posts) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
post: (
|
post: post.posts.data[0].attributes,
|
||||||
await getPost({
|
|
||||||
slug: slug,
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).posts.data[0].attributes,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -8,31 +8,41 @@ import ReturnButton, {
|
||||||
} from "components/PanelComponents/ReturnButton";
|
} from "components/PanelComponents/ReturnButton";
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { getPost } from "graphql/operations";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { GetPostQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
|
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, randomInt } from "queries/helpers";
|
import {
|
||||||
|
getLocalesFromLanguages,
|
||||||
|
prettySlug,
|
||||||
|
randomInt,
|
||||||
|
} from "queries/helpers";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
interface ContactProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
post: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AboutUs(props: ContactProps): JSX.Element {
|
export default function AboutUs(props: Props): JSX.Element {
|
||||||
const { langui, post } = props;
|
const { langui, post } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [formResponse, setFormResponse] = useState("");
|
const [formResponse, setFormResponse] = useState("");
|
||||||
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
|
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
|
||||||
"stale"
|
"stale"
|
||||||
);
|
);
|
||||||
const locales = getLocalesFromLanguages(post.translations_languages);
|
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||||
|
|
||||||
const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
|
const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
|
||||||
const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
|
const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
|
||||||
|
|
||||||
|
const body = post?.translations?.[0]?.body ?? "";
|
||||||
|
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
|
@ -42,12 +52,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
|
||||||
title={langui.about_us}
|
title={langui.about_us}
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
{post.translations.length > 0 && post.translations[0].body && (
|
<TOC text={body} title={title} />
|
||||||
<TOC
|
|
||||||
text={post.translations[0].body}
|
|
||||||
title={post.translations[0].title}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -61,7 +66,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
<Markdawn text={post.translations[0].body} />
|
<Markdawn text={body} />
|
||||||
) : (
|
) : (
|
||||||
<LanguageSwitcher
|
<LanguageSwitcher
|
||||||
locales={locales}
|
locales={locales}
|
||||||
|
@ -110,13 +115,13 @@ export default function AboutUs(props: ContactProps): JSX.Element {
|
||||||
.then((response: ResponseMailProps) => {
|
.then((response: ResponseMailProps) => {
|
||||||
switch (response.code) {
|
switch (response.code) {
|
||||||
case "OKAY":
|
case "OKAY":
|
||||||
setFormResponse(langui.response_email_success);
|
setFormResponse(langui.response_email_success ?? "");
|
||||||
setFormState("completed");
|
setFormState("completed");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "EENVELOPE":
|
case "EENVELOPE":
|
||||||
setFormResponse(langui.response_invalid_email);
|
setFormResponse(langui.response_invalid_email ?? "");
|
||||||
setFormState("stale");
|
setFormState("stale");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -127,7 +132,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setFormResponse(langui.response_invalid_code);
|
setFormResponse(langui.response_invalid_code ?? "");
|
||||||
setFormState("stale");
|
setFormState("stale");
|
||||||
setRandomNumber1(randomInt(0, 10));
|
setRandomNumber1(randomInt(0, 10));
|
||||||
setRandomNumber2(randomInt(0, 10));
|
setRandomNumber2(randomInt(0, 10));
|
||||||
|
@ -194,7 +199,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
value={langui.send}
|
value={langui.send ?? "Send"}
|
||||||
className="w-min !px-6"
|
className="w-min !px-6"
|
||||||
disabled={formState !== "stale"}
|
disabled={formState !== "stale"}
|
||||||
/>
|
/>
|
||||||
|
@ -224,16 +229,17 @@ export default function AboutUs(props: ContactProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: ContactProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
const slug = "contact";
|
const slug = "contact";
|
||||||
const props: ContactProps = {
|
const post = await sdk.getPost({
|
||||||
|
slug: slug,
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!post.posts) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
post: (
|
post: post.posts.data[0].attributes,
|
||||||
await getPost({
|
|
||||||
slug: slug,
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).posts.data[0].attributes,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -5,9 +5,9 @@ import SubPanel from "components/Panels/SubPanel";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
|
||||||
interface AboutUsProps extends AppStaticProps {}
|
interface Props extends AppStaticProps {}
|
||||||
|
|
||||||
export default function AboutUs(props: AboutUsProps): JSX.Element {
|
export default function AboutUs(props: Props): JSX.Element {
|
||||||
const { langui } = props;
|
const { langui } = props;
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
@ -38,8 +38,8 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: AboutUsProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const props: AboutUsProps = {
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -7,21 +7,27 @@ import ReturnButton, {
|
||||||
} from "components/PanelComponents/ReturnButton";
|
} from "components/PanelComponents/ReturnButton";
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { getPost } from "graphql/operations";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { GetPostQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
interface SiteInfoProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
post: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SiteInformation(props: SiteInfoProps): JSX.Element {
|
export default function SiteInformation(props: Props): JSX.Element {
|
||||||
const { langui, post } = props;
|
const { langui, post } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const locales = getLocalesFromLanguages(post.translations_languages);
|
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||||
|
|
||||||
|
const body = post?.translations?.[0]?.body ?? "";
|
||||||
|
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
@ -32,12 +38,7 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
|
||||||
title={langui.about_us}
|
title={langui.about_us}
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
{post.translations.length > 0 && post.translations[0].body && (
|
<TOC text={body} title={title} />
|
||||||
<TOC
|
|
||||||
text={post.translations[0].body}
|
|
||||||
title={post.translations[0].title}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
<Markdawn text={post.translations[0].body} />
|
<Markdawn text={body} />
|
||||||
) : (
|
) : (
|
||||||
<LanguageSwitcher
|
<LanguageSwitcher
|
||||||
locales={locales}
|
locales={locales}
|
||||||
|
@ -64,11 +65,7 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={
|
navTitle={title}
|
||||||
post.translations.length > 0
|
|
||||||
? post.translations[0].title
|
|
||||||
: prettySlug(post.slug)
|
|
||||||
}
|
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -78,16 +75,17 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: SiteInfoProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
const slug = "legality";
|
const slug = "legality";
|
||||||
const props: SiteInfoProps = {
|
const post = await sdk.getPost({
|
||||||
|
slug: slug,
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!post.posts) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
post: (
|
post: post.posts.data[0].attributes,
|
||||||
await getPost({
|
|
||||||
slug: slug,
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).posts.data[0].attributes,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -7,22 +7,27 @@ import ReturnButton, {
|
||||||
} from "components/PanelComponents/ReturnButton";
|
} from "components/PanelComponents/ReturnButton";
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { getPost } from "graphql/operations";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { GetPostQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
interface SharingPolicyProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
post: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
}
|
}
|
||||||
|
export default function SharingPolicy(props: Props): JSX.Element {
|
||||||
export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
|
|
||||||
const { langui, post } = props;
|
const { langui, post } = props;
|
||||||
const locales = getLocalesFromLanguages(post.translations_languages);
|
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
const body = post?.translations?.[0]?.body ?? "";
|
||||||
|
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
|
@ -32,12 +37,7 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
|
||||||
title={langui.about_us}
|
title={langui.about_us}
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
{post.translations.length > 0 && post.translations[0].body && (
|
<TOC text={body} title={title} />
|
||||||
<TOC
|
|
||||||
text={post.translations[0].body}
|
|
||||||
title={post.translations[0].title}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
<Markdawn text={post.translations[0].body} />
|
<Markdawn text={body} />
|
||||||
) : (
|
) : (
|
||||||
<LanguageSwitcher
|
<LanguageSwitcher
|
||||||
locales={locales}
|
locales={locales}
|
||||||
|
@ -64,11 +64,7 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={
|
navTitle={title}
|
||||||
post.translations.length > 0
|
|
||||||
? post.translations[0].title
|
|
||||||
: prettySlug(post.slug)
|
|
||||||
}
|
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -78,16 +74,17 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: SharingPolicyProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
const slug = "sharing-policy";
|
const slug = "sharing-policy";
|
||||||
const props: SharingPolicyProps = {
|
const post = await sdk.getPost({
|
||||||
|
slug: slug,
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!post.posts) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
post: (
|
post: post.posts.data[0].attributes,
|
||||||
await getPost({
|
|
||||||
slug: slug,
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).posts.data[0].attributes,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -64,7 +64,6 @@ export default async function Mail(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse<ResponseMailProps>
|
res: NextApiResponse<ResponseMailProps>
|
||||||
) {
|
) {
|
||||||
console.log(req.body);
|
|
||||||
const body = req.body as RequestProps;
|
const body = req.body as RequestProps;
|
||||||
const { serverRuntimeConfig } = getConfig();
|
const { serverRuntimeConfig } = getConfig();
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import RecorderChip from "components/RecorderChip";
|
import RecorderChip from "components/RecorderChip";
|
||||||
import ToolTip from "components/ToolTip";
|
import ToolTip from "components/ToolTip";
|
||||||
import { getContentsSlugs, getContentText } from "graphql/operations";
|
import { GetContentTextQuery } from "graphql/generated";
|
||||||
import { GetContentTextQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import {
|
||||||
GetStaticPathsContext,
|
GetStaticPathsContext,
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
|
@ -33,15 +33,21 @@ import {
|
||||||
} from "queries/helpers";
|
} from "queries/helpers";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
content: Exclude<
|
||||||
contentId: GetContentTextQuery["contents"]["data"][number]["id"];
|
GetContentTextQuery["contents"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
contentId: Exclude<
|
||||||
|
GetContentTextQuery["contents"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["id"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Content(props: Props): JSX.Element {
|
export default function Content(props: Props): JSX.Element {
|
||||||
useTesting(props);
|
useTesting(props);
|
||||||
const { langui, content, languages } = props;
|
const { langui, content, languages } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const locales = getLocalesFromLanguages(content.text_set_languages);
|
const locales = getLocalesFromLanguages(content?.text_set_languages);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
@ -53,7 +59,7 @@ export default function Content(props: Props): JSX.Element {
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{content.text_set.length > 0 && content.text_set[0].source_language.data && (
|
{content?.text_set?.[0]?.source_language?.data?.attributes && (
|
||||||
<div className="grid gap-5">
|
<div className="grid gap-5">
|
||||||
<h2 className="text-xl">
|
<h2 className="text-xl">
|
||||||
{content.text_set[0].source_language.data.attributes.code ===
|
{content.text_set[0].source_language.data.attributes.code ===
|
||||||
|
@ -91,134 +97,157 @@ export default function Content(props: Props): JSX.Element {
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{content.text_set[0].transcribers.data.length > 0 && (
|
{content.text_set[0].transcribers &&
|
||||||
<div>
|
content.text_set[0].transcribers.data.length > 0 && (
|
||||||
<p className="font-headers">{langui.transcribers}:</p>
|
<div>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<p className="font-headers">{langui.transcribers}:</p>
|
||||||
{content.text_set[0].transcribers.data.map((recorder) => (
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
<RecorderChip
|
{content.text_set[0].transcribers.data.map((recorder) => (
|
||||||
key={recorder.id}
|
<>
|
||||||
langui={langui}
|
{recorder.attributes && (
|
||||||
recorder={recorder}
|
<RecorderChip
|
||||||
/>
|
key={recorder.id}
|
||||||
))}
|
langui={langui}
|
||||||
|
recorder={recorder.attributes}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
|
|
||||||
{content.text_set[0].translators.data.length > 0 && (
|
{content.text_set[0].translators &&
|
||||||
<div>
|
content.text_set[0].translators.data.length > 0 && (
|
||||||
<p className="font-headers">{langui.translators}:</p>
|
<div>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<p className="font-headers">{langui.translators}:</p>
|
||||||
{content.text_set[0].translators.data.map((recorder) => (
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
<RecorderChip
|
{content.text_set[0].translators.data.map((recorder) => (
|
||||||
key={recorder.id}
|
<>
|
||||||
langui={langui}
|
{recorder.attributes && (
|
||||||
recorder={recorder}
|
<RecorderChip
|
||||||
/>
|
key={recorder.id}
|
||||||
))}
|
langui={langui}
|
||||||
|
recorder={recorder.attributes}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
|
|
||||||
{content.text_set[0].proofreaders.data.length > 0 && (
|
{content.text_set[0].proofreaders &&
|
||||||
<div>
|
content.text_set[0].proofreaders.data.length > 0 && (
|
||||||
<p className="font-headers">{langui.proofreaders}:</p>
|
<div>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<p className="font-headers">{langui.proofreaders}:</p>
|
||||||
{content.text_set[0].proofreaders.data.map((recorder) => (
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
<RecorderChip
|
{content.text_set[0].proofreaders.data.map((recorder) => (
|
||||||
key={recorder.id}
|
<>
|
||||||
langui={langui}
|
{recorder.attributes && (
|
||||||
recorder={recorder}
|
<RecorderChip
|
||||||
/>
|
key={recorder.id}
|
||||||
))}
|
langui={langui}
|
||||||
|
recorder={recorder.attributes}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content.text_set.length > 0 && content.text_set[0].text && (
|
{content?.text_set &&
|
||||||
<>
|
content.text_set.length > 0 &&
|
||||||
<HorizontalLine />
|
content.text_set[0]?.text && (
|
||||||
<TOC
|
<>
|
||||||
text={content.text_set[0].text}
|
<HorizontalLine />
|
||||||
title={
|
<TOC
|
||||||
content.titles.length > 0
|
text={content.text_set[0].text}
|
||||||
? prettyinlineTitle(
|
title={
|
||||||
content.titles[0].pre_title,
|
content.titles && content.titles.length > 0 && content.titles[0]
|
||||||
content.titles[0].title,
|
? prettyinlineTitle(
|
||||||
content.titles[0].subtitle
|
content.titles[0].pre_title,
|
||||||
)
|
content.titles[0].title,
|
||||||
: prettySlug(content.slug)
|
content.titles[0].subtitle
|
||||||
}
|
)
|
||||||
/>
|
: prettySlug(content.slug)
|
||||||
</>
|
}
|
||||||
)}
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel>
|
<ContentPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
href={`/contents/${content.slug}`}
|
href={`/contents/${content?.slug}`}
|
||||||
title={langui.content}
|
title={langui.content}
|
||||||
langui={langui}
|
langui={langui}
|
||||||
displayOn={ReturnButtonType.mobile}
|
displayOn={ReturnButtonType.mobile}
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
<div className="grid place-items-center">
|
{content && (
|
||||||
<ThumbnailHeader
|
<div className="grid place-items-center">
|
||||||
thumbnail={content.thumbnail.data?.attributes}
|
<ThumbnailHeader
|
||||||
pre_title={
|
thumbnail={content.thumbnail?.data?.attributes}
|
||||||
content.titles.length > 0 ? content.titles[0].pre_title : undefined
|
pre_title={
|
||||||
}
|
content.titles && content.titles.length > 0
|
||||||
title={
|
? content.titles[0]?.pre_title
|
||||||
content.titles.length > 0
|
: undefined
|
||||||
? content.titles[0].title
|
}
|
||||||
: prettySlug(content.slug)
|
title={
|
||||||
}
|
content.titles && content.titles.length > 0
|
||||||
subtitle={
|
? content.titles[0]?.title
|
||||||
content.titles.length > 0 ? content.titles[0].subtitle : undefined
|
: prettySlug(content.slug)
|
||||||
}
|
}
|
||||||
description={
|
subtitle={
|
||||||
content.titles.length > 0
|
content.titles && content.titles.length > 0
|
||||||
? content.titles[0].description
|
? content.titles[0]?.subtitle
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
type={content.type}
|
description={
|
||||||
categories={content.categories}
|
content.titles && content.titles.length > 0
|
||||||
langui={langui}
|
? content.titles[0]?.description
|
||||||
/>
|
: undefined
|
||||||
|
}
|
||||||
<HorizontalLine />
|
type={content.type}
|
||||||
|
categories={content.categories}
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
langui={langui}
|
||||||
<Markdawn text={content.text_set[0].text} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
<HorizontalLine />
|
||||||
|
|
||||||
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
|
<Markdawn text={content.text_set?.[0]?.text ?? ""} />
|
||||||
|
) : (
|
||||||
|
<LanguageSwitcher
|
||||||
|
locales={locales}
|
||||||
|
languages={props.languages}
|
||||||
|
langui={props.langui}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
let description = "";
|
let description = "";
|
||||||
if (content.type.data) {
|
if (content?.type?.data) {
|
||||||
description += `${langui.type}: `;
|
description += `${langui.type}: `;
|
||||||
if (content.type.data.attributes.titles.length > 0) {
|
|
||||||
description += content.type.data.attributes.titles[0].title;
|
description +=
|
||||||
} else {
|
content.type.data.attributes?.titles?.[0]?.title ??
|
||||||
description += prettySlug(content.type.data.attributes.slug);
|
prettySlug(content.type.data.attributes?.slug);
|
||||||
}
|
|
||||||
description += "\n";
|
description += "\n";
|
||||||
}
|
}
|
||||||
if (content.categories.data.length > 0) {
|
if (content?.categories?.data && content.categories.data.length > 0) {
|
||||||
description += `${langui.categories}: `;
|
description += `${langui.categories}: `;
|
||||||
description += content.categories.data
|
description += content.categories.data
|
||||||
.map((category) => category.attributes.short)
|
.map((category) => category.attributes?.short)
|
||||||
.join(" | ");
|
.join(" | ");
|
||||||
description += "\n";
|
description += "\n";
|
||||||
}
|
}
|
||||||
|
@ -226,15 +255,15 @@ export default function Content(props: Props): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={
|
navTitle={
|
||||||
content.titles.length > 0
|
content?.titles && content.titles.length > 0 && content.titles[0]
|
||||||
? prettyinlineTitle(
|
? prettyinlineTitle(
|
||||||
content.titles[0].pre_title,
|
content.titles[0].pre_title,
|
||||||
content.titles[0].title,
|
content.titles[0].title,
|
||||||
content.titles[0].subtitle
|
content.titles[0].subtitle
|
||||||
)
|
)
|
||||||
: prettySlug(content.slug)
|
: prettySlug(content?.slug)
|
||||||
}
|
}
|
||||||
thumbnail={content.thumbnail.data?.attributes}
|
thumbnail={content?.thumbnail?.data?.attributes ?? undefined}
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
description={description}
|
description={description}
|
||||||
|
@ -246,18 +275,19 @@ export default function Content(props: Props): JSX.Element {
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: Props }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
const slug = context.params?.slug?.toString() ?? "";
|
const slug = context.params?.slug?.toString() ?? "";
|
||||||
const content = (
|
const content = await sdk.getContentText({
|
||||||
await getContentText({
|
slug: slug,
|
||||||
slug: slug,
|
language_code: context.locale ?? "en",
|
||||||
language_code: context.locale ?? "en",
|
});
|
||||||
})
|
|
||||||
).contents.data[0];
|
if (!content.contents || content.contents.data.length === 0)
|
||||||
if (!content) return { notFound: true };
|
return { notFound: true };
|
||||||
const props: Props = {
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
content: content.attributes,
|
content: content.contents.data[0].attributes,
|
||||||
contentId: content.id,
|
contentId: content.contents.data[0].id,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
@ -267,11 +297,13 @@ export async function getStaticProps(
|
||||||
export async function getStaticPaths(
|
export async function getStaticPaths(
|
||||||
context: GetStaticPathsContext
|
context: GetStaticPathsContext
|
||||||
): Promise<GetStaticPathsResult> {
|
): Promise<GetStaticPathsResult> {
|
||||||
const contents = await getContentsSlugs({});
|
const sdk = getReadySdk();
|
||||||
|
const contents = await sdk.getContentsSlugs();
|
||||||
const paths: GetStaticPathsResult["paths"] = [];
|
const paths: GetStaticPathsResult["paths"] = [];
|
||||||
contents.contents.data.map((item) => {
|
contents.contents?.data.map((item) => {
|
||||||
context.locales?.map((local) => {
|
context.locales?.map((local) => {
|
||||||
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
if (item.attributes)
|
||||||
|
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
@ -287,12 +319,12 @@ function useTesting(props: Props) {
|
||||||
const contentURL = `/admin/content-manager/collectionType/api::content.content/${contentId}`;
|
const contentURL = `/admin/content-manager/collectionType/api::content.content/${contentId}`;
|
||||||
|
|
||||||
if (router.locale === "en") {
|
if (router.locale === "en") {
|
||||||
if (content.categories.data.length === 0) {
|
if (content?.categories?.data.length === 0) {
|
||||||
prettyTestError(router, "Missing categories", ["content"], contentURL);
|
prettyTestError(router, "Missing categories", ["content"], contentURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.ranged_contents.data.length === 0) {
|
if (content?.ranged_contents?.data.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Unconnected to any source",
|
"Unconnected to any source",
|
||||||
|
@ -301,7 +333,7 @@ function useTesting(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.text_set.length === 0) {
|
if (content?.text_set?.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Has no textset, nor audioset, nor videoset",
|
"Has no textset, nor audioset, nor videoset",
|
||||||
|
@ -310,7 +342,7 @@ function useTesting(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.text_set.length > 1) {
|
if (content?.text_set && content.text_set.length > 1) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"More than one textset for this language",
|
"More than one textset for this language",
|
||||||
|
@ -319,10 +351,10 @@ function useTesting(props: Props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.text_set.length === 1) {
|
if (content?.text_set?.length === 1) {
|
||||||
const textset = content.text_set[0];
|
const textset = content.text_set[0];
|
||||||
|
|
||||||
if (!textset.text) {
|
if (!textset?.text) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing text",
|
"Missing text",
|
||||||
|
@ -330,16 +362,18 @@ function useTesting(props: Props) {
|
||||||
contentURL
|
contentURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!textset.source_language.data) {
|
if (!textset?.source_language?.data) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing source language",
|
"Missing source language",
|
||||||
["content", "text_set"],
|
["content", "text_set"],
|
||||||
contentURL
|
contentURL
|
||||||
);
|
);
|
||||||
} else if (textset.source_language.data.attributes.code === router.locale) {
|
} else if (
|
||||||
|
textset.source_language.data.attributes?.code === router.locale
|
||||||
|
) {
|
||||||
// This is a transcript
|
// This is a transcript
|
||||||
if (textset.transcribers.data.length === 0) {
|
if (textset.transcribers?.data.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing transcribers attribution",
|
"Missing transcribers attribution",
|
||||||
|
@ -347,7 +381,7 @@ function useTesting(props: Props) {
|
||||||
contentURL
|
contentURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (textset.translators.data.length > 0) {
|
if (textset.translators && textset.translators.data.length > 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Transcripts shouldn't have translators",
|
"Transcripts shouldn't have translators",
|
||||||
|
@ -357,7 +391,7 @@ function useTesting(props: Props) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a translation
|
// This is a translation
|
||||||
if (textset.translators.data.length === 0) {
|
if (textset.translators?.data.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing translators attribution",
|
"Missing translators attribution",
|
||||||
|
@ -365,7 +399,7 @@ function useTesting(props: Props) {
|
||||||
contentURL
|
contentURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (textset.transcribers.data.length > 0) {
|
if (textset.transcribers && textset.transcribers.data.length > 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Translations shouldn't have transcribers",
|
"Translations shouldn't have transcribers",
|
||||||
|
|
|
@ -1,379 +0,0 @@
|
||||||
import AppLayout from "components/AppLayout";
|
|
||||||
import Button from "components/Button";
|
|
||||||
import Chip from "components/Chip";
|
|
||||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
|
|
||||||
import HorizontalLine from "components/HorizontalLine";
|
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import TOC from "components/Markdown/TOC";
|
|
||||||
import ReturnButton, {
|
|
||||||
ReturnButtonType,
|
|
||||||
} from "components/PanelComponents/ReturnButton";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
|
||||||
import RecorderChip from "components/RecorderChip";
|
|
||||||
import ToolTip from "components/ToolTip";
|
|
||||||
import { getContentsSlugs, getContentText } from "graphql/operations";
|
|
||||||
import { GetContentTextQuery } from "graphql/operations-types";
|
|
||||||
import {
|
|
||||||
GetStaticPathsContext,
|
|
||||||
GetStaticPathsResult,
|
|
||||||
GetStaticPropsContext,
|
|
||||||
} from "next";
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
|
||||||
import {
|
|
||||||
getLocalesFromLanguages,
|
|
||||||
getStatusDescription,
|
|
||||||
prettyinlineTitle,
|
|
||||||
prettyLanguage,
|
|
||||||
prettySlug,
|
|
||||||
prettyTestError,
|
|
||||||
prettyTestWarning,
|
|
||||||
} from "queries/helpers";
|
|
||||||
|
|
||||||
interface ContentReadProps extends AppStaticProps {
|
|
||||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
|
||||||
contentId: GetContentTextQuery["contents"]["data"][number]["id"];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|
||||||
useTesting(props);
|
|
||||||
const { langui, content, languages } = props;
|
|
||||||
const router = useRouter();
|
|
||||||
const locales = getLocalesFromLanguages(content.text_set_languages);
|
|
||||||
|
|
||||||
const subPanel = (
|
|
||||||
<SubPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href={`/contents/${content.slug}`}
|
|
||||||
title={"Content"}
|
|
||||||
langui={langui}
|
|
||||||
displayOn={ReturnButtonType.desktop}
|
|
||||||
horizontalLine
|
|
||||||
/>
|
|
||||||
|
|
||||||
{content.text_set.length > 0 && content.text_set[0].source_language.data && (
|
|
||||||
<div className="grid gap-5">
|
|
||||||
<h2 className="text-xl">
|
|
||||||
{content.text_set[0].source_language.data.attributes.code ===
|
|
||||||
router.locale
|
|
||||||
? langui.transcript_notice
|
|
||||||
: langui.translation_notice}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{content.text_set[0].source_language.data.attributes.code !==
|
|
||||||
router.locale && (
|
|
||||||
<div className="grid place-items-center gap-2">
|
|
||||||
<p className="font-headers">{langui.source_language}:</p>
|
|
||||||
<Button
|
|
||||||
href={router.asPath}
|
|
||||||
locale={
|
|
||||||
content.text_set[0].source_language.data.attributes.code
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{prettyLanguage(
|
|
||||||
content.text_set[0].source_language.data.attributes.code,
|
|
||||||
languages
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
|
||||||
<p className="font-headers">{langui.status}:</p>
|
|
||||||
|
|
||||||
<ToolTip
|
|
||||||
content={getStatusDescription(content.text_set[0].status, langui)}
|
|
||||||
maxWidth={"20rem"}
|
|
||||||
>
|
|
||||||
<Chip>{content.text_set[0].status}</Chip>
|
|
||||||
</ToolTip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{content.text_set[0].transcribers.data.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<p className="font-headers">{langui.transcribers}:</p>
|
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
|
||||||
{content.text_set[0].transcribers.data.map((recorder) => (
|
|
||||||
<RecorderChip
|
|
||||||
key={recorder.id}
|
|
||||||
langui={langui}
|
|
||||||
recorder={recorder}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{content.text_set[0].translators.data.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<p className="font-headers">{langui.translators}:</p>
|
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
|
||||||
{content.text_set[0].translators.data.map((recorder) => (
|
|
||||||
<RecorderChip
|
|
||||||
key={recorder.id}
|
|
||||||
langui={langui}
|
|
||||||
recorder={recorder}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{content.text_set[0].proofreaders.data.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<p className="font-headers">{langui.proofreaders}:</p>
|
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
|
||||||
{content.text_set[0].proofreaders.data.map((recorder) => (
|
|
||||||
<RecorderChip
|
|
||||||
key={recorder.id}
|
|
||||||
langui={langui}
|
|
||||||
recorder={recorder}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{content.text_set.length > 0 && content.text_set[0].text && (
|
|
||||||
<>
|
|
||||||
<HorizontalLine />
|
|
||||||
<TOC
|
|
||||||
text={content.text_set[0].text}
|
|
||||||
title={
|
|
||||||
content.titles.length > 0
|
|
||||||
? prettyinlineTitle(
|
|
||||||
content.titles[0].pre_title,
|
|
||||||
content.titles[0].title,
|
|
||||||
content.titles[0].subtitle
|
|
||||||
)
|
|
||||||
: prettySlug(content.slug)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
|
||||||
);
|
|
||||||
const contentPanel = (
|
|
||||||
<ContentPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href={`/contents/${content.slug}`}
|
|
||||||
title={langui.content}
|
|
||||||
langui={langui}
|
|
||||||
displayOn={ReturnButtonType.mobile}
|
|
||||||
className="mb-10"
|
|
||||||
/>
|
|
||||||
<div className="grid place-items-center">
|
|
||||||
<ThumbnailHeader
|
|
||||||
thumbnail={content.thumbnail.data?.attributes}
|
|
||||||
pre_title={
|
|
||||||
content.titles.length > 0 ? content.titles[0].pre_title : undefined
|
|
||||||
}
|
|
||||||
title={
|
|
||||||
content.titles.length > 0
|
|
||||||
? content.titles[0].title
|
|
||||||
: prettySlug(content.slug)
|
|
||||||
}
|
|
||||||
subtitle={
|
|
||||||
content.titles.length > 0 ? content.titles[0].subtitle : undefined
|
|
||||||
}
|
|
||||||
description={
|
|
||||||
content.titles.length > 0
|
|
||||||
? content.titles[0].description
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
type={content.type}
|
|
||||||
categories={content.categories}
|
|
||||||
langui={langui}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<HorizontalLine />
|
|
||||||
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
|
||||||
<Markdawn text={content.text_set[0].text} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</ContentPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
let description = "";
|
|
||||||
if (content.type.data) {
|
|
||||||
description += `${langui.type}: `;
|
|
||||||
if (content.type.data.attributes.titles.length > 0) {
|
|
||||||
description += content.type.data.attributes.titles[0].title;
|
|
||||||
} else {
|
|
||||||
description += prettySlug(content.type.data.attributes.slug);
|
|
||||||
}
|
|
||||||
description += "\n";
|
|
||||||
}
|
|
||||||
if (content.categories.data.length > 0) {
|
|
||||||
description += `${langui.categories}: `;
|
|
||||||
description += content.categories.data
|
|
||||||
.map((category) => category.attributes.short)
|
|
||||||
.join(" | ");
|
|
||||||
description += "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppLayout
|
|
||||||
navTitle="Contents"
|
|
||||||
title={
|
|
||||||
content.titles.length > 0
|
|
||||||
? prettyinlineTitle(
|
|
||||||
content.titles[0].pre_title,
|
|
||||||
content.titles[0].title,
|
|
||||||
content.titles[0].subtitle
|
|
||||||
)
|
|
||||||
: prettySlug(content.slug)
|
|
||||||
}
|
|
||||||
thumbnail={content.thumbnail.data?.attributes}
|
|
||||||
contentPanel={contentPanel}
|
|
||||||
subPanel={subPanel}
|
|
||||||
description={description}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getStaticProps(
|
|
||||||
context: GetStaticPropsContext
|
|
||||||
): Promise<{ notFound: boolean } | { props: ContentReadProps }> {
|
|
||||||
const slug = context.params?.slug?.toString() ?? "";
|
|
||||||
const content = (
|
|
||||||
await getContentText({
|
|
||||||
slug: slug,
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).contents.data[0];
|
|
||||||
if (!content) return { notFound: true };
|
|
||||||
const props: ContentReadProps = {
|
|
||||||
...(await getAppStaticProps(context)),
|
|
||||||
content: content.attributes,
|
|
||||||
contentId: content.id,
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
props: props,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getStaticPaths(
|
|
||||||
context: GetStaticPathsContext
|
|
||||||
): Promise<GetStaticPathsResult> {
|
|
||||||
const contents = await getContentsSlugs({});
|
|
||||||
const paths: GetStaticPathsResult["paths"] = [];
|
|
||||||
contents.contents.data.map((item) => {
|
|
||||||
context.locales?.map((local) => {
|
|
||||||
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
paths,
|
|
||||||
fallback: "blocking",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function useTesting(props: ContentReadProps) {
|
|
||||||
const router = useRouter();
|
|
||||||
const { content, contentId } = props;
|
|
||||||
|
|
||||||
const contentURL = `/admin/content-manager/collectionType/api::content.content/${contentId}`;
|
|
||||||
|
|
||||||
if (router.locale === "en") {
|
|
||||||
if (content.categories.data.length === 0) {
|
|
||||||
prettyTestError(router, "Missing categories", ["content"], contentURL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.ranged_contents.data.length === 0) {
|
|
||||||
prettyTestWarning(
|
|
||||||
router,
|
|
||||||
"Unconnected to any source",
|
|
||||||
["content"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.text_set.length === 0) {
|
|
||||||
prettyTestWarning(
|
|
||||||
router,
|
|
||||||
"Has no textset, nor audioset, nor videoset",
|
|
||||||
["content"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.text_set.length > 1) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"More than one textset for this language",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.text_set.length === 1) {
|
|
||||||
const textset = content.text_set[0];
|
|
||||||
|
|
||||||
if (!textset.text) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"Missing text",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!textset.source_language.data) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"Missing source language",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
} else if (textset.source_language.data.attributes.code === router.locale) {
|
|
||||||
// This is a transcript
|
|
||||||
if (textset.transcribers.data.length === 0) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"Missing transcribers attribution",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (textset.translators.data.length > 0) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"Transcripts shouldn't have translators",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This is a translation
|
|
||||||
if (textset.translators.data.length === 0) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"Missing translators attribution",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (textset.transcribers.data.length > 0) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
"Translations shouldn't have transcribers",
|
|
||||||
["content", "text_set"],
|
|
||||||
contentURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,21 +7,18 @@ import ContentPanel, {
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import Select from "components/Select";
|
import Select from "components/Select";
|
||||||
import { getContents } from "graphql/operations";
|
import { GetContentsQuery } from "graphql/generated";
|
||||||
import {
|
import { getReadySdk } from "graphql/sdk";
|
||||||
GetContentsQuery,
|
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface ContentsProps extends AppStaticProps {
|
interface ContentsProps extends AppStaticProps {
|
||||||
contents: GetContentsQuery["contents"]["data"];
|
contents: Exclude<GetContentsQuery["contents"], null | undefined>["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupContentItems = Map<string, GetContentsQuery["contents"]["data"]>;
|
type GroupContentItems = Map<string, ContentsProps["contents"]>;
|
||||||
|
|
||||||
export default function Contents(props: ContentsProps): JSX.Element {
|
export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
const { langui, contents } = props;
|
const { langui, contents } = props;
|
||||||
|
@ -48,7 +45,7 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
<p className="flex-shrink-0">{langui.group_by}:</p>
|
<p className="flex-shrink-0">{langui.group_by}:</p>
|
||||||
<Select
|
<Select
|
||||||
className="w-full"
|
className="w-full"
|
||||||
options={[langui.category, langui.type]}
|
options={[langui.category ?? "", langui.type ?? ""]}
|
||||||
state={groupingMethod}
|
state={groupingMethod}
|
||||||
setState={setGroupingMethod}
|
setState={setGroupingMethod}
|
||||||
allowEmpty
|
allowEmpty
|
||||||
|
@ -70,8 +67,8 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
{name}
|
{name}
|
||||||
<Chip>{`${items.length} ${
|
<Chip>{`${items.length} ${
|
||||||
items.length <= 1
|
items.length <= 1
|
||||||
? langui.result.toLowerCase()
|
? langui.result?.toLowerCase() ?? ""
|
||||||
: langui.results.toLowerCase()
|
: langui.results?.toLowerCase() ?? ""
|
||||||
}`}</Chip>
|
}`}</Chip>
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
|
@ -80,7 +77,14 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
|
className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
|
||||||
>
|
>
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<LibraryContentPreview key={item.id} item={item.attributes} />
|
<>
|
||||||
|
{item.attributes && (
|
||||||
|
<LibraryContentPreview
|
||||||
|
key={item.id}
|
||||||
|
item={item.attributes}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -102,35 +106,32 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: ContentsProps }> {
|
): Promise<{ notFound: boolean } | { props: ContentsProps }> {
|
||||||
const contents = (
|
const sdk = getReadySdk();
|
||||||
await getContents({
|
const contents = await sdk.getContents({
|
||||||
language_code: context.locale ?? "en",
|
language_code: context.locale ?? "en",
|
||||||
})
|
});
|
||||||
).contents.data;
|
if (!contents.contents) return { notFound: true };
|
||||||
|
contents.contents.data.sort((a, b) => {
|
||||||
contents.sort((a, b) => {
|
const titleA = a.attributes?.titles?.[0]
|
||||||
const titleA =
|
? prettyinlineTitle(
|
||||||
a.attributes.titles.length > 0
|
a.attributes.titles[0].pre_title,
|
||||||
? prettyinlineTitle(
|
a.attributes.titles[0].title,
|
||||||
a.attributes.titles[0].pre_title,
|
a.attributes.titles[0].subtitle
|
||||||
a.attributes.titles[0].title,
|
)
|
||||||
a.attributes.titles[0].subtitle
|
: a.attributes?.slug ?? "";
|
||||||
)
|
const titleB = b.attributes?.titles?.[0]
|
||||||
: a.attributes.slug;
|
? prettyinlineTitle(
|
||||||
const titleB =
|
b.attributes.titles[0].pre_title,
|
||||||
b.attributes.titles.length > 0
|
b.attributes.titles[0].title,
|
||||||
? prettyinlineTitle(
|
b.attributes.titles[0].subtitle
|
||||||
b.attributes.titles[0].pre_title,
|
)
|
||||||
b.attributes.titles[0].title,
|
: b.attributes?.slug ?? "";
|
||||||
b.attributes.titles[0].subtitle
|
|
||||||
)
|
|
||||||
: b.attributes.slug;
|
|
||||||
return titleA.localeCompare(titleB);
|
return titleA.localeCompare(titleB);
|
||||||
});
|
});
|
||||||
|
|
||||||
const props: ContentsProps = {
|
const props: ContentsProps = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
contents: contents,
|
contents: contents.contents.data,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
@ -138,7 +139,7 @@ export async function getStaticProps(
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGroups(
|
function getGroups(
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
|
langui: AppStaticProps["langui"],
|
||||||
groupByType: number,
|
groupByType: number,
|
||||||
items: ContentsProps["contents"]
|
items: ContentsProps["contents"]
|
||||||
): GroupContentItems {
|
): GroupContentItems {
|
||||||
|
@ -165,11 +166,11 @@ function getGroups(
|
||||||
group.set(langui.no_category, []);
|
group.set(langui.no_category, []);
|
||||||
|
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.categories.data.length === 0) {
|
if (item.attributes?.categories?.data.length === 0) {
|
||||||
group.get(langui.no_category)?.push(item);
|
group.get(langui.no_category)?.push(item);
|
||||||
} else {
|
} else {
|
||||||
item.attributes.categories.data.map((category) => {
|
item.attributes?.categories?.data.map((category) => {
|
||||||
group.get(category.attributes.name)?.push(item);
|
group.get(category.attributes?.name)?.push(item);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -180,10 +181,8 @@ function getGroups(
|
||||||
const group: GroupContentItems = new Map();
|
const group: GroupContentItems = new Map();
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
const type =
|
const type =
|
||||||
item.attributes.type.data.attributes.titles.length > 0
|
item.attributes?.type?.data?.attributes?.titles?.[0]?.title ??
|
||||||
? item.attributes.type.data.attributes.titles[0].title
|
prettySlug(item.attributes?.type?.data?.attributes?.slug);
|
||||||
: prettySlug(item.attributes.type.data.attributes.slug);
|
|
||||||
|
|
||||||
if (!group.has(type)) group.set(type, []);
|
if (!group.has(type)) group.set(type, []);
|
||||||
group.get(type)?.push(item);
|
group.get(type)?.push(item);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,22 +2,28 @@ import AppLayout from "components/AppLayout";
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
import LanguageSwitcher from "components/LanguageSwitcher";
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
import Markdawn from "components/Markdown/Markdawn";
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import { getPost } from "graphql/operations";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { GetPostQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
interface HomeProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
post: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home(props: HomeProps): JSX.Element {
|
export default function Home(props: Props): JSX.Element {
|
||||||
const { post } = props;
|
const { post } = props;
|
||||||
const locales = getLocalesFromLanguages(post.translations_languages);
|
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
const body = post?.translations?.[0]?.body ?? "";
|
||||||
|
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||||
|
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel>
|
<ContentPanel>
|
||||||
<div className="grid place-items-center place-content-center w-full gap-5 text-center">
|
<div className="grid place-items-center place-content-center w-full gap-5 text-center">
|
||||||
|
@ -28,7 +34,7 @@ export default function Home(props: HomeProps): JSX.Element {
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
<Markdawn text={post.translations[0].body} />
|
<Markdawn text={body} />
|
||||||
) : (
|
) : (
|
||||||
<LanguageSwitcher
|
<LanguageSwitcher
|
||||||
locales={locales}
|
locales={locales}
|
||||||
|
@ -39,31 +45,22 @@ export default function Home(props: HomeProps): JSX.Element {
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return <AppLayout navTitle={title} contentPanel={contentPanel} {...props} />;
|
||||||
<AppLayout
|
|
||||||
navTitle={
|
|
||||||
post.translations.length > 0
|
|
||||||
? post.translations[0].title
|
|
||||||
: prettySlug(post.slug)
|
|
||||||
}
|
|
||||||
contentPanel={contentPanel}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: HomeProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
|
const sdk = getReadySdk();
|
||||||
const slug = "home";
|
const slug = "home";
|
||||||
const props: HomeProps = {
|
const post = await sdk.getPost({
|
||||||
|
slug: slug,
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!post.posts) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
post: (
|
post: post.posts.data[0].attributes,
|
||||||
await getPost({
|
|
||||||
slug: slug,
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).posts.data[0].attributes,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -15,12 +15,12 @@ import ContentPanel, {
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { getLibraryItem, getLibraryItemsSlugs } from "graphql/operations";
|
|
||||||
import {
|
import {
|
||||||
Enum_Componentmetadatabooks_Binding_Type,
|
Enum_Componentmetadatabooks_Binding_Type,
|
||||||
Enum_Componentmetadatabooks_Page_Order,
|
Enum_Componentmetadatabooks_Page_Order,
|
||||||
GetLibraryItemQuery,
|
GetLibraryItemQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/generated";
|
||||||
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import {
|
||||||
GetStaticPathsContext,
|
GetStaticPathsContext,
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
|
@ -41,22 +41,27 @@ import {
|
||||||
} from "queries/helpers";
|
} from "queries/helpers";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
interface LibrarySlugProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
item: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"];
|
item: Exclude<
|
||||||
itemId: GetLibraryItemQuery["libraryItems"]["data"][number]["id"];
|
GetLibraryItemQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
itemId: Exclude<
|
||||||
|
GetLibraryItemQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["id"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
useTesting(props);
|
useTesting(props);
|
||||||
const { item, langui, currencies } = props;
|
const { item, langui, currencies } = props;
|
||||||
const appLayout = useAppLayout();
|
const appLayout = useAppLayout();
|
||||||
|
|
||||||
const isVariantSet =
|
const isVariantSet =
|
||||||
item.metadata.length > 0 &&
|
item?.metadata?.[0]?.__typename === "ComponentMetadataGroup" &&
|
||||||
item.metadata[0].__typename === "ComponentMetadataGroup" &&
|
item.metadata[0].subtype?.data?.attributes?.slug === "variant-set";
|
||||||
item.metadata[0].subtype.data.attributes.slug === "variant-set";
|
|
||||||
|
|
||||||
sortContent(item.contents);
|
sortContent(item?.contents);
|
||||||
|
|
||||||
const [lightboxOpen, setLightboxOpen] = useState(false);
|
const [lightboxOpen, setLightboxOpen] = useState(false);
|
||||||
const [lightboxImages, setLightboxImages] = useState([""]);
|
const [lightboxImages, setLightboxImages] = useState([""]);
|
||||||
|
@ -80,7 +85,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
onClick={() => appLayout.setSubPanelOpen(false)}
|
onClick={() => appLayout.setSubPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{item.gallery.data.length > 0 && (
|
{item?.gallery && item.gallery.data.length > 0 && (
|
||||||
<NavOption
|
<NavOption
|
||||||
title={langui.gallery}
|
title={langui.gallery}
|
||||||
url="#gallery"
|
url="#gallery"
|
||||||
|
@ -96,7 +101,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
onClick={() => appLayout.setSubPanelOpen(false)}
|
onClick={() => appLayout.setSubPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{item.subitems.data.length > 0 && (
|
{item?.subitems && item.subitems.data.length > 0 && (
|
||||||
<NavOption
|
<NavOption
|
||||||
title={isVariantSet ? langui.variants : langui.subitems}
|
title={isVariantSet ? langui.variants : langui.subitems}
|
||||||
url={isVariantSet ? "#variants" : "#subitems"}
|
url={isVariantSet ? "#variants" : "#subitems"}
|
||||||
|
@ -105,7 +110,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.contents.data.length > 0 && (
|
{item?.contents && item.contents.data.length > 0 && (
|
||||||
<NavOption
|
<NavOption
|
||||||
title={langui.contents}
|
title={langui.contents}
|
||||||
url="#contents"
|
url="#contents"
|
||||||
|
@ -138,17 +143,19 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
<div
|
<div
|
||||||
className="drop-shadow-shade-xl w-full h-[50vh] mobile:h-[60vh] desktop:mb-16 relative cursor-pointer"
|
className="drop-shadow-shade-xl w-full h-[50vh] mobile:h-[60vh] desktop:mb-16 relative cursor-pointer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setLightboxOpen(true);
|
if (item?.thumbnail?.data?.attributes) {
|
||||||
setLightboxImages([
|
setLightboxOpen(true);
|
||||||
getAssetURL(
|
setLightboxImages([
|
||||||
item.thumbnail.data.attributes.url,
|
getAssetURL(
|
||||||
ImageQuality.Large
|
item.thumbnail.data.attributes.url,
|
||||||
),
|
ImageQuality.Large
|
||||||
]);
|
),
|
||||||
setLightboxIndex(0);
|
]);
|
||||||
|
setLightboxIndex(0);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.thumbnail.data ? (
|
{item?.thumbnail?.data?.attributes ? (
|
||||||
<Img
|
<Img
|
||||||
image={item.thumbnail.data.attributes}
|
image={item.thumbnail.data.attributes}
|
||||||
quality={ImageQuality.Large}
|
quality={ImageQuality.Large}
|
||||||
|
@ -163,7 +170,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
|
|
||||||
<InsetBox id="summary" className="grid place-items-center">
|
<InsetBox id="summary" className="grid place-items-center">
|
||||||
<div className="w-[clamp(0px,100%,42rem)] grid place-items-center gap-8">
|
<div className="w-[clamp(0px,100%,42rem)] grid place-items-center gap-8">
|
||||||
{item.subitem_of.data.length > 0 && (
|
{item?.subitem_of?.data[0]?.attributes && (
|
||||||
<div className="grid place-items-center">
|
<div className="grid place-items-center">
|
||||||
<p>{langui.subitem_of}</p>
|
<p>{langui.subitem_of}</p>
|
||||||
<Button
|
<Button
|
||||||
|
@ -178,41 +185,53 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="grid place-items-center">
|
<div className="grid place-items-center">
|
||||||
<h1 className="text-3xl">{item.title}</h1>
|
<h1 className="text-3xl">{item?.title}</h1>
|
||||||
{item.subtitle && <h2 className="text-2xl">{item.subtitle}</h2>}
|
{item?.subtitle && <h2 className="text-2xl">{item.subtitle}</h2>}
|
||||||
</div>
|
</div>
|
||||||
{item.descriptions.length > 0 && (
|
{item?.descriptions?.[0] && (
|
||||||
<p className="text-justify">{item.descriptions[0].description}</p>
|
<p className="text-justify">{item.descriptions[0].description}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</InsetBox>
|
</InsetBox>
|
||||||
|
|
||||||
{item.gallery.data.length > 0 && (
|
{item?.gallery && item.gallery.data.length > 0 && (
|
||||||
<div id="gallery" className="grid place-items-center gap-8 w-full">
|
<div id="gallery" className="grid place-items-center gap-8 w-full">
|
||||||
<h2 className="text-2xl">{langui.gallery}</h2>
|
<h2 className="text-2xl">{langui.gallery}</h2>
|
||||||
<div className="grid w-full gap-8 items-end grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]">
|
<div className="grid w-full gap-8 items-end grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]">
|
||||||
{item.gallery.data.map((galleryItem, index) => (
|
{item.gallery.data.map((galleryItem, index) => (
|
||||||
<div
|
<>
|
||||||
key={galleryItem.id}
|
{galleryItem.attributes && (
|
||||||
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
|
<div
|
||||||
onClick={() => {
|
key={galleryItem.id}
|
||||||
setLightboxOpen(true);
|
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
|
||||||
setLightboxImages(
|
onClick={() => {
|
||||||
item.gallery.data.map((image) =>
|
if (item.gallery?.data) {
|
||||||
getAssetURL(image.attributes.url, ImageQuality.Large)
|
const images: string[] = [];
|
||||||
)
|
item.gallery.data.map((image) => {
|
||||||
);
|
if (image.attributes)
|
||||||
setLightboxIndex(index);
|
images.push(
|
||||||
}}
|
getAssetURL(
|
||||||
>
|
image.attributes.url,
|
||||||
<div className="bg-light absolute inset-0 rounded-lg drop-shadow-shade-md"></div>
|
ImageQuality.Large
|
||||||
<Img
|
)
|
||||||
className="rounded-lg"
|
);
|
||||||
image={galleryItem.attributes}
|
});
|
||||||
layout="fill"
|
setLightboxOpen(true);
|
||||||
objectFit="cover"
|
setLightboxImages(images);
|
||||||
/>
|
setLightboxIndex(index);
|
||||||
</div>
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="bg-light absolute inset-0 rounded-lg drop-shadow-shade-md"></div>
|
||||||
|
<Img
|
||||||
|
className="rounded-lg"
|
||||||
|
image={galleryItem.attributes}
|
||||||
|
layout="fill"
|
||||||
|
objectFit="cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -222,7 +241,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
<div className="w-[clamp(0px,100%,42rem)] grid place-items gap-8">
|
<div className="w-[clamp(0px,100%,42rem)] grid place-items gap-8">
|
||||||
<h2 className="text-2xl text-center">{langui.details}</h2>
|
<h2 className="text-2xl text-center">{langui.details}</h2>
|
||||||
<div className="grid grid-flow-col w-full place-content-between">
|
<div className="grid grid-flow-col w-full place-content-between">
|
||||||
{item.metadata.length > 0 && (
|
{item?.metadata?.[0] && (
|
||||||
<div className="grid place-items-center place-content-start">
|
<div className="grid place-items-center place-content-start">
|
||||||
<h3 className="text-xl">{langui.type}</h3>
|
<h3 className="text-xl">{langui.type}</h3>
|
||||||
<div className="grid grid-flow-col gap-1">
|
<div className="grid grid-flow-col gap-1">
|
||||||
|
@ -233,24 +252,24 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.release_date && (
|
{item?.release_date && (
|
||||||
<div className="grid place-items-center place-content-start">
|
<div className="grid place-items-center place-content-start">
|
||||||
<h3 className="text-xl">{langui.release_date}</h3>
|
<h3 className="text-xl">{langui.release_date}</h3>
|
||||||
<p>{prettyDate(item.release_date)}</p>
|
<p>{prettyDate(item.release_date)}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.price && (
|
{item?.price && (
|
||||||
<div className="grid place-items-center text-center place-content-start">
|
<div className="grid place-items-center text-center place-content-start">
|
||||||
<h3 className="text-xl">{langui.price}</h3>
|
<h3 className="text-xl">{langui.price}</h3>
|
||||||
<p>
|
<p>
|
||||||
{prettyPrice(
|
{prettyPrice(
|
||||||
item.price,
|
item.price,
|
||||||
currencies,
|
currencies,
|
||||||
item.price.currency.data.attributes.code
|
item.price.currency?.data?.attributes?.code
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
{item.price.currency.data.attributes.code !==
|
{item.price.currency?.data?.attributes?.code !==
|
||||||
appLayout.currency && (
|
appLayout.currency && (
|
||||||
<p>
|
<p>
|
||||||
{prettyPrice(item.price, currencies, appLayout.currency)}{" "}
|
{prettyPrice(item.price, currencies, appLayout.currency)}{" "}
|
||||||
|
@ -261,18 +280,18 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{item.categories.data.length > 0 && (
|
{item?.categories && item.categories.data.length > 0 && (
|
||||||
<div className="flex flex-col place-items-center gap-2">
|
<div className="flex flex-col place-items-center gap-2">
|
||||||
<h3 className="text-xl">{langui.categories}</h3>
|
<h3 className="text-xl">{langui.categories}</h3>
|
||||||
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||||
{item.categories.data.map((category) => (
|
{item.categories.data.map((category) => (
|
||||||
<Chip key={category.id}>{category.attributes.name}</Chip>
|
<Chip key={category.id}>{category.attributes?.name}</Chip>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.size && (
|
{item?.size && (
|
||||||
<>
|
<>
|
||||||
<h3 className="text-xl">{langui.size}</h3>
|
<h3 className="text-xl">{langui.size}</h3>
|
||||||
<div className="grid grid-flow-col w-full place-content-between">
|
<div className="grid grid-flow-col w-full place-content-between">
|
||||||
|
@ -303,13 +322,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.metadata.length > 0 &&
|
{item?.metadata?.[0]?.__typename !== "ComponentMetadataGroup" &&
|
||||||
item.metadata[0].__typename !== "ComponentMetadataGroup" &&
|
item?.metadata?.[0]?.__typename !== "ComponentMetadataOther" && (
|
||||||
item.metadata[0].__typename !== "ComponentMetadataOther" && (
|
|
||||||
<>
|
<>
|
||||||
<h3 className="text-xl">{langui.type_information}</h3>
|
<h3 className="text-xl">{langui.type_information}</h3>
|
||||||
<div className="grid grid-cols-2 w-full place-content-between">
|
<div className="grid grid-cols-2 w-full place-content-between">
|
||||||
{item.metadata[0].__typename ===
|
{item?.metadata?.[0]?.__typename ===
|
||||||
"ComponentMetadataBooks" && (
|
"ComponentMetadataBooks" && (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-row place-content-start gap-4">
|
<div className="flex flex-row place-content-start gap-4">
|
||||||
|
@ -336,18 +354,15 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
{item.metadata[0].page_order ===
|
{item.metadata[0].page_order ===
|
||||||
Enum_Componentmetadatabooks_Page_Order.LeftToRight
|
Enum_Componentmetadatabooks_Page_Order.LeftToRight
|
||||||
? langui.left_to_right
|
? langui.left_to_right
|
||||||
: item.metadata[0].page_order ===
|
: langui.right_to_left}
|
||||||
Enum_Componentmetadatabooks_Page_Order.RightToLeft
|
|
||||||
? langui.right_to_left
|
|
||||||
: ""}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row place-content-start gap-4">
|
<div className="flex flex-row place-content-start gap-4">
|
||||||
<p className="font-bold">{langui.languages}:</p>
|
<p className="font-bold">{langui.languages}:</p>
|
||||||
{item.metadata[0].languages.data.map((lang) => (
|
{item.metadata[0]?.languages?.data.map((lang) => (
|
||||||
<p key={lang.attributes.code}>
|
<p key={lang.attributes?.code}>
|
||||||
{lang.attributes.name}
|
{lang.attributes?.name}
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -359,7 +374,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</InsetBox>
|
</InsetBox>
|
||||||
|
|
||||||
{item.subitems.data.length > 0 && (
|
{item?.subitems && item.subitems.data.length > 0 && (
|
||||||
<div
|
<div
|
||||||
id={isVariantSet ? "variants" : "subitems"}
|
id={isVariantSet ? "variants" : "subitems"}
|
||||||
className="grid place-items-center gap-8 w-full"
|
className="grid place-items-center gap-8 w-full"
|
||||||
|
@ -372,13 +387,14 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
<LibraryItemsPreview
|
<LibraryItemsPreview
|
||||||
key={subitem.id}
|
key={subitem.id}
|
||||||
item={subitem.attributes}
|
item={subitem.attributes}
|
||||||
|
currencies={props.currencies}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.contents.data.length > 0 && (
|
{item?.contents && item.contents.data.length > 0 && (
|
||||||
<div id="contents" className="w-full grid place-items-center gap-8">
|
<div id="contents" className="w-full grid place-items-center gap-8">
|
||||||
<h2 className="text-2xl">{langui.contents}</h2>
|
<h2 className="text-2xl">{langui.contents}</h2>
|
||||||
<div className="grid gap-4 w-full">
|
<div className="grid gap-4 w-full">
|
||||||
|
@ -399,15 +415,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={prettyinlineTitle("", item.title, item.subtitle)}
|
navTitle={prettyinlineTitle("", item?.title, item?.subtitle)}
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
thumbnail={item.thumbnail.data?.attributes}
|
thumbnail={item?.thumbnail?.data?.attributes ?? undefined}
|
||||||
description={
|
description={item?.descriptions?.[0]?.description ?? undefined}
|
||||||
item.descriptions.length > 0
|
|
||||||
? item.descriptions[0].description
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -415,18 +427,17 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: LibrarySlugProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const item = (
|
const sdk = getReadySdk();
|
||||||
await getLibraryItem({
|
const item = await sdk.getLibraryItem({
|
||||||
slug: context.params?.slug?.toString() ?? "",
|
slug: context.params?.slug ? context.params.slug.toString() : "",
|
||||||
language_code: context.locale ?? "en",
|
language_code: context.locale ?? "en",
|
||||||
})
|
});
|
||||||
).libraryItems.data[0];
|
if (!item.libraryItems) return { notFound: true };
|
||||||
if (!item) return { notFound: true };
|
const props: Props = {
|
||||||
const props: LibrarySlugProps = {
|
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
item: item.attributes,
|
item: item.libraryItems.data[0].attributes,
|
||||||
itemId: item.id,
|
itemId: item.libraryItems.data[0].id,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
@ -436,29 +447,32 @@ export async function getStaticProps(
|
||||||
export async function getStaticPaths(
|
export async function getStaticPaths(
|
||||||
context: GetStaticPathsContext
|
context: GetStaticPathsContext
|
||||||
): Promise<GetStaticPathsResult> {
|
): Promise<GetStaticPathsResult> {
|
||||||
const libraryItems = await getLibraryItemsSlugs({});
|
const sdk = getReadySdk();
|
||||||
|
const libraryItems = await sdk.getLibraryItemsSlugs();
|
||||||
const paths: GetStaticPathsResult["paths"] = [];
|
const paths: GetStaticPathsResult["paths"] = [];
|
||||||
libraryItems.libraryItems.data.map((item) => {
|
if (libraryItems.libraryItems) {
|
||||||
context.locales?.map((local) => {
|
libraryItems.libraryItems.data.map((item) => {
|
||||||
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
context.locales?.map((local) => {
|
||||||
|
paths.push({ params: { slug: item.attributes?.slug }, locale: local });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
return {
|
return {
|
||||||
paths,
|
paths,
|
||||||
fallback: "blocking",
|
fallback: "blocking",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function useTesting(props: LibrarySlugProps) {
|
function useTesting(props: Props) {
|
||||||
const { item, itemId } = props;
|
const { item, itemId } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const libraryItemURL = `/admin/content-manager/collectionType/api::library-item.library-item/${itemId}`;
|
const libraryItemURL = `/admin/content-manager/collectionType/api::library-item.library-item/${itemId}`;
|
||||||
|
|
||||||
sortContent(item.contents);
|
sortContent(item?.contents);
|
||||||
|
|
||||||
if (router.locale === "en") {
|
if (router.locale === "en") {
|
||||||
if (!item.thumbnail.data) {
|
if (!item?.thumbnail?.data) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing thumbnail",
|
"Missing thumbnail",
|
||||||
|
@ -466,7 +480,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (item.metadata.length === 0) {
|
if (item?.metadata?.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing metadata",
|
"Missing metadata",
|
||||||
|
@ -474,9 +488,9 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
item.metadata[0].__typename === "ComponentMetadataGroup" &&
|
item?.metadata?.[0]?.__typename === "ComponentMetadataGroup" &&
|
||||||
(item.metadata[0].subtype.data.attributes.slug === "relation-set" ||
|
(item.metadata[0].subtype?.data?.attributes?.slug === "relation-set" ||
|
||||||
item.metadata[0].subtype.data.attributes.slug === "variant-set")
|
item.metadata[0].subtype?.data?.attributes?.slug === "variant-set")
|
||||||
) {
|
) {
|
||||||
// This is a group type item
|
// This is a group type item
|
||||||
if (item.price) {
|
if (item.price) {
|
||||||
|
@ -503,7 +517,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (item.contents.data.length > 0) {
|
if (item.contents && item.contents.data.length > 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Group-type items shouldn't have contents",
|
"Group-type items shouldn't have contents",
|
||||||
|
@ -511,7 +525,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (item.subitems.data.length === 0) {
|
if (item.subitems && item.subitems.data.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Group-type items should have subitems",
|
"Group-type items should have subitems",
|
||||||
|
@ -522,8 +536,8 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
} else {
|
} else {
|
||||||
// This is a normal item
|
// This is a normal item
|
||||||
|
|
||||||
if (item.metadata[0].__typename === "ComponentMetadataGroup") {
|
if (item?.metadata?.[0]?.__typename === "ComponentMetadataGroup") {
|
||||||
if (item.subitems.data.length === 0) {
|
if (item.subitems?.data.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Group-type item should have subitems",
|
"Group-type item should have subitems",
|
||||||
|
@ -533,7 +547,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.price) {
|
if (item?.price) {
|
||||||
if (!item.price.amount) {
|
if (!item.price.amount) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
|
@ -559,8 +573,8 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.digital) {
|
if (!item?.digital) {
|
||||||
if (item.size) {
|
if (item?.size) {
|
||||||
if (!item.size.width) {
|
if (!item.size.width) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
|
@ -595,7 +609,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.release_date) {
|
if (item?.release_date) {
|
||||||
if (!item.release_date.year) {
|
if (!item.release_date.year) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
|
@ -629,7 +643,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.contents.data.length === 0) {
|
if (item?.contents?.data.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing contents",
|
"Missing contents",
|
||||||
|
@ -638,26 +652,27 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let currentRangePage = 0;
|
let currentRangePage = 0;
|
||||||
item.contents.data.map((content) => {
|
item?.contents?.data.map((content) => {
|
||||||
const contentURL = `/admin/content-manager/collectionType/api::content.content/${content.id}`;
|
const contentURL = `/admin/content-manager/collectionType/api::content.content/${content.id}`;
|
||||||
|
|
||||||
if (content.attributes.scan_set.length === 0) {
|
if (content.attributes?.scan_set?.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing scan_set",
|
"Missing scan_set",
|
||||||
["libraryItem", "content", content.id],
|
["libraryItem", "content", content.id ?? ""],
|
||||||
contentURL
|
contentURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (content.attributes.range.length === 0) {
|
if (content.attributes?.range.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing range",
|
"Missing range",
|
||||||
["libraryItem", "content", content.id],
|
["libraryItem", "content", content.id ?? ""],
|
||||||
contentURL
|
contentURL
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
content.attributes.range[0].__typename === "ComponentRangePageRange"
|
content.attributes?.range[0]?.__typename ===
|
||||||
|
"ComponentRangePageRange"
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
content.attributes.range[0].starting_page <
|
content.attributes.range[0].starting_page <
|
||||||
|
@ -666,7 +681,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
`Overlapping pages ${content.attributes.range[0].starting_page} to ${currentRangePage}`,
|
`Overlapping pages ${content.attributes.range[0].starting_page} to ${currentRangePage}`,
|
||||||
["libraryItem", "content", content.id, "range"],
|
["libraryItem", "content", content.id ?? "", "range"],
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -678,16 +693,16 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
`Missing pages ${currentRangePage + 1} to ${
|
`Missing pages ${currentRangePage + 1} to ${
|
||||||
content.attributes.range[0].starting_page - 1
|
content.attributes.range[0].starting_page - 1
|
||||||
}`,
|
}`,
|
||||||
["libraryItem", "content", content.id, "range"],
|
["libraryItem", "content", content.id ?? "", "range"],
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!content.attributes.content.data) {
|
if (!content.attributes.content?.data) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing content",
|
"Missing content",
|
||||||
["libraryItem", "content", content.id, "range"],
|
["libraryItem", "content", content.id ?? "", "range"],
|
||||||
libraryItemURL
|
libraryItemURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -696,26 +711,8 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (item.metadata[0].__typename === "ComponentMetadataBooks") {
|
if (item?.metadata?.[0]?.__typename === "ComponentMetadataBooks") {
|
||||||
if (currentRangePage < item.metadata[0].page_count) {
|
if (item.metadata[0].languages?.data.length === 0) {
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
`Missing pages ${currentRangePage + 1} to ${
|
|
||||||
item.metadata[0].page_count
|
|
||||||
}`,
|
|
||||||
["libraryItem", "content"],
|
|
||||||
libraryItemURL
|
|
||||||
);
|
|
||||||
} else if (currentRangePage > item.metadata[0].page_count) {
|
|
||||||
prettyTestError(
|
|
||||||
router,
|
|
||||||
`Page overflow, content references pages up to ${currentRangePage} when the highest expected was ${item.metadata[0].page_count}`,
|
|
||||||
["libraryItem", "content"],
|
|
||||||
libraryItemURL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.metadata[0].languages.data.length === 0) {
|
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing language",
|
"Missing language",
|
||||||
|
@ -724,7 +721,25 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.metadata[0].page_count) {
|
if (item.metadata[0].page_count) {
|
||||||
|
if (currentRangePage < item.metadata[0].page_count) {
|
||||||
|
prettyTestError(
|
||||||
|
router,
|
||||||
|
`Missing pages ${currentRangePage + 1} to ${
|
||||||
|
item.metadata[0].page_count
|
||||||
|
}`,
|
||||||
|
["libraryItem", "content"],
|
||||||
|
libraryItemURL
|
||||||
|
);
|
||||||
|
} else if (currentRangePage > item.metadata[0].page_count) {
|
||||||
|
prettyTestError(
|
||||||
|
router,
|
||||||
|
`Page overflow, content references pages up to ${currentRangePage} when the highest expected was ${item.metadata[0].page_count}`,
|
||||||
|
["libraryItem", "content"],
|
||||||
|
libraryItemURL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing page_count",
|
"Missing page_count",
|
||||||
|
@ -736,7 +751,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.root_item && item.subitem_of.data.length === 0) {
|
if (!item?.root_item && item?.subitem_of?.data.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"This item is inaccessible (not root item and not subitem of another item)",
|
"This item is inaccessible (not root item and not subitem of another item)",
|
||||||
|
@ -745,7 +760,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.gallery.data.length === 0) {
|
if (item?.gallery?.data.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing gallery",
|
"Missing gallery",
|
||||||
|
@ -755,7 +770,7 @@ function useTesting(props: LibrarySlugProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.descriptions.length === 0) {
|
if (item?.descriptions?.length === 0) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"Missing description",
|
"Missing description",
|
||||||
|
|
|
@ -11,8 +11,8 @@ import ContentPanel, {
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { getLibraryItemScans, getLibraryItemsSlugs } from "graphql/operations";
|
import { GetLibraryItemScansQuery } from "graphql/generated";
|
||||||
import { GetLibraryItemScansQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import {
|
||||||
GetStaticPathsContext,
|
GetStaticPathsContext,
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
|
@ -23,15 +23,21 @@ import { prettyinlineTitle, prettySlug, sortContent } from "queries/helpers";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
item: GetLibraryItemScansQuery["libraryItems"]["data"][number]["attributes"];
|
item: Exclude<
|
||||||
itemId: GetLibraryItemScansQuery["libraryItems"]["data"][number]["id"];
|
GetLibraryItemScansQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
itemId: Exclude<
|
||||||
|
GetLibraryItemScansQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["id"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LibrarySlug(props: Props): JSX.Element {
|
export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
const { item, langui } = props;
|
const { item, langui } = props;
|
||||||
const appLayout = useAppLayout();
|
const appLayout = useAppLayout();
|
||||||
|
|
||||||
sortContent(item.contents);
|
sortContent(item?.contents);
|
||||||
|
|
||||||
const [lightboxOpen, setLightboxOpen] = useState(false);
|
const [lightboxOpen, setLightboxOpen] = useState(false);
|
||||||
const [lightboxImages, setLightboxImages] = useState([""]);
|
const [lightboxImages, setLightboxImages] = useState([""]);
|
||||||
|
@ -40,21 +46,21 @@ export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
href={`/library/${item.slug}`}
|
href={`/library/${item?.slug}`}
|
||||||
title={langui.item}
|
title={langui.item}
|
||||||
langui={langui}
|
langui={langui}
|
||||||
displayOn={ReturnButtonType.desktop}
|
displayOn={ReturnButtonType.desktop}
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{item.contents.data.map((content) => (
|
{item?.contents?.data.map((content) => (
|
||||||
<NavOption
|
<NavOption
|
||||||
key={content.id}
|
key={content.id}
|
||||||
url={`#${content.attributes.slug}`}
|
url={`#${content.attributes?.slug}`}
|
||||||
title={prettySlug(content.attributes.slug, item.slug)}
|
title={prettySlug(content.attributes?.slug, item.slug)}
|
||||||
subtitle={
|
subtitle={
|
||||||
content.attributes.range.length > 0 &&
|
content.attributes?.range[0]?.__typename ===
|
||||||
content.attributes.range[0].__typename === "ComponentRangePageRange"
|
"ComponentRangePageRange"
|
||||||
? `${content.attributes.range[0].starting_page} → ${content.attributes.range[0].ending_page}`
|
? `${content.attributes.range[0].starting_page} → ${content.attributes.range[0].ending_page}`
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
@ -76,55 +82,68 @@ export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
href={`/library/${item.slug}`}
|
href={`/library/${item?.slug}`}
|
||||||
title={langui.item}
|
title={langui.item}
|
||||||
langui={langui}
|
langui={langui}
|
||||||
displayOn={ReturnButtonType.mobile}
|
displayOn={ReturnButtonType.mobile}
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
{item.contents.data.map((content) => (
|
{item?.contents?.data.map((content) => (
|
||||||
<>
|
<>
|
||||||
<h2
|
<h2
|
||||||
id={content.attributes.slug}
|
id={content.attributes?.slug}
|
||||||
key={`h2${content.id}`}
|
key={`h2${content.id}`}
|
||||||
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
|
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
|
||||||
>
|
>
|
||||||
{prettySlug(content.attributes.slug, item.slug)}
|
{prettySlug(content.attributes?.slug, item.slug)}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{content.attributes.scan_set.length > 0 ? (
|
{content.attributes?.scan_set?.[0] ? (
|
||||||
<div
|
<div
|
||||||
key={`items${content.id}`}
|
key={`items${content.id}`}
|
||||||
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
||||||
>
|
>
|
||||||
{content.attributes.scan_set[0].pages.data.map((page, index) => (
|
{content.attributes.scan_set[0].pages?.data.map((page, index) => (
|
||||||
<div
|
<div
|
||||||
key={page.id}
|
key={page.id}
|
||||||
className="drop-shadow-shade-lg hover:scale-[1.02] cursor-pointer transition-transform"
|
className="drop-shadow-shade-lg hover:scale-[1.02] cursor-pointer transition-transform"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setLightboxOpen(true);
|
setLightboxOpen(true);
|
||||||
setLightboxImages(
|
if (content.attributes?.scan_set?.[0]?.pages) {
|
||||||
content.attributes.scan_set[0].pages.data.map((image) =>
|
const images: string[] = [];
|
||||||
getAssetURL(image.attributes.url, ImageQuality.Large)
|
content.attributes.scan_set[0].pages.data.map((image) => {
|
||||||
)
|
if (image.attributes?.url)
|
||||||
);
|
images.push(
|
||||||
|
getAssetURL(
|
||||||
|
image.attributes.url,
|
||||||
|
ImageQuality.Large
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
setLightboxImages(images);
|
||||||
|
}
|
||||||
|
|
||||||
setLightboxIndex(index);
|
setLightboxIndex(index);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Img image={page.attributes} quality={ImageQuality.Small} />
|
{page.attributes && (
|
||||||
|
<Img image={page.attributes} quality={ImageQuality.Small} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="pb-12 border-b-[3px] border-dotted last-of-type:border-0">
|
<div className="pb-12 border-b-[3px] border-dotted last-of-type:border-0">
|
||||||
<LanguageSwitcher
|
{content.attributes?.scan_set_languages && (
|
||||||
locales={content.attributes.scan_set_languages.map(
|
<LanguageSwitcher
|
||||||
(language) => language.language.data.attributes.code
|
locales={content.attributes.scan_set_languages.map(
|
||||||
)}
|
(language) => language?.language?.data?.attributes?.code
|
||||||
languages={props.languages}
|
)}
|
||||||
langui={props.langui}
|
languages={props.languages}
|
||||||
href={`#${content.attributes.slug}`}
|
langui={props.langui}
|
||||||
/>
|
href={`#${content.attributes.slug}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -134,10 +153,10 @@ export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={prettyinlineTitle("", item.title, item.subtitle)}
|
navTitle={prettyinlineTitle("", item?.title, item?.subtitle)}
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
thumbnail={item.thumbnail.data?.attributes}
|
thumbnail={item?.thumbnail?.data?.attributes ?? undefined}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -146,17 +165,16 @@ export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: Props }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const item = (
|
const sdk = getReadySdk();
|
||||||
await getLibraryItemScans({
|
const item = await sdk.getLibraryItemScans({
|
||||||
slug: context.params?.slug?.toString() ?? "",
|
slug: context.params?.slug?.toString() ?? "",
|
||||||
language_code: context.locale ?? "en",
|
language_code: context.locale ?? "en",
|
||||||
})
|
});
|
||||||
).libraryItems.data[0];
|
if (!item.libraryItems) return { notFound: true };
|
||||||
if (!item) return { notFound: true };
|
|
||||||
const props: Props = {
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
item: item.attributes,
|
item: item.libraryItems.data[0].attributes,
|
||||||
itemId: item.id,
|
itemId: item.libraryItems.data[0].id,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
@ -166,13 +184,17 @@ export async function getStaticProps(
|
||||||
export async function getStaticPaths(
|
export async function getStaticPaths(
|
||||||
context: GetStaticPathsContext
|
context: GetStaticPathsContext
|
||||||
): Promise<GetStaticPathsResult> {
|
): Promise<GetStaticPathsResult> {
|
||||||
const libraryItems = await getLibraryItemsSlugs({});
|
const sdk = getReadySdk();
|
||||||
|
const libraryItems = await sdk.getLibraryItemsSlugs({});
|
||||||
const paths: GetStaticPathsResult["paths"] = [];
|
const paths: GetStaticPathsResult["paths"] = [];
|
||||||
libraryItems.libraryItems.data.map((item) => {
|
if (libraryItems.libraryItems) {
|
||||||
context.locales?.map((local) => {
|
libraryItems.libraryItems.data.map((item) => {
|
||||||
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
context.locales?.map((local) => {
|
||||||
|
if (item.attributes)
|
||||||
|
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
return {
|
return {
|
||||||
paths,
|
paths,
|
||||||
fallback: "blocking",
|
fallback: "blocking",
|
||||||
|
|
|
@ -8,27 +8,23 @@ import ContentPanel, {
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import Select from "components/Select";
|
import Select from "components/Select";
|
||||||
import Switch from "components/Switch";
|
import Switch from "components/Switch";
|
||||||
import { getLibraryItemsPreview } from "graphql/operations";
|
import { GetLibraryItemsPreviewQuery } from "graphql/generated";
|
||||||
import {
|
import { getReadySdk } from "graphql/sdk";
|
||||||
GetCurrenciesQuery,
|
|
||||||
GetLibraryItemsPreviewQuery,
|
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface LibraryProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
|
items: Exclude<
|
||||||
|
GetLibraryItemsPreviewQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupLibraryItems = Map<
|
type GroupLibraryItems = Map<string, Props["items"]>;
|
||||||
string,
|
|
||||||
GetLibraryItemsPreviewQuery["libraryItems"]["data"]
|
|
||||||
>;
|
|
||||||
|
|
||||||
export default function Library(props: LibraryProps): JSX.Element {
|
export default function Library(props: Props): JSX.Element {
|
||||||
const { langui, items: libraryItems, currencies } = props;
|
const { langui, items: libraryItems, currencies } = props;
|
||||||
|
|
||||||
const [showSubitems, setShowSubitems] = useState<boolean>(false);
|
const [showSubitems, setShowSubitems] = useState<boolean>(false);
|
||||||
|
@ -37,7 +33,7 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
const [sortingMethod, setSortingMethod] = useState<number>(0);
|
const [sortingMethod, setSortingMethod] = useState<number>(0);
|
||||||
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
||||||
|
|
||||||
const [filteredItems, setFilteredItems] = useState<LibraryProps["items"]>(
|
const [filteredItems, setFilteredItems] = useState<Props["items"]>(
|
||||||
filterItems(
|
filterItems(
|
||||||
showSubitems,
|
showSubitems,
|
||||||
showPrimaryItems,
|
showPrimaryItems,
|
||||||
|
@ -46,7 +42,7 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const [sortedItems, setSortedItem] = useState<LibraryProps["items"]>(
|
const [sortedItems, setSortedItem] = useState<Props["items"]>(
|
||||||
sortBy(groupingMethod, filteredItems, currencies)
|
sortBy(groupingMethod, filteredItems, currencies)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -85,7 +81,11 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
<p className="flex-shrink-0">{langui.group_by}:</p>
|
<p className="flex-shrink-0">{langui.group_by}:</p>
|
||||||
<Select
|
<Select
|
||||||
className="w-full"
|
className="w-full"
|
||||||
options={[langui.category, langui.type, langui.release_year]}
|
options={[
|
||||||
|
langui.category ?? "Category",
|
||||||
|
langui.type ?? "Type",
|
||||||
|
langui.release_year ?? "Year",
|
||||||
|
]}
|
||||||
state={groupingMethod}
|
state={groupingMethod}
|
||||||
setState={setGroupingMethod}
|
setState={setGroupingMethod}
|
||||||
allowEmpty
|
allowEmpty
|
||||||
|
@ -96,7 +96,11 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
<p className="flex-shrink-0">{langui.order_by}:</p>
|
<p className="flex-shrink-0">{langui.order_by}:</p>
|
||||||
<Select
|
<Select
|
||||||
className="w-full"
|
className="w-full"
|
||||||
options={[langui.name, langui.price, langui.release_date]}
|
options={[
|
||||||
|
langui.name ?? "Name",
|
||||||
|
langui.price ?? "Price",
|
||||||
|
langui.release_date ?? "Release date",
|
||||||
|
]}
|
||||||
state={sortingMethod}
|
state={sortingMethod}
|
||||||
setState={setSortingMethod}
|
setState={setSortingMethod}
|
||||||
/>
|
/>
|
||||||
|
@ -132,8 +136,8 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
{name}
|
{name}
|
||||||
<Chip>{`${items.length} ${
|
<Chip>{`${items.length} ${
|
||||||
items.length <= 1
|
items.length <= 1
|
||||||
? langui.result.toLowerCase()
|
? langui.result?.toLowerCase() ?? "result"
|
||||||
: langui.results.toLowerCase()
|
: langui.results?.toLowerCase() ?? "results"
|
||||||
}`}</Chip>
|
}`}</Chip>
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
|
@ -167,14 +171,15 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: LibraryProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const props: LibraryProps = {
|
const sdk = getReadySdk();
|
||||||
|
const items = await sdk.getLibraryItemsPreview({
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!items.libraryItems) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
items: (
|
items: items.libraryItems.data,
|
||||||
await getLibraryItemsPreview({
|
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).libraryItems.data,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
@ -182,9 +187,9 @@ export async function getStaticProps(
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGroups(
|
function getGroups(
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
|
langui: AppStaticProps["langui"],
|
||||||
groupByType: number,
|
groupByType: number,
|
||||||
items: LibraryProps["items"]
|
items: Props["items"]
|
||||||
): GroupLibraryItems {
|
): GroupLibraryItems {
|
||||||
switch (groupByType) {
|
switch (groupByType) {
|
||||||
case 0: {
|
case 0: {
|
||||||
|
@ -209,11 +214,11 @@ function getGroups(
|
||||||
typeGroup.set(langui.no_category, []);
|
typeGroup.set(langui.no_category, []);
|
||||||
|
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.categories.data.length === 0) {
|
if (item.attributes?.categories?.data.length === 0) {
|
||||||
typeGroup.get(langui.no_category)?.push(item);
|
typeGroup.get(langui.no_category)?.push(item);
|
||||||
} else {
|
} else {
|
||||||
item.attributes.categories.data.map((category) => {
|
item.attributes?.categories?.data.map((category) => {
|
||||||
typeGroup.get(category.attributes.name)?.push(item);
|
typeGroup.get(category.attributes?.name)?.push(item);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -223,49 +228,50 @@ function getGroups(
|
||||||
|
|
||||||
case 1: {
|
case 1: {
|
||||||
const group: GroupLibraryItems = new Map();
|
const group: GroupLibraryItems = new Map();
|
||||||
group.set(langui.audio, []);
|
group.set(langui.audio ?? "Audio", []);
|
||||||
group.set(langui.game, []);
|
group.set(langui.game ?? "Game", []);
|
||||||
group.set(langui.textual, []);
|
group.set(langui.textual ?? "Textual", []);
|
||||||
group.set(langui.video, []);
|
group.set(langui.video ?? "Video", []);
|
||||||
group.set(langui.other, []);
|
group.set(langui.other ?? "Other", []);
|
||||||
group.set(langui.group, []);
|
group.set(langui.group ?? "Group", []);
|
||||||
group.set(langui.no_type, []);
|
group.set(langui.no_type ?? "No type", []);
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.metadata.length > 0) {
|
if (item.attributes?.metadata && item.attributes.metadata.length > 0) {
|
||||||
switch (item.attributes.metadata[0].__typename) {
|
switch (item.attributes.metadata[0]?.__typename) {
|
||||||
case "ComponentMetadataAudio":
|
case "ComponentMetadataAudio":
|
||||||
group.get(langui.audio)?.push(item);
|
group.get(langui.audio ?? "Audio")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "ComponentMetadataGame":
|
case "ComponentMetadataGame":
|
||||||
group.get(langui.game)?.push(item);
|
group.get(langui.game ?? "Game")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "ComponentMetadataBooks":
|
case "ComponentMetadataBooks":
|
||||||
group.get(langui.textual)?.push(item);
|
group.get(langui.textual ?? "Textual")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "ComponentMetadataVideo":
|
case "ComponentMetadataVideo":
|
||||||
group.get(langui.video)?.push(item);
|
group.get(langui.video ?? "Video")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "ComponentMetadataOther":
|
case "ComponentMetadataOther":
|
||||||
group.get(langui.other)?.push(item);
|
group.get(langui.other ?? "Other")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "ComponentMetadataGroup":
|
case "ComponentMetadataGroup":
|
||||||
switch (
|
switch (
|
||||||
item.attributes.metadata[0].subitems_type.data.attributes.slug
|
item.attributes.metadata[0]?.subitems_type?.data?.attributes
|
||||||
|
?.slug
|
||||||
) {
|
) {
|
||||||
case "audio":
|
case "audio":
|
||||||
group.get(langui.audio)?.push(item);
|
group.get(langui.audio ?? "Audio")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "video":
|
case "video":
|
||||||
group.get(langui.video)?.push(item);
|
group.get(langui.video ?? "Video")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "game":
|
case "game":
|
||||||
group.get(langui.game)?.push(item);
|
group.get(langui.game ?? "Game")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "textual":
|
case "textual":
|
||||||
group.get(langui.textual)?.push(item);
|
group.get(langui.textual ?? "Textual")?.push(item);
|
||||||
break;
|
break;
|
||||||
case "mixed":
|
case "mixed":
|
||||||
group.get(langui.group)?.push(item);
|
group.get(langui.group ?? "Group")?.push(item);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -279,7 +285,7 @@ function getGroups(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
group.get(langui.no_type)?.push(item);
|
group.get(langui.no_type ?? "No type")?.push(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return group;
|
return group;
|
||||||
|
@ -288,7 +294,7 @@ function getGroups(
|
||||||
case 2: {
|
case 2: {
|
||||||
const years: number[] = [];
|
const years: number[] = [];
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.release_date) {
|
if (item.attributes?.release_date?.year) {
|
||||||
if (!years.includes(item.attributes.release_date.year))
|
if (!years.includes(item.attributes.release_date.year))
|
||||||
years.push(item.attributes.release_date.year);
|
years.push(item.attributes.release_date.year);
|
||||||
}
|
}
|
||||||
|
@ -298,12 +304,12 @@ function getGroups(
|
||||||
years.map((year) => {
|
years.map((year) => {
|
||||||
group.set(year.toString(), []);
|
group.set(year.toString(), []);
|
||||||
});
|
});
|
||||||
group.set(langui.no_year, []);
|
group.set(langui.no_year || "No year", []);
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.release_date) {
|
if (item.attributes?.release_date?.year) {
|
||||||
group.get(item.attributes.release_date.year.toString())?.push(item);
|
group.get(item.attributes.release_date.year.toString())?.push(item);
|
||||||
} else {
|
} else {
|
||||||
group.get(langui.no_year)?.push(item);
|
group.get(langui.no_year || "No year")?.push(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -322,66 +328,63 @@ function filterItems(
|
||||||
showSubitems: boolean,
|
showSubitems: boolean,
|
||||||
showPrimaryItems: boolean,
|
showPrimaryItems: boolean,
|
||||||
showSecondaryItems: boolean,
|
showSecondaryItems: boolean,
|
||||||
items: LibraryProps["items"]
|
items: Props["items"]
|
||||||
): LibraryProps["items"] {
|
): Props["items"] {
|
||||||
return [...items].filter((item) => {
|
return [...items].filter((item) => {
|
||||||
if (!showSubitems && !item.attributes.root_item) return false;
|
if (!showSubitems && !item.attributes?.root_item) return false;
|
||||||
if (
|
if (
|
||||||
showSubitems &&
|
showSubitems &&
|
||||||
item.attributes.metadata.length > 0 &&
|
item.attributes?.metadata?.[0]?.__typename === "ComponentMetadataGroup" &&
|
||||||
item.attributes.metadata[0].__typename === "ComponentMetadataGroup" &&
|
(item.attributes.metadata[0].subtype?.data?.attributes?.slug ===
|
||||||
(item.attributes.metadata[0].subtype.data.attributes.slug ===
|
|
||||||
"variant-set" ||
|
"variant-set" ||
|
||||||
item.attributes.metadata[0].subtype.data.attributes.slug ===
|
item.attributes.metadata[0].subtype?.data?.attributes?.slug ===
|
||||||
"relation-set")
|
"relation-set")
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
if (item.attributes.primary && !showPrimaryItems) return false;
|
if (item.attributes?.primary && !showPrimaryItems) return false;
|
||||||
if (!item.attributes.primary && !showSecondaryItems) return false;
|
if (!item.attributes?.primary && !showSecondaryItems) return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortBy(
|
function sortBy(
|
||||||
orderByType: number,
|
orderByType: number,
|
||||||
items: LibraryProps["items"],
|
items: Props["items"],
|
||||||
currencies: GetCurrenciesQuery["currencies"]["data"]
|
currencies: AppStaticProps["currencies"]
|
||||||
): LibraryProps["items"] {
|
): Props["items"] {
|
||||||
switch (orderByType) {
|
switch (orderByType) {
|
||||||
case 0:
|
case 0:
|
||||||
return [...items].sort((a, b) => {
|
return [...items].sort((a, b) => {
|
||||||
const titleA = prettyinlineTitle(
|
const titleA = prettyinlineTitle(
|
||||||
"",
|
"",
|
||||||
a.attributes.title,
|
a.attributes?.title,
|
||||||
a.attributes.subtitle
|
a.attributes?.subtitle
|
||||||
);
|
);
|
||||||
const titleB = prettyinlineTitle(
|
const titleB = prettyinlineTitle(
|
||||||
"",
|
"",
|
||||||
b.attributes.title,
|
b.attributes?.title,
|
||||||
b.attributes.subtitle
|
b.attributes?.subtitle
|
||||||
);
|
);
|
||||||
return titleA.localeCompare(titleB);
|
return titleA.localeCompare(titleB);
|
||||||
});
|
});
|
||||||
case 1:
|
case 1:
|
||||||
return [...items].sort((a, b) => {
|
return [...items].sort((a, b) => {
|
||||||
const priceA = a.attributes.price
|
const priceA = a.attributes?.price
|
||||||
? convertPrice(a.attributes.price, currencies[0])
|
? convertPrice(a.attributes.price, currencies[0])
|
||||||
: 99999;
|
: 99999;
|
||||||
const priceB = b.attributes.price
|
const priceB = b.attributes?.price
|
||||||
? convertPrice(b.attributes.price, currencies[0])
|
? convertPrice(b.attributes.price, currencies[0])
|
||||||
: 99999;
|
: 99999;
|
||||||
return priceA - priceB;
|
return priceA - priceB;
|
||||||
});
|
});
|
||||||
case 2:
|
case 2:
|
||||||
return [...items].sort((a, b) => {
|
return [...items].sort((a, b) => {
|
||||||
const dateA =
|
const dateA = a.attributes?.release_date
|
||||||
a.attributes.release_date === null
|
? prettyDate(a.attributes.release_date)
|
||||||
? "9999"
|
: "9999";
|
||||||
: prettyDate(a.attributes.release_date);
|
const dateB = b.attributes?.release_date
|
||||||
const dateB =
|
? prettyDate(b.attributes.release_date)
|
||||||
b.attributes.release_date === null
|
: "9999";
|
||||||
? "9999"
|
|
||||||
: prettyDate(b.attributes.release_date);
|
|
||||||
return dateA.localeCompare(dateB);
|
return dateA.localeCompare(dateB);
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -17,7 +17,13 @@ export default function Merch(props: MerchProps): JSX.Element {
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AppLayout navTitle={langui.merch} subPanel={subPanel} {...props} />;
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navTitle={langui.merch}
|
||||||
|
subPanel={subPanel}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
|
|
|
@ -12,8 +12,8 @@ import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import RecorderChip from "components/RecorderChip";
|
import RecorderChip from "components/RecorderChip";
|
||||||
import ToolTip from "components/ToolTip";
|
import ToolTip from "components/ToolTip";
|
||||||
import { getPost, getPostsSlugs } from "graphql/operations";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { GetPostQuery, StrapiImage } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import {
|
||||||
GetStaticPathsContext,
|
GetStaticPathsContext,
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
|
@ -28,21 +28,30 @@ import {
|
||||||
} from "queries/helpers";
|
} from "queries/helpers";
|
||||||
|
|
||||||
interface PostProps extends AppStaticProps {
|
interface PostProps extends AppStaticProps {
|
||||||
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
post: Exclude<
|
||||||
postId: GetPostQuery["posts"]["data"][number]["id"];
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
postId: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["id"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LibrarySlug(props: PostProps): JSX.Element {
|
export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
const { post, langui } = props;
|
const { post, langui } = props;
|
||||||
const locales = getLocalesFromLanguages(post.translations_languages);
|
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const thumbnail: StrapiImage | undefined =
|
const thumbnail = post?.translations?.[0]?.thumbnail?.data
|
||||||
post.translations.length > 0 && post.translations[0].thumbnail.data
|
? post.translations[0].thumbnail.data.attributes
|
||||||
? post.translations[0].thumbnail.data.attributes
|
: post?.thumbnail?.data
|
||||||
: post.thumbnail.data
|
? post.thumbnail.data.attributes
|
||||||
? post.thumbnail.data.attributes
|
: undefined;
|
||||||
: undefined;
|
|
||||||
|
const body = post?.translations?.[0]?.body ?? "";
|
||||||
|
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||||
|
const except = post?.translations?.[0]?.excerpt ?? "";
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
@ -54,7 +63,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{post.translations.length > 0 && (
|
{post?.translations?.[0] && (
|
||||||
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
||||||
<p className="font-headers">{langui.status}:</p>
|
<p className="font-headers">{langui.status}:</p>
|
||||||
|
|
||||||
|
@ -67,12 +76,20 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{post.authors.data.length > 0 && (
|
{post?.authors && post.authors.data.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<p className="font-headers">{"Authors"}:</p>
|
<p className="font-headers">{"Authors"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{post.authors.data.map((author) => (
|
{post.authors.data.map((author) => (
|
||||||
<RecorderChip key={author.id} langui={langui} recorder={author} />
|
<>
|
||||||
|
{author.attributes && (
|
||||||
|
<RecorderChip
|
||||||
|
key={author.id}
|
||||||
|
langui={langui}
|
||||||
|
recorder={author.attributes}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,12 +97,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
|
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
|
|
||||||
{post.translations.length > 0 && post.translations[0].body && (
|
<TOC text={body} title={title} />
|
||||||
<TOC
|
|
||||||
text={post.translations[0].body}
|
|
||||||
title={post.translations[0].title}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
|
@ -100,24 +112,16 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
|
|
||||||
<ThumbnailHeader
|
<ThumbnailHeader
|
||||||
thumbnail={thumbnail}
|
thumbnail={thumbnail}
|
||||||
title={
|
title={title}
|
||||||
post.translations.length > 0
|
description={except}
|
||||||
? post.translations[0].title
|
|
||||||
: prettySlug(post.slug)
|
|
||||||
}
|
|
||||||
description={
|
|
||||||
post.translations.length > 0
|
|
||||||
? post.translations[0].excerpt
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
categories={post.categories}
|
categories={post?.categories}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
{locales.includes(router.locale ?? "en") ? (
|
||||||
<Markdawn text={post.translations[0].body} />
|
<Markdawn text={body} />
|
||||||
) : (
|
) : (
|
||||||
<LanguageSwitcher
|
<LanguageSwitcher
|
||||||
locales={locales}
|
locales={locales}
|
||||||
|
@ -130,14 +134,10 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<AppLayout
|
||||||
navTitle={
|
navTitle={title}
|
||||||
post.translations.length > 0
|
|
||||||
? post.translations[0].title
|
|
||||||
: prettySlug(post.slug)
|
|
||||||
}
|
|
||||||
contentPanel={contentPanel}
|
contentPanel={contentPanel}
|
||||||
subPanel={subPanel}
|
subPanel={subPanel}
|
||||||
thumbnail={thumbnail}
|
thumbnail={thumbnail ?? undefined}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -146,18 +146,17 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: PostProps }> {
|
): Promise<{ notFound: boolean } | { props: PostProps }> {
|
||||||
const slug = context.params?.slug?.toString() ?? "";
|
const sdk = getReadySdk();
|
||||||
const post = (
|
const slug = context.params?.slug ? context.params.slug.toString() : "";
|
||||||
await getPost({
|
const post = await sdk.getPost({
|
||||||
slug: slug,
|
slug: slug,
|
||||||
language_code: context.locale ?? "en",
|
language_code: context.locale ?? "en",
|
||||||
})
|
});
|
||||||
).posts.data[0];
|
if (!post.posts?.data[0]) return { notFound: true };
|
||||||
if (!post) return { notFound: true };
|
|
||||||
const props: PostProps = {
|
const props: PostProps = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
post: post.attributes,
|
post: post.posts.data[0].attributes,
|
||||||
postId: post.id,
|
postId: post.posts.data[0].id,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
@ -167,13 +166,16 @@ export async function getStaticProps(
|
||||||
export async function getStaticPaths(
|
export async function getStaticPaths(
|
||||||
context: GetStaticPathsContext
|
context: GetStaticPathsContext
|
||||||
): Promise<GetStaticPathsResult> {
|
): Promise<GetStaticPathsResult> {
|
||||||
const posts = await getPostsSlugs({});
|
const sdk = getReadySdk();
|
||||||
|
const posts = await sdk.getPostsSlugs();
|
||||||
const paths: GetStaticPathsResult["paths"] = [];
|
const paths: GetStaticPathsResult["paths"] = [];
|
||||||
posts.posts.data.map((item) => {
|
if (posts.posts)
|
||||||
context.locales?.map((local) => {
|
posts.posts.data.map((item) => {
|
||||||
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
context.locales?.map((local) => {
|
||||||
|
if (item.attributes)
|
||||||
|
paths.push({ params: { slug: item.attributes.slug }, locale: local });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
paths,
|
paths,
|
||||||
fallback: "blocking",
|
fallback: "blocking",
|
||||||
|
|
|
@ -5,25 +5,23 @@ import ContentPanel, {
|
||||||
ContentPanelWidthSizes,
|
ContentPanelWidthSizes,
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { getPostsPreview } from "graphql/operations";
|
import { GetPostsPreviewQuery } from "graphql/generated";
|
||||||
import { GetPostsPreviewQuery } from "graphql/operations-types";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { prettyDate } from "queries/helpers";
|
import { prettyDate } from "queries/helpers";
|
||||||
|
|
||||||
interface NewsProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
posts: GetPostsPreviewQuery["posts"]["data"];
|
posts: Exclude<GetPostsPreviewQuery["posts"], null | undefined>["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function News(props: NewsProps): JSX.Element {
|
export default function News(props: Props): JSX.Element {
|
||||||
const { langui, posts } = props;
|
const { langui, posts } = props;
|
||||||
|
|
||||||
posts
|
posts
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const dateA =
|
const dateA = a.attributes?.date ? prettyDate(a.attributes.date) : "9999";
|
||||||
a.attributes.date === null ? "9999" : prettyDate(a.attributes.date);
|
const dateB = b.attributes?.date ? prettyDate(b.attributes.date) : "9999";
|
||||||
const dateB =
|
|
||||||
b.attributes.date === null ? "9999" : prettyDate(b.attributes.date);
|
|
||||||
return dateA.localeCompare(dateB);
|
return dateA.localeCompare(dateB);
|
||||||
})
|
})
|
||||||
.reverse();
|
.reverse();
|
||||||
|
@ -60,12 +58,15 @@ export default function News(props: NewsProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: NewsProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const props: NewsProps = {
|
const sdk = getReadySdk();
|
||||||
|
const posts = await sdk.getPostsPreview({
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!posts.posts) return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
posts: await (
|
posts: posts.posts.data,
|
||||||
await getPostsPreview({ language_code: context.locale ?? "en" })
|
|
||||||
).posts.data,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -8,11 +8,8 @@ import ReturnButton, {
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { getChronologyItems, getEras } from "graphql/operations";
|
import { GetChronologyItemsQuery, GetErasQuery } from "graphql/generated";
|
||||||
import {
|
import { getReadySdk } from "graphql/sdk";
|
||||||
GetChronologyItemsQuery,
|
|
||||||
GetErasQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
@ -22,19 +19,24 @@ import {
|
||||||
prettyTestWarning,
|
prettyTestWarning,
|
||||||
} from "queries/helpers";
|
} from "queries/helpers";
|
||||||
|
|
||||||
interface ChronologyProps extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
chronologyItems: GetChronologyItemsQuery["chronologyItems"]["data"];
|
chronologyItems: Exclude<
|
||||||
chronologyEras: GetErasQuery["chronologyEras"]["data"];
|
GetChronologyItemsQuery["chronologyItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"];
|
||||||
|
chronologyEras: Exclude<
|
||||||
|
GetErasQuery["chronologyEras"],
|
||||||
|
null | undefined
|
||||||
|
>["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Chronology(props: ChronologyProps): JSX.Element {
|
export default function Chronology(props: Props): JSX.Element {
|
||||||
useTesting(props);
|
useTesting(props);
|
||||||
const { chronologyItems, chronologyEras, langui } = props;
|
const { chronologyItems, chronologyEras, langui } = props;
|
||||||
const appLayout = useAppLayout();
|
const appLayout = useAppLayout();
|
||||||
|
|
||||||
// Group by year the Chronology items
|
// Group by year the Chronology items
|
||||||
const chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] =
|
const chronologyItemYearGroups: Props["chronologyItems"][number][][][] = [];
|
||||||
[];
|
|
||||||
|
|
||||||
chronologyEras.map(() => {
|
chronologyEras.map(() => {
|
||||||
chronologyItemYearGroups.push([]);
|
chronologyItemYearGroups.push([]);
|
||||||
|
@ -42,25 +44,28 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
|
||||||
|
|
||||||
let currentChronologyEraIndex = 0;
|
let currentChronologyEraIndex = 0;
|
||||||
chronologyItems.map((item) => {
|
chronologyItems.map((item) => {
|
||||||
if (
|
if (item.attributes) {
|
||||||
item.attributes.year >
|
if (
|
||||||
chronologyEras[currentChronologyEraIndex].attributes.ending_year
|
item.attributes.year >
|
||||||
) {
|
(chronologyEras[currentChronologyEraIndex].attributes?.ending_year ??
|
||||||
currentChronologyEraIndex += 1;
|
999999)
|
||||||
}
|
) {
|
||||||
if (
|
currentChronologyEraIndex += 1;
|
||||||
Object.prototype.hasOwnProperty.call(
|
}
|
||||||
chronologyItemYearGroups[currentChronologyEraIndex],
|
if (
|
||||||
item.attributes.year
|
Object.prototype.hasOwnProperty.call(
|
||||||
)
|
chronologyItemYearGroups[currentChronologyEraIndex],
|
||||||
) {
|
item.attributes.year
|
||||||
chronologyItemYearGroups[currentChronologyEraIndex][
|
)
|
||||||
item.attributes.year
|
) {
|
||||||
].push(item);
|
chronologyItemYearGroups[currentChronologyEraIndex][
|
||||||
} else {
|
item.attributes.year
|
||||||
chronologyItemYearGroups[currentChronologyEraIndex][
|
].push(item);
|
||||||
item.attributes.year
|
} else {
|
||||||
] = [item];
|
chronologyItemYearGroups[currentChronologyEraIndex][
|
||||||
|
item.attributes.year
|
||||||
|
] = [item];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -75,18 +80,24 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{chronologyEras.map((era) => (
|
{chronologyEras.map((era) => (
|
||||||
<NavOption
|
<>
|
||||||
key={era.id}
|
{era.attributes && (
|
||||||
url={`#${era.attributes.slug}`}
|
<NavOption
|
||||||
title={
|
key={era.id}
|
||||||
era.attributes.title.length > 0
|
url={`#${era.attributes.slug}`}
|
||||||
? era.attributes.title[0].title
|
title={
|
||||||
: prettySlug(era.attributes.slug)
|
era.attributes.title &&
|
||||||
}
|
era.attributes.title.length > 0 &&
|
||||||
subtitle={`${era.attributes.starting_year} → ${era.attributes.ending_year}`}
|
era.attributes.title[0]
|
||||||
border
|
? era.attributes.title[0].title
|
||||||
onClick={() => appLayout.setSubPanelOpen(false)}
|
: prettySlug(era.attributes.slug)
|
||||||
/>
|
}
|
||||||
|
subtitle={`${era.attributes.starting_year} → ${era.attributes.ending_year}`}
|
||||||
|
border
|
||||||
|
onClick={() => appLayout.setSubPanelOpen(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
@ -104,27 +115,31 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
|
||||||
{chronologyItemYearGroups.map((era, eraIndex) => (
|
{chronologyItemYearGroups.map((era, eraIndex) => (
|
||||||
<>
|
<>
|
||||||
<InsetBox
|
<InsetBox
|
||||||
id={chronologyEras[eraIndex].attributes.slug}
|
id={chronologyEras[eraIndex].attributes?.slug}
|
||||||
className="grid text-center my-8 gap-4"
|
className="grid text-center my-8 gap-4"
|
||||||
>
|
>
|
||||||
<h2 className="text-2xl">
|
<h2 className="text-2xl">
|
||||||
{chronologyEras[eraIndex].attributes.title.length > 0
|
{chronologyEras[eraIndex].attributes?.title?.[0]
|
||||||
? chronologyEras[eraIndex].attributes.title[0].title
|
? chronologyEras[eraIndex].attributes?.title?.[0]?.title
|
||||||
: prettySlug(chronologyEras[eraIndex].attributes.slug)}
|
: prettySlug(chronologyEras[eraIndex].attributes?.slug)}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="whitespace-pre-line ">
|
<p className="whitespace-pre-line ">
|
||||||
{chronologyEras[eraIndex].attributes.title.length > 0
|
{chronologyEras[eraIndex].attributes?.title?.[0]
|
||||||
? chronologyEras[eraIndex].attributes.title[0].description
|
? chronologyEras[eraIndex].attributes?.title?.[0]?.description
|
||||||
: ""}
|
: ""}
|
||||||
</p>
|
</p>
|
||||||
</InsetBox>
|
</InsetBox>
|
||||||
{era.map((items, index) => (
|
{era.map((items, index) => (
|
||||||
<ChronologyYearComponent
|
<>
|
||||||
key={`${eraIndex}-${index}`}
|
{items[0].attributes?.year && (
|
||||||
year={items[0].attributes.year}
|
<ChronologyYearComponent
|
||||||
items={items}
|
key={`${eraIndex}-${index}`}
|
||||||
langui={langui}
|
year={items[0].attributes.year}
|
||||||
/>
|
items={items}
|
||||||
|
langui={langui}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
|
@ -143,36 +158,40 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: ChronologyProps }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const props: ChronologyProps = {
|
const sdk = getReadySdk();
|
||||||
|
const chronologyItems = await sdk.getChronologyItems({
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
const chronologyEras = await sdk.getEras({
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
});
|
||||||
|
if (!chronologyItems.chronologyItems || !chronologyEras.chronologyEras)
|
||||||
|
return { notFound: true };
|
||||||
|
const props: Props = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
chronologyItems: (
|
chronologyItems: chronologyItems.chronologyItems.data,
|
||||||
await getChronologyItems({
|
chronologyEras: chronologyEras.chronologyEras.data,
|
||||||
language_code: context.locale ?? "en",
|
|
||||||
})
|
|
||||||
).chronologyItems.data,
|
|
||||||
chronologyEras: (await getEras({ language_code: context.locale ?? "en" }))
|
|
||||||
.chronologyEras.data,
|
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function useTesting(props: ChronologyProps) {
|
function useTesting(props: Props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { chronologyItems, chronologyEras } = props;
|
const { chronologyItems, chronologyEras } = props;
|
||||||
chronologyEras.map((era) => {
|
chronologyEras.map((era) => {
|
||||||
const chronologyErasURL = `/admin/content-manager/collectionType/api::chronology-era.chronology-era/${chronologyItems[0].id}`;
|
const chronologyErasURL = `/admin/content-manager/collectionType/api::chronology-era.chronology-era/${chronologyItems[0].id}`;
|
||||||
|
|
||||||
if (era.attributes.title.length === 0) {
|
if (era.attributes?.title?.length === 0) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing translation for title and description, using slug instead",
|
"Missing translation for title and description, using slug instead",
|
||||||
["chronologyEras", era.attributes.slug],
|
["chronologyEras", era.attributes.slug],
|
||||||
chronologyErasURL
|
chronologyErasURL
|
||||||
);
|
);
|
||||||
} else if (era.attributes.title.length > 1) {
|
} else if (era.attributes?.title && era.attributes.title.length > 1) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"More than one title and description",
|
"More than one title and description",
|
||||||
|
@ -180,18 +199,18 @@ function useTesting(props: ChronologyProps) {
|
||||||
chronologyErasURL
|
chronologyErasURL
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (!era.attributes.title[0].title)
|
if (!era.attributes?.title?.[0]?.title)
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing title, using slug instead",
|
"Missing title, using slug instead",
|
||||||
["chronologyEras", era.attributes.slug],
|
["chronologyEras", era.attributes?.slug ?? ""],
|
||||||
chronologyErasURL
|
chronologyErasURL
|
||||||
);
|
);
|
||||||
if (!era.attributes.title[0].description)
|
if (!era.attributes?.title?.[0]?.description)
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"Missing description",
|
"Missing description",
|
||||||
["chronologyEras", era.attributes.slug],
|
["chronologyEras", era.attributes?.slug ?? ""],
|
||||||
chronologyErasURL
|
chronologyErasURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -200,23 +219,23 @@ function useTesting(props: ChronologyProps) {
|
||||||
chronologyItems.map((item) => {
|
chronologyItems.map((item) => {
|
||||||
const chronologyItemsURL = `/admin/content-manager/collectionType/api::chronology-item.chronology-item/${chronologyItems[0].id}`;
|
const chronologyItemsURL = `/admin/content-manager/collectionType/api::chronology-item.chronology-item/${chronologyItems[0].id}`;
|
||||||
|
|
||||||
const date = `${item.attributes.year}/${item.attributes.month}/${item.attributes.day}`;
|
const date = `${item.attributes?.year}/${item.attributes?.month}/${item.attributes?.day}`;
|
||||||
|
|
||||||
if (item.attributes.events.length > 0) {
|
if (item.attributes?.events && item.attributes.events.length > 0) {
|
||||||
item.attributes.events.map((event) => {
|
item.attributes.events.map((event) => {
|
||||||
if (!event.source.data) {
|
if (!event?.source?.data) {
|
||||||
prettyTestError(
|
prettyTestError(
|
||||||
router,
|
router,
|
||||||
"No source for this event",
|
"No source for this event",
|
||||||
["chronologyItems", date, event.id],
|
["chronologyItems", date, event?.id ?? ""],
|
||||||
chronologyItemsURL
|
chronologyItemsURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!(event.translations.length > 0)) {
|
if (!(event?.translations && event.translations.length > 0)) {
|
||||||
prettyTestWarning(
|
prettyTestWarning(
|
||||||
router,
|
router,
|
||||||
"No translation for this event",
|
"No translation for this event",
|
||||||
["chronologyItems", date, event.id],
|
["chronologyItems", date, event?.id ?? ""],
|
||||||
chronologyItemsURL
|
chronologyItemsURL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,58 @@
|
||||||
import {
|
|
||||||
getCurrencies,
|
|
||||||
getLanguages,
|
|
||||||
getWebsiteInterface,
|
|
||||||
} from "graphql/operations";
|
|
||||||
import {
|
import {
|
||||||
GetCurrenciesQuery,
|
GetCurrenciesQuery,
|
||||||
GetLanguagesQuery,
|
GetLanguagesQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/generated";
|
||||||
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
|
|
||||||
export interface AppStaticProps {
|
export interface AppStaticProps {
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: Exclude<
|
||||||
currencies: GetCurrenciesQuery["currencies"]["data"];
|
Exclude<
|
||||||
languages: GetLanguagesQuery["languages"]["data"];
|
GetWebsiteInterfaceQuery["websiteInterfaces"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"],
|
||||||
|
null | undefined
|
||||||
|
>;
|
||||||
|
currencies: Exclude<
|
||||||
|
GetCurrenciesQuery["currencies"],
|
||||||
|
null | undefined
|
||||||
|
>["data"];
|
||||||
|
languages: Exclude<GetLanguagesQuery["languages"], null | undefined>["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAppStaticProps(
|
export async function getAppStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<AppStaticProps> {
|
): Promise<AppStaticProps> {
|
||||||
const languages = (await getLanguages({})).languages.data;
|
const sdk = getReadySdk();
|
||||||
languages.sort((a, b) =>
|
const languages = (await sdk.getLanguages()).languages;
|
||||||
a.attributes.localized_name.localeCompare(b.attributes.localized_name)
|
|
||||||
);
|
|
||||||
|
|
||||||
const currencies = (await getCurrencies({})).currencies.data;
|
if (languages?.data) {
|
||||||
currencies.sort((a, b) => a.attributes.code.localeCompare(b.attributes.code));
|
languages.data.sort((a, b) =>
|
||||||
|
a.attributes && b.attributes
|
||||||
|
? a.attributes.localized_name.localeCompare(b.attributes.localized_name)
|
||||||
|
: 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currencies = (await sdk.getCurrencies()).currencies;
|
||||||
|
if (currencies?.data) {
|
||||||
|
currencies.data.sort((a, b) =>
|
||||||
|
a.attributes && b.attributes
|
||||||
|
? a.attributes.code.localeCompare(b.attributes.code)
|
||||||
|
: 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const langui = (
|
||||||
|
await sdk.getWebsiteInterface({
|
||||||
|
language_code: context.locale ?? "en",
|
||||||
|
})
|
||||||
|
).websiteInterfaces?.data[0].attributes;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
langui: (
|
langui: langui ?? ({} as AppStaticProps["langui"]),
|
||||||
await getWebsiteInterface({
|
currencies: currencies?.data ?? ({} as AppStaticProps["currencies"]),
|
||||||
language_code: context.locale ?? "en",
|
languages: languages?.data ?? ({} as AppStaticProps["languages"]),
|
||||||
})
|
|
||||||
).websiteInterfaces.data[0].attributes,
|
|
||||||
currencies: currencies,
|
|
||||||
languages: languages,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,33 +4,36 @@ import {
|
||||||
ImageQuality,
|
ImageQuality,
|
||||||
} from "components/Img";
|
} from "components/Img";
|
||||||
import {
|
import {
|
||||||
|
DatePickerFragment,
|
||||||
Enum_Componentsetstextset_Status,
|
Enum_Componentsetstextset_Status,
|
||||||
GetCurrenciesQuery,
|
GetCurrenciesQuery,
|
||||||
GetLanguagesQuery,
|
|
||||||
GetLibraryItemQuery,
|
GetLibraryItemQuery,
|
||||||
GetLibraryItemsPreviewQuery,
|
GetLibraryItemScansQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
PricePickerFragment,
|
||||||
StrapiImage,
|
UploadImageFragment,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/generated";
|
||||||
import { NextRouter } from "next/router";
|
import { NextRouter } from "next/router";
|
||||||
|
import { AppStaticProps } from "./getAppStaticProps";
|
||||||
|
|
||||||
export function prettyDate(
|
export function prettyDate(datePicker: DatePickerFragment): string {
|
||||||
datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
|
let result = "";
|
||||||
): string {
|
if (datePicker.year) result += datePicker.year.toString();
|
||||||
return `${datePicker.year}/${datePicker.month
|
if (datePicker.month)
|
||||||
.toString()
|
result += `/${datePicker.month.toString().padStart(2, "0")}`;
|
||||||
.padStart(2, "0")}/${datePicker.day.toString().padStart(2, "0")}`;
|
if (datePicker.day)
|
||||||
|
result += `/${datePicker.day.toString().padStart(2, "0")}`;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettyPrice(
|
export function prettyPrice(
|
||||||
pricePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"],
|
pricePicker: PricePickerFragment,
|
||||||
currencies: GetCurrenciesQuery["currencies"]["data"],
|
currencies: AppStaticProps["currencies"],
|
||||||
targetCurrencyCode?: string
|
targetCurrencyCode?: string
|
||||||
): string {
|
): string {
|
||||||
if (!targetCurrencyCode) return "";
|
if (!targetCurrencyCode) return "";
|
||||||
let result = "";
|
let result = "";
|
||||||
currencies.map((currency) => {
|
currencies.map((currency) => {
|
||||||
if (currency.attributes.code === targetCurrencyCode) {
|
if (currency?.attributes?.code === targetCurrencyCode) {
|
||||||
const amountInTargetCurrency = convertPrice(pricePicker, currency);
|
const amountInTargetCurrency = convertPrice(pricePicker, currency);
|
||||||
result =
|
result =
|
||||||
currency.attributes.symbol +
|
currency.attributes.symbol +
|
||||||
|
@ -44,13 +47,22 @@ export function prettyPrice(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertPrice(
|
export function convertPrice(
|
||||||
pricePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"],
|
pricePicker: PricePickerFragment,
|
||||||
targetCurrency: GetCurrenciesQuery["currencies"]["data"][number]
|
targetCurrency: Exclude<
|
||||||
|
GetCurrenciesQuery["currencies"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]
|
||||||
): number {
|
): number {
|
||||||
return (
|
if (
|
||||||
(pricePicker.amount * pricePicker.currency.data.attributes.rate_to_usd) /
|
pricePicker.amount &&
|
||||||
targetCurrency.attributes.rate_to_usd
|
pricePicker.currency?.data?.attributes &&
|
||||||
);
|
targetCurrency.attributes
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
(pricePicker.amount * pricePicker.currency.data.attributes.rate_to_usd) /
|
||||||
|
targetCurrency.attributes.rate_to_usd
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettySlug(slug?: string, parentSlug?: string): string {
|
export function prettySlug(slug?: string, parentSlug?: string): string {
|
||||||
|
@ -65,9 +77,9 @@ export function prettySlug(slug?: string, parentSlug?: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettyinlineTitle(
|
export function prettyinlineTitle(
|
||||||
pretitle: string,
|
pretitle: string | undefined | null,
|
||||||
title: string,
|
title: string | undefined | null,
|
||||||
subtitle: string
|
subtitle: string | undefined | null
|
||||||
): string {
|
): string {
|
||||||
let result = "";
|
let result = "";
|
||||||
if (pretitle) result += `${pretitle}: `;
|
if (pretitle) result += `${pretitle}: `;
|
||||||
|
@ -77,11 +89,9 @@ export function prettyinlineTitle(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettyItemType(
|
export function prettyItemType(
|
||||||
metadata: {
|
metadata: any,
|
||||||
__typename: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"][number]["__typename"];
|
langui: AppStaticProps["langui"]
|
||||||
},
|
): string | undefined | null {
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]
|
|
||||||
): string {
|
|
||||||
switch (metadata.__typename) {
|
switch (metadata.__typename) {
|
||||||
case "ComponentMetadataAudio":
|
case "ComponentMetadataAudio":
|
||||||
return langui.audio;
|
return langui.audio;
|
||||||
|
@ -100,50 +110,132 @@ export function prettyItemType(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettyItemSubType(metadata: {
|
export function prettyItemSubType(
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
metadata:
|
||||||
__typename: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"][number]["__typename"];
|
| {
|
||||||
subtype?: any;
|
__typename: "ComponentMetadataAudio";
|
||||||
platforms?: any;
|
subtype?: {
|
||||||
subitems_type?: any;
|
data?: {
|
||||||
}): string {
|
attributes?: {
|
||||||
switch (metadata.__typename) {
|
slug: string;
|
||||||
case "ComponentMetadataAudio":
|
titles?: Array<{
|
||||||
case "ComponentMetadataBooks":
|
title: string;
|
||||||
case "ComponentMetadataVideo":
|
} | null> | null;
|
||||||
return metadata.subtype.data.attributes.titles.length > 0
|
} | null;
|
||||||
? metadata.subtype.data.attributes.titles[0].title
|
} | null;
|
||||||
: prettySlug(metadata.subtype.data.attributes.slug);
|
} | null;
|
||||||
case "ComponentMetadataGame":
|
}
|
||||||
return metadata.platforms.data.length > 0
|
| {
|
||||||
? metadata.platforms.data[0].attributes.short
|
__typename: "ComponentMetadataBooks";
|
||||||
: "";
|
subtype?: {
|
||||||
|
data?: {
|
||||||
case "ComponentMetadataGroup": {
|
attributes?: {
|
||||||
const firstPart =
|
slug: string;
|
||||||
metadata.subtype.data.attributes.titles.length > 0
|
titles?: Array<{
|
||||||
|
title: string;
|
||||||
|
} | null> | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
__typename: "ComponentMetadataGame";
|
||||||
|
platforms?: {
|
||||||
|
data: Array<{
|
||||||
|
id?: string | null;
|
||||||
|
attributes?: {
|
||||||
|
short: string;
|
||||||
|
} | null;
|
||||||
|
}>;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
__typename: "ComponentMetadataGroup";
|
||||||
|
subtype?: {
|
||||||
|
data?: {
|
||||||
|
attributes?: {
|
||||||
|
slug: string;
|
||||||
|
titles?: Array<{
|
||||||
|
title: string;
|
||||||
|
} | null> | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
subitems_type?: {
|
||||||
|
data?: {
|
||||||
|
attributes?: {
|
||||||
|
slug: string;
|
||||||
|
titles?: Array<{
|
||||||
|
title: string;
|
||||||
|
} | null> | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
| { __typename: "ComponentMetadataOther" }
|
||||||
|
| {
|
||||||
|
__typename: "ComponentMetadataVideo";
|
||||||
|
subtype?: {
|
||||||
|
data?: {
|
||||||
|
attributes?: {
|
||||||
|
slug: string;
|
||||||
|
titles?: Array<{
|
||||||
|
title: string;
|
||||||
|
} | null> | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
| { __typename: "Error" }
|
||||||
|
| null
|
||||||
|
): string {
|
||||||
|
if (metadata) {
|
||||||
|
switch (metadata.__typename) {
|
||||||
|
case "ComponentMetadataAudio":
|
||||||
|
case "ComponentMetadataBooks":
|
||||||
|
case "ComponentMetadataVideo":
|
||||||
|
return metadata.subtype?.data?.attributes?.titles &&
|
||||||
|
metadata.subtype?.data?.attributes?.titles.length > 0 &&
|
||||||
|
metadata.subtype.data.attributes.titles[0]
|
||||||
? metadata.subtype.data.attributes.titles[0].title
|
? metadata.subtype.data.attributes.titles[0].title
|
||||||
: prettySlug(metadata.subtype.data.attributes.slug);
|
: prettySlug(metadata.subtype?.data?.attributes?.slug);
|
||||||
|
case "ComponentMetadataGame":
|
||||||
|
return metadata.platforms?.data &&
|
||||||
|
metadata.platforms?.data.length > 0 &&
|
||||||
|
metadata.platforms.data[0].attributes
|
||||||
|
? metadata.platforms.data[0].attributes.short
|
||||||
|
: "";
|
||||||
|
case "ComponentMetadataGroup": {
|
||||||
|
const firstPart =
|
||||||
|
metadata.subtype?.data?.attributes?.titles &&
|
||||||
|
metadata.subtype?.data?.attributes?.titles.length > 0 &&
|
||||||
|
metadata.subtype.data.attributes.titles[0]
|
||||||
|
? metadata.subtype.data.attributes.titles[0].title
|
||||||
|
: prettySlug(metadata.subtype?.data?.attributes?.slug);
|
||||||
|
|
||||||
const secondPart =
|
const secondPart =
|
||||||
metadata.subitems_type.data.attributes.titles.length > 0
|
metadata.subitems_type?.data?.attributes?.titles &&
|
||||||
? metadata.subitems_type.data.attributes.titles[0].title
|
metadata.subitems_type?.data?.attributes?.titles.length > 0 &&
|
||||||
: prettySlug(metadata.subitems_type.data.attributes.slug);
|
metadata.subitems_type.data.attributes.titles[0]
|
||||||
return `${secondPart} ${firstPart}`;
|
? metadata.subitems_type.data.attributes.titles[0].title
|
||||||
|
: prettySlug(metadata.subitems_type?.data?.attributes?.slug);
|
||||||
|
return `${secondPart} ${firstPart}`;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettyLanguage(
|
export function prettyLanguage(
|
||||||
code: string,
|
code: string,
|
||||||
languages: GetLanguagesQuery["languages"]["data"]
|
languages: AppStaticProps["languages"]
|
||||||
): string {
|
): string {
|
||||||
let result = code;
|
let result = code;
|
||||||
languages.forEach((language) => {
|
languages.forEach((language) => {
|
||||||
if (language.attributes.code === code)
|
if (language?.attributes?.code === code)
|
||||||
result = language.attributes.localized_name;
|
result = language.attributes.localized_name;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -207,8 +299,8 @@ export function capitalizeString(string: string): string {
|
||||||
return words.join(" ");
|
return words.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertMmToInch(mm: number): string {
|
export function convertMmToInch(mm: number | null | undefined): string {
|
||||||
return (mm * 0.03937008).toPrecision(3);
|
return mm ? (mm * 0.03937008).toPrecision(3) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OgImage = {
|
export type OgImage = {
|
||||||
|
@ -218,31 +310,44 @@ export type OgImage = {
|
||||||
alt: string;
|
alt: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getOgImage(quality: ImageQuality, image: StrapiImage): OgImage {
|
export function getOgImage(
|
||||||
|
quality: ImageQuality,
|
||||||
|
image: UploadImageFragment
|
||||||
|
): OgImage {
|
||||||
const imgSize = getImgSizesByQuality(
|
const imgSize = getImgSizesByQuality(
|
||||||
image.width,
|
image.width ?? 0,
|
||||||
image.height,
|
image.height ?? 0,
|
||||||
quality ? quality : ImageQuality.Small
|
quality ? quality : ImageQuality.Small
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
image: getAssetURL(image.url, quality),
|
image: getAssetURL(image.url, quality),
|
||||||
width: imgSize.width,
|
width: imgSize.width,
|
||||||
height: imgSize.height,
|
height: imgSize.height,
|
||||||
alt: image.alternativeText,
|
alt: image.alternativeText || "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sortContent(contents: {
|
export function sortContent(
|
||||||
data: {
|
contents:
|
||||||
attributes: {
|
| Exclude<
|
||||||
range: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]["contents"]["data"][number]["attributes"]["range"];
|
Exclude<
|
||||||
};
|
GetLibraryItemQuery["libraryItems"],
|
||||||
}[];
|
null | undefined
|
||||||
}) {
|
>["data"][number]["attributes"],
|
||||||
contents.data.sort((a, b) => {
|
null | undefined
|
||||||
|
>["contents"]
|
||||||
|
| Exclude<
|
||||||
|
Exclude<
|
||||||
|
GetLibraryItemScansQuery["libraryItems"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"],
|
||||||
|
null | undefined
|
||||||
|
>["contents"]
|
||||||
|
) {
|
||||||
|
contents?.data.sort((a, b) => {
|
||||||
if (
|
if (
|
||||||
a.attributes.range[0].__typename === "ComponentRangePageRange" &&
|
a.attributes?.range[0]?.__typename === "ComponentRangePageRange" &&
|
||||||
b.attributes.range[0].__typename === "ComponentRangePageRange"
|
b.attributes?.range[0]?.__typename === "ComponentRangePageRange"
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
a.attributes.range[0].starting_page -
|
a.attributes.range[0].starting_page -
|
||||||
|
@ -255,8 +360,8 @@ export function sortContent(contents: {
|
||||||
|
|
||||||
export function getStatusDescription(
|
export function getStatusDescription(
|
||||||
status: string,
|
status: string,
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]
|
langui: AppStaticProps["langui"]
|
||||||
): string {
|
): string | null | undefined {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case Enum_Componentsetstextset_Status.Incomplete:
|
case Enum_Componentsetstextset_Status.Incomplete:
|
||||||
return langui.status_incomplete;
|
return langui.status_incomplete;
|
||||||
|
@ -300,15 +405,15 @@ export function randomInt(min: number, max: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLocalesFromLanguages(
|
export function getLocalesFromLanguages(
|
||||||
languages: {
|
languages?: Array<{
|
||||||
language: {
|
language?: {
|
||||||
data: {
|
data?: {
|
||||||
attributes: {
|
attributes?: { code: string } | null;
|
||||||
code: string;
|
} | null;
|
||||||
};
|
} | null;
|
||||||
};
|
} | null> | null
|
||||||
};
|
|
||||||
}[]
|
|
||||||
) {
|
) {
|
||||||
return languages.map((language) => language.language.data.attributes.code);
|
return languages
|
||||||
|
? languages.map((language) => language?.language?.data?.attributes?.code)
|
||||||
|
: [];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue