Merge pull request #10 from Accords-Library/develop
Better Markdawn and auto-generated tables of content
This commit is contained in:
commit
56c07b715d
|
@ -20,7 +20,6 @@
|
||||||
"turndown": "^7.1.1"
|
"turndown": "^7.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
|
||||||
"@types/node": "17.0.21",
|
"@types/node": "17.0.21",
|
||||||
"@types/react": "17.0.40",
|
"@types/react": "17.0.40",
|
||||||
"@types/react-dom": "^17.0.13",
|
"@types/react-dom": "^17.0.13",
|
||||||
|
@ -455,20 +454,6 @@
|
||||||
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/typography": {
|
|
||||||
"version": "0.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz",
|
|
||||||
"integrity": "sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"lodash.castarray": "^4.4.0",
|
|
||||||
"lodash.isplainobject": "^4.0.6",
|
|
||||||
"lodash.merge": "^4.6.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/json5": {
|
"node_modules/@types/json5": {
|
||||||
"version": "0.0.29",
|
"version": "0.0.29",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||||
|
@ -2405,18 +2390,6 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash.castarray": {
|
|
||||||
"version": "4.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
|
||||||
"integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/lodash.isplainobject": {
|
|
||||||
"version": "4.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
|
||||||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
|
@ -3950,17 +3923,6 @@
|
||||||
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@tailwindcss/typography": {
|
|
||||||
"version": "0.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz",
|
|
||||||
"integrity": "sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"lodash.castarray": "^4.4.0",
|
|
||||||
"lodash.isplainobject": "^4.0.6",
|
|
||||||
"lodash.merge": "^4.6.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@types/json5": {
|
"@types/json5": {
|
||||||
"version": "0.0.29",
|
"version": "0.0.29",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||||
|
@ -5394,18 +5356,6 @@
|
||||||
"path-exists": "^3.0.0"
|
"path-exists": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash.castarray": {
|
|
||||||
"version": "4.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
|
||||||
"integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"lodash.isplainobject": {
|
|
||||||
"version": "4.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
|
||||||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"lodash.merge": {
|
"lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
"turndown": "^7.1.1"
|
"turndown": "^7.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
|
||||||
"@types/node": "17.0.21",
|
"@types/node": "17.0.21",
|
||||||
"@types/react": "17.0.40",
|
"@types/react": "17.0.40",
|
||||||
"@types/react-dom": "^17.0.13",
|
"@types/react-dom": "^17.0.13",
|
||||||
|
|
|
@ -2,10 +2,11 @@ import {
|
||||||
GetContentQuery,
|
GetContentQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import { prettySlug } from "queries/helpers";
|
import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Img, { ImageQuality } from "components/Img";
|
import Img, { ImageQuality } from "components/Img";
|
||||||
import InsetBox from "components/InsetBox";
|
import InsetBox from "components/InsetBox";
|
||||||
|
import Chip from "components/Chip";
|
||||||
|
|
||||||
export type ThumbnailHeaderProps = {
|
export type ThumbnailHeaderProps = {
|
||||||
content: {
|
content: {
|
||||||
|
@ -39,7 +40,18 @@ export default function ThumbnailHeader(
|
||||||
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div>
|
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid place-items-center text-center">
|
<div
|
||||||
|
id={slugify(
|
||||||
|
content.titles.length > 0
|
||||||
|
? prettyinlineTitle(
|
||||||
|
content.titles[0].pre_title,
|
||||||
|
content.titles[0].title,
|
||||||
|
content.titles[0].subtitle
|
||||||
|
)
|
||||||
|
: prettySlug(content.slug)
|
||||||
|
)}
|
||||||
|
className="grid place-items-center text-center"
|
||||||
|
>
|
||||||
{content.titles.length > 0 ? (
|
{content.titles.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<p className="text-2xl">{content.titles[0].pre_title}</p>
|
<p className="text-2xl">{content.titles[0].pre_title}</p>
|
||||||
|
@ -54,22 +66,26 @@ export default function ThumbnailHeader(
|
||||||
|
|
||||||
<div className="grid grid-flow-col gap-8">
|
<div className="grid grid-flow-col gap-8">
|
||||||
{content.type && (
|
{content.type && (
|
||||||
<div className="grid place-items-center place-content-start 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>
|
||||||
<Button>
|
<div className="flex flex-row flex-wrap">
|
||||||
{content.type.data.attributes.titles.length > 0
|
<Chip>
|
||||||
? content.type.data.attributes.titles[0].title
|
{content.type.data.attributes.titles.length > 0
|
||||||
: prettySlug(content.type.data.attributes.slug)}
|
? content.type.data.attributes.titles[0].title
|
||||||
</Button>
|
: prettySlug(content.type.data.attributes.slug)}
|
||||||
|
</Chip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content.categories.data.length > 0 && (
|
{content.categories.data.length > 0 && (
|
||||||
<div className="grid place-items-center place-content-start 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>
|
||||||
{content.categories.data.map((category) => (
|
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||||
<Button key={category.id}>{category.attributes.name}</Button>
|
{content.categories.data.map((category) => (
|
||||||
))}
|
<Chip key={category.id}>{category.attributes.name}</Chip>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
import HorizontalLine from "components/HorizontalLine";
|
||||||
|
import InsetBox from "components/InsetBox";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import Markdown from "markdown-to-jsx";
|
import Markdown from "markdown-to-jsx";
|
||||||
import SceneBreak from "./SceneBreak";
|
import { slugify } from "queries/helpers";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
type ScenBreakProps = {
|
type ScenBreakProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -9,15 +12,31 @@ type ScenBreakProps = {
|
||||||
|
|
||||||
export default function Markdawn(props: ScenBreakProps): JSX.Element {
|
export default function Markdawn(props: ScenBreakProps): JSX.Element {
|
||||||
const appLayout = useAppLayout();
|
const appLayout = useAppLayout();
|
||||||
|
const text = preprocessMarkDawn(props.text);
|
||||||
|
|
||||||
if (props.text) {
|
if (text) {
|
||||||
return (
|
return (
|
||||||
<Markdown
|
<Markdown
|
||||||
className={`prose prose-p:text-justify text-black ${props.className}`}
|
className={`formatted ${props.className}`}
|
||||||
options={{
|
options={{
|
||||||
|
slugify: slugify,
|
||||||
overrides: {
|
overrides: {
|
||||||
hr: {
|
Sep: {
|
||||||
component: SceneBreak,
|
component: () => {
|
||||||
|
return <div className="my-24"></div>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SceneBreak: {
|
||||||
|
component: (props: { id: string }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id={props.id}
|
||||||
|
className={"h-0 text-center text-3xl text-dark mt-16 mb-20"}
|
||||||
|
>
|
||||||
|
* * *
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
player: {
|
player: {
|
||||||
component: () => {
|
component: () => {
|
||||||
|
@ -28,12 +47,80 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Transcript: {
|
||||||
|
component: (props) => {
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-[auto_1fr] gap-x-6 gap-y-2">
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Line: {
|
||||||
|
component: (props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<strong className="text-dark opacity-60">
|
||||||
|
{props.name}
|
||||||
|
</strong>
|
||||||
|
<p className="whitespace-pre-line">{props.children}</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
InsetBox: {
|
||||||
|
component: (props) => {
|
||||||
|
return <InsetBox>{props.children}</InsetBox>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
li: {
|
||||||
|
component: (props: { children: React.ReactNode }) => {
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
className={
|
||||||
|
props.children && props.children?.toString().length > 100
|
||||||
|
? "my-4"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Highlight: {
|
||||||
|
component: (props: { children: React.ReactNode }) => {
|
||||||
|
return <mark>{props.children}</mark>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
component: (props: { children: React.ReactNode }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HorizontalLine />
|
||||||
|
<div>{props.children}</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.text}
|
{text}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function preprocessMarkDawn(text: string): string {
|
||||||
|
let scenebreakIndex = 0;
|
||||||
|
const result = text.split("\n").map((line) => {
|
||||||
|
if (line === "* * *" || line === "---") {
|
||||||
|
scenebreakIndex++;
|
||||||
|
return `<SceneBreak id="scene-break-${scenebreakIndex}">`;
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
});
|
||||||
|
return result.join("\n");
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
type ScenBreakProps = {
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function SceneBreak(props: ScenBreakProps): JSX.Element {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={
|
|
||||||
"h-0 text-center text-3xl text-dark mt-16 mb-20" + " " + props.className
|
|
||||||
}
|
|
||||||
>
|
|
||||||
* * *
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
import { slugify } from "queries/helpers";
|
||||||
|
import { preprocessMarkDawn } from "./Markdawn";
|
||||||
|
|
||||||
|
type TOCProps = {
|
||||||
|
text: string;
|
||||||
|
title?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function TOC(props: TOCProps): JSX.Element {
|
||||||
|
const toc = getTocFromMarkdawn(preprocessMarkDawn(props.text), props.title);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl">Table of content</h3>
|
||||||
|
<ol className="text-left">
|
||||||
|
<li className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap">
|
||||||
|
<a className="" href={`#${toc.slug}`}>
|
||||||
|
{<abbr title={toc.title}>{toc.title}</abbr>}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{toc.children.map((h2, h2Index) => (
|
||||||
|
<>
|
||||||
|
<li
|
||||||
|
key={h2.slug}
|
||||||
|
className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap"
|
||||||
|
>
|
||||||
|
<span className="text-dark">{`${h2Index + 1}. `}</span>
|
||||||
|
<a href={`#${h2.slug}`}>
|
||||||
|
{<abbr title={h2.title}>{h2.title}</abbr>}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<ol className="pl-4 text-left">
|
||||||
|
{h2.children.map((h3, h3Index) => (
|
||||||
|
<li
|
||||||
|
key={h3.slug}
|
||||||
|
className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap"
|
||||||
|
>
|
||||||
|
<span className="text-dark">{`${h2Index + 1}.${
|
||||||
|
h3Index + 1
|
||||||
|
}. `}</span>
|
||||||
|
<a href={`#${h3.slug}`}>
|
||||||
|
{<abbr title={h3.title}>{h3.title}</abbr>}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TOC = {
|
||||||
|
title: string;
|
||||||
|
slug: string;
|
||||||
|
children: TOC[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getTocFromMarkdawn(text: string, title?: string): TOC {
|
||||||
|
if (!title) title = "Return to top";
|
||||||
|
let toc: TOC = { title: title, slug: slugify(title) || "", children: [] };
|
||||||
|
let h2 = -1;
|
||||||
|
let h3 = -1;
|
||||||
|
let h4 = -1;
|
||||||
|
let h5 = -1;
|
||||||
|
let scenebreak = 0;
|
||||||
|
let scenebreakIndex = 0;
|
||||||
|
text.split("\n").map((line) => {
|
||||||
|
if (line.startsWith("# ")) {
|
||||||
|
toc.slug = slugify(line);
|
||||||
|
} else if (line.startsWith("## ")) {
|
||||||
|
toc.children.push({
|
||||||
|
title: line.slice("## ".length),
|
||||||
|
slug: slugify(line),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
h2++;
|
||||||
|
h3 = -1;
|
||||||
|
h4 = -1;
|
||||||
|
h5 = -1;
|
||||||
|
scenebreak = 0;
|
||||||
|
} else if (line.startsWith("### ")) {
|
||||||
|
toc.children[h2].children.push({
|
||||||
|
title: line.slice("### ".length),
|
||||||
|
slug: slugify(line),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
h3++;
|
||||||
|
h4 = -1;
|
||||||
|
h5 = -1;
|
||||||
|
scenebreak = 0;
|
||||||
|
} else if (line.startsWith("#### ")) {
|
||||||
|
toc.children[h2].children[h3].children.push({
|
||||||
|
title: line.slice("#### ".length),
|
||||||
|
slug: slugify(line),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
h4++;
|
||||||
|
h5 = -1;
|
||||||
|
scenebreak = 0;
|
||||||
|
} else if (line.startsWith("##### ")) {
|
||||||
|
toc.children[h2].children[h3].children[h4].children.push({
|
||||||
|
title: line.slice("##### ".length),
|
||||||
|
slug: slugify(line),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
h5++;
|
||||||
|
scenebreak = 0;
|
||||||
|
} else if (line.startsWith("###### ")) {
|
||||||
|
toc.children[h2].children[h3].children[h4].children[h5].children.push({
|
||||||
|
title: line.slice("###### ".length),
|
||||||
|
slug: slugify(line),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
} else if (line.startsWith(`<SceneBreak`)) {
|
||||||
|
scenebreak++;
|
||||||
|
scenebreakIndex++;
|
||||||
|
if (h5 >= 0) {
|
||||||
|
toc.children[h2].children[h3].children[h4].children[h5].children.push({
|
||||||
|
title: `Scene break ${scenebreak}`,
|
||||||
|
slug: slugify(`scene-break-${scenebreakIndex}`),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
} else if (h4 >= 0) {
|
||||||
|
toc.children[h2].children[h3].children[h4].children.push({
|
||||||
|
title: `Scene break ${scenebreak}`,
|
||||||
|
slug: slugify(`scene-break-${scenebreakIndex}`),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
} else if (h3 >= 0) {
|
||||||
|
toc.children[h2].children[h3].children.push({
|
||||||
|
title: `Scene break ${scenebreak}`,
|
||||||
|
slug: slugify(`scene-break-${scenebreakIndex}`),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
} else if (h2 >= 0) {
|
||||||
|
toc.children[h2].children.push({
|
||||||
|
title: `Scene break ${scenebreak}`,
|
||||||
|
slug: slugify(`scene-break-${scenebreakIndex}`),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toc.children.push({
|
||||||
|
title: `Scene break ${scenebreak}`,
|
||||||
|
slug: slugify(`scene-break-${scenebreakIndex}`),
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return toc;
|
||||||
|
}
|
|
@ -12,12 +12,15 @@ export enum ContentPanelWidthSizes {
|
||||||
export default function ContentPanel(props: ContentPanelProps): JSX.Element {
|
export default function ContentPanel(props: ContentPanelProps): JSX.Element {
|
||||||
const width = props.width ? props.width : ContentPanelWidthSizes.default;
|
const width = props.width ? props.width : ContentPanelWidthSizes.default;
|
||||||
const widthCSS =
|
const widthCSS =
|
||||||
width === ContentPanelWidthSizes.default ? "max-w-[45rem]" : "w-full";
|
width === ContentPanelWidthSizes.default ? "max-w-2xl" : "w-full";
|
||||||
const prose = props.autoformat ? "prose text-justify" : "";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`grid pt-10 pb-20 px-6 desktop:py-20 desktop:px-10`}>
|
<div className={`grid pt-10 pb-20 px-6 desktop:py-20 desktop:px-10`}>
|
||||||
<main className={`${prose} ${widthCSS} place-self-center`}>
|
<main
|
||||||
|
className={`${
|
||||||
|
props.autoformat && "formatted"
|
||||||
|
} ${widthCSS} place-self-center`}
|
||||||
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -117,6 +117,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/wiki"
|
url="/wiki"
|
||||||
icon="travel_explore"
|
icon="travel_explore"
|
||||||
|
@ -136,6 +138,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
*/}
|
||||||
|
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
|
|
||||||
|
@ -147,7 +151,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
{/*
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/merch"
|
url="/merch"
|
||||||
icon="store"
|
icon="store"
|
||||||
|
@ -156,6 +160,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
*/}
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/gallery"
|
url="/gallery"
|
||||||
|
@ -166,6 +172,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/archives"
|
url="/archives"
|
||||||
icon="inventory"
|
icon="inventory"
|
||||||
|
@ -175,6 +183,9 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
*/}
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/about-us"
|
url="/about-us"
|
||||||
icon="info"
|
icon="info"
|
||||||
|
|
|
@ -6,7 +6,7 @@ export type SwitchProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Select(props: SwitchProps): JSX.Element {
|
export default function Switch(props: SwitchProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`h-6 w-12 rounded-full border-2 border-mid grid transition-colors relative cursor-pointer ${
|
className={`h-6 w-12 rounded-full border-2 border-mid grid transition-colors relative cursor-pointer ${
|
||||||
|
|
|
@ -109,6 +109,12 @@ query getWebsiteInterface($language_code: String) {
|
||||||
translation_notice
|
translation_notice
|
||||||
source_language
|
source_language
|
||||||
pronouns
|
pronouns
|
||||||
|
no_category
|
||||||
|
item
|
||||||
|
items
|
||||||
|
content
|
||||||
|
result
|
||||||
|
results
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1142,3 +1148,77 @@ query getLanguages {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query getPost($slug: String, $language_code: String) {
|
||||||
|
posts(filters: { slug: { eq: $slug } }) {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
publishedAt
|
||||||
|
updatedAt
|
||||||
|
authors {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
username
|
||||||
|
anonymize
|
||||||
|
anonymous_code
|
||||||
|
pronouns
|
||||||
|
bio(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
bio
|
||||||
|
}
|
||||||
|
languages {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avatar {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
alternativeText
|
||||||
|
caption
|
||||||
|
width
|
||||||
|
height
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
categories {
|
||||||
|
data {
|
||||||
|
id
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
short
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hidden
|
||||||
|
translations(filters: { language: { code: { eq: $language_code } } }) {
|
||||||
|
Status
|
||||||
|
title
|
||||||
|
excerpt
|
||||||
|
thumbnail {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
alternativeText
|
||||||
|
caption
|
||||||
|
width
|
||||||
|
height
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,13 @@ export enum Enum_Componentmetadatavideo_Resolution {
|
||||||
QuadHd_2160p = "QuadHD_2160p",
|
QuadHd_2160p = "QuadHD_2160p",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Enum_Componenttranslationsposts_Status {
|
||||||
|
Incomplete = "Incomplete",
|
||||||
|
Draft = "Draft",
|
||||||
|
Review = "Review",
|
||||||
|
Done = "Done",
|
||||||
|
}
|
||||||
|
|
||||||
export enum Enum_Componenttranslationschronologyitem_Status {
|
export enum Enum_Componenttranslationschronologyitem_Status {
|
||||||
Incomplete = "Incomplete",
|
Incomplete = "Incomplete",
|
||||||
Draft = "Draft",
|
Draft = "Draft",
|
||||||
|
@ -191,6 +198,12 @@ export type GetWebsiteInterfaceQuery = {
|
||||||
translation_notice: string;
|
translation_notice: string;
|
||||||
source_language: string;
|
source_language: string;
|
||||||
pronouns: string;
|
pronouns: string;
|
||||||
|
no_category: string;
|
||||||
|
item: string;
|
||||||
|
items: string;
|
||||||
|
content: string;
|
||||||
|
result: string;
|
||||||
|
results: string;
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
@ -1525,3 +1538,100 @@ export type GetLanguagesQuery = {
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type GetPostQueryVariables = Exact<{
|
||||||
|
slug: InputMaybe<Scalars["String"]>;
|
||||||
|
language_code: InputMaybe<Scalars["String"]>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type GetPostQuery = {
|
||||||
|
__typename: "Query";
|
||||||
|
posts: {
|
||||||
|
__typename: "PostEntityResponseCollection";
|
||||||
|
data: Array<{
|
||||||
|
__typename: "PostEntity";
|
||||||
|
id: string;
|
||||||
|
attributes: {
|
||||||
|
__typename: "Post";
|
||||||
|
slug: string;
|
||||||
|
publishedAt: any;
|
||||||
|
updatedAt: any;
|
||||||
|
hidden: boolean;
|
||||||
|
authors: {
|
||||||
|
__typename: "RecorderRelationResponseCollection";
|
||||||
|
data: Array<{
|
||||||
|
__typename: "RecorderEntity";
|
||||||
|
id: string;
|
||||||
|
attributes: {
|
||||||
|
__typename: "Recorder";
|
||||||
|
username: string;
|
||||||
|
anonymize: boolean;
|
||||||
|
anonymous_code: string;
|
||||||
|
pronouns: string;
|
||||||
|
bio: Array<{
|
||||||
|
__typename: "ComponentTranslationsBio";
|
||||||
|
bio: string;
|
||||||
|
}>;
|
||||||
|
languages: {
|
||||||
|
__typename: "LanguageRelationResponseCollection";
|
||||||
|
data: Array<{
|
||||||
|
__typename: "LanguageEntity";
|
||||||
|
attributes: { __typename: "Language"; code: string };
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
avatar: {
|
||||||
|
__typename: "UploadFileEntityResponse";
|
||||||
|
data: {
|
||||||
|
__typename: "UploadFileEntity";
|
||||||
|
attributes: {
|
||||||
|
__typename: "UploadFile";
|
||||||
|
name: string;
|
||||||
|
alternativeText: string;
|
||||||
|
caption: string;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
categories: {
|
||||||
|
__typename: "CategoryRelationResponseCollection";
|
||||||
|
data: Array<{
|
||||||
|
__typename: "CategoryEntity";
|
||||||
|
id: string;
|
||||||
|
attributes: {
|
||||||
|
__typename: "Category";
|
||||||
|
name: string;
|
||||||
|
short: string;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
translations: Array<{
|
||||||
|
__typename: "ComponentTranslationsPosts";
|
||||||
|
Status: Enum_Componenttranslationsposts_Status;
|
||||||
|
title: string;
|
||||||
|
excerpt: string;
|
||||||
|
body: string;
|
||||||
|
thumbnail: {
|
||||||
|
__typename: "UploadFileEntityResponse";
|
||||||
|
data: {
|
||||||
|
__typename: "UploadFileEntity";
|
||||||
|
attributes: {
|
||||||
|
__typename: "UploadFile";
|
||||||
|
name: string;
|
||||||
|
alternativeText: string;
|
||||||
|
caption: string;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -23,6 +23,8 @@ import {
|
||||||
GetLibraryItemsPreviewQueryVariables,
|
GetLibraryItemsPreviewQueryVariables,
|
||||||
GetLibraryItemsSlugsQuery,
|
GetLibraryItemsSlugsQuery,
|
||||||
GetLibraryItemsSlugsQueryVariables,
|
GetLibraryItemsSlugsQueryVariables,
|
||||||
|
GetPostQuery,
|
||||||
|
GetPostQueryVariables,
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
GetWebsiteInterfaceQueryVariables,
|
GetWebsiteInterfaceQueryVariables,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
|
@ -141,3 +143,10 @@ export async function getLanguages(
|
||||||
const query = getQueryFromOperations("getLanguages");
|
const query = getQueryFromOperations("getLanguages");
|
||||||
return await graphQL(query, JSON.stringify(variables));
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -1060,6 +1060,8 @@ input ComponentTranslationsPostsFiltersInput {
|
||||||
Status: StringFilterInput
|
Status: StringFilterInput
|
||||||
title: StringFilterInput
|
title: StringFilterInput
|
||||||
excerpt: StringFilterInput
|
excerpt: StringFilterInput
|
||||||
|
body: StringFilterInput
|
||||||
|
language: LanguageFiltersInput
|
||||||
and: [ComponentTranslationsPostsFiltersInput]
|
and: [ComponentTranslationsPostsFiltersInput]
|
||||||
or: [ComponentTranslationsPostsFiltersInput]
|
or: [ComponentTranslationsPostsFiltersInput]
|
||||||
not: ComponentTranslationsPostsFiltersInput
|
not: ComponentTranslationsPostsFiltersInput
|
||||||
|
@ -1071,6 +1073,8 @@ input ComponentTranslationsPostsInput {
|
||||||
title: String
|
title: String
|
||||||
excerpt: String
|
excerpt: String
|
||||||
thumbnail: ID
|
thumbnail: ID
|
||||||
|
body: String
|
||||||
|
language: ID
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComponentTranslationsPosts {
|
type ComponentTranslationsPosts {
|
||||||
|
@ -1079,6 +1083,8 @@ type ComponentTranslationsPosts {
|
||||||
title: String!
|
title: String!
|
||||||
excerpt: String
|
excerpt: String
|
||||||
thumbnail: UploadFileEntityResponse
|
thumbnail: UploadFileEntityResponse
|
||||||
|
body: String
|
||||||
|
language: LanguageEntityResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ENUM_COMPONENTTRANSLATIONSSCANSET_STATUS {
|
enum ENUM_COMPONENTTRANSLATIONSSCANSET_STATUS {
|
||||||
|
@ -1648,6 +1654,7 @@ input CurrencyFiltersInput {
|
||||||
symbol: StringFilterInput
|
symbol: StringFilterInput
|
||||||
code: StringFilterInput
|
code: StringFilterInput
|
||||||
rate_to_usd: FloatFilterInput
|
rate_to_usd: FloatFilterInput
|
||||||
|
display_decimals: BooleanFilterInput
|
||||||
createdAt: DateTimeFilterInput
|
createdAt: DateTimeFilterInput
|
||||||
updatedAt: DateTimeFilterInput
|
updatedAt: DateTimeFilterInput
|
||||||
and: [CurrencyFiltersInput]
|
and: [CurrencyFiltersInput]
|
||||||
|
@ -1659,12 +1666,14 @@ input CurrencyInput {
|
||||||
symbol: String
|
symbol: String
|
||||||
code: String
|
code: String
|
||||||
rate_to_usd: Float
|
rate_to_usd: Float
|
||||||
|
display_decimals: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Currency {
|
type Currency {
|
||||||
symbol: String!
|
symbol: String!
|
||||||
code: String!
|
code: String!
|
||||||
rate_to_usd: Float
|
rate_to_usd: Float!
|
||||||
|
display_decimals: Boolean!
|
||||||
createdAt: DateTime
|
createdAt: DateTime
|
||||||
updatedAt: DateTime
|
updatedAt: DateTime
|
||||||
}
|
}
|
||||||
|
@ -1916,6 +1925,7 @@ input LibraryItemFiltersInput {
|
||||||
digital: BooleanFilterInput
|
digital: BooleanFilterInput
|
||||||
primary: BooleanFilterInput
|
primary: BooleanFilterInput
|
||||||
submerchs: MerchItemFiltersInput
|
submerchs: MerchItemFiltersInput
|
||||||
|
categories: CategoryFiltersInput
|
||||||
createdAt: DateTimeFilterInput
|
createdAt: DateTimeFilterInput
|
||||||
updatedAt: DateTimeFilterInput
|
updatedAt: DateTimeFilterInput
|
||||||
and: [LibraryItemFiltersInput]
|
and: [LibraryItemFiltersInput]
|
||||||
|
@ -1942,6 +1952,7 @@ input LibraryItemInput {
|
||||||
digital: Boolean
|
digital: Boolean
|
||||||
primary: Boolean
|
primary: Boolean
|
||||||
submerchs: [ID]
|
submerchs: [ID]
|
||||||
|
categories: [ID]
|
||||||
}
|
}
|
||||||
|
|
||||||
type LibraryItem {
|
type LibraryItem {
|
||||||
|
@ -1987,6 +1998,11 @@ type LibraryItem {
|
||||||
pagination: PaginationArg = {}
|
pagination: PaginationArg = {}
|
||||||
sort: [String] = []
|
sort: [String] = []
|
||||||
): MerchItemRelationResponseCollection
|
): MerchItemRelationResponseCollection
|
||||||
|
categories(
|
||||||
|
filters: CategoryFiltersInput
|
||||||
|
pagination: PaginationArg = {}
|
||||||
|
sort: [String] = []
|
||||||
|
): CategoryRelationResponseCollection
|
||||||
createdAt: DateTime
|
createdAt: DateTime
|
||||||
updatedAt: DateTime
|
updatedAt: DateTime
|
||||||
}
|
}
|
||||||
|
@ -2107,6 +2123,7 @@ input PostFiltersInput {
|
||||||
authors: RecorderFiltersInput
|
authors: RecorderFiltersInput
|
||||||
slug: StringFilterInput
|
slug: StringFilterInput
|
||||||
categories: CategoryFiltersInput
|
categories: CategoryFiltersInput
|
||||||
|
hidden: BooleanFilterInput
|
||||||
createdAt: DateTimeFilterInput
|
createdAt: DateTimeFilterInput
|
||||||
updatedAt: DateTimeFilterInput
|
updatedAt: DateTimeFilterInput
|
||||||
publishedAt: DateTimeFilterInput
|
publishedAt: DateTimeFilterInput
|
||||||
|
@ -2120,6 +2137,7 @@ input PostInput {
|
||||||
slug: String
|
slug: String
|
||||||
categories: [ID]
|
categories: [ID]
|
||||||
translations: [ComponentTranslationsPostsInput]
|
translations: [ComponentTranslationsPostsInput]
|
||||||
|
hidden: Boolean
|
||||||
publishedAt: DateTime
|
publishedAt: DateTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2140,6 +2158,7 @@ type Post {
|
||||||
pagination: PaginationArg = {}
|
pagination: PaginationArg = {}
|
||||||
sort: [String] = []
|
sort: [String] = []
|
||||||
): [ComponentTranslationsPosts]
|
): [ComponentTranslationsPosts]
|
||||||
|
hidden: Boolean!
|
||||||
createdAt: DateTime
|
createdAt: DateTime
|
||||||
updatedAt: DateTime
|
updatedAt: DateTime
|
||||||
publishedAt: DateTime
|
publishedAt: DateTime
|
||||||
|
@ -2619,6 +2638,38 @@ input WebsiteInterfaceFiltersInput {
|
||||||
group_by: StringFilterInput
|
group_by: StringFilterInput
|
||||||
select_option_sidebar: StringFilterInput
|
select_option_sidebar: StringFilterInput
|
||||||
group: StringFilterInput
|
group: StringFilterInput
|
||||||
|
settings: StringFilterInput
|
||||||
|
theme: StringFilterInput
|
||||||
|
light: StringFilterInput
|
||||||
|
auto: StringFilterInput
|
||||||
|
dark: StringFilterInput
|
||||||
|
font_size: StringFilterInput
|
||||||
|
player_name: StringFilterInput
|
||||||
|
currency: StringFilterInput
|
||||||
|
font: StringFilterInput
|
||||||
|
calculated: StringFilterInput
|
||||||
|
status_incomplete: StringFilterInput
|
||||||
|
status_draft: StringFilterInput
|
||||||
|
status_review: StringFilterInput
|
||||||
|
status_done: StringFilterInput
|
||||||
|
incomplete: StringFilterInput
|
||||||
|
draft: StringFilterInput
|
||||||
|
review: StringFilterInput
|
||||||
|
done: StringFilterInput
|
||||||
|
status: StringFilterInput
|
||||||
|
transcribers: StringFilterInput
|
||||||
|
translators: StringFilterInput
|
||||||
|
proofreaders: StringFilterInput
|
||||||
|
transcript_notice: StringFilterInput
|
||||||
|
translation_notice: StringFilterInput
|
||||||
|
source_language: StringFilterInput
|
||||||
|
pronouns: StringFilterInput
|
||||||
|
no_category: StringFilterInput
|
||||||
|
item: StringFilterInput
|
||||||
|
items: StringFilterInput
|
||||||
|
content: StringFilterInput
|
||||||
|
result: StringFilterInput
|
||||||
|
results: StringFilterInput
|
||||||
createdAt: DateTimeFilterInput
|
createdAt: DateTimeFilterInput
|
||||||
updatedAt: DateTimeFilterInput
|
updatedAt: DateTimeFilterInput
|
||||||
and: [WebsiteInterfaceFiltersInput]
|
and: [WebsiteInterfaceFiltersInput]
|
||||||
|
@ -2707,6 +2758,38 @@ input WebsiteInterfaceInput {
|
||||||
group_by: String
|
group_by: String
|
||||||
select_option_sidebar: String
|
select_option_sidebar: String
|
||||||
group: String
|
group: String
|
||||||
|
settings: String
|
||||||
|
theme: String
|
||||||
|
light: String
|
||||||
|
auto: String
|
||||||
|
dark: String
|
||||||
|
font_size: String
|
||||||
|
player_name: String
|
||||||
|
currency: String
|
||||||
|
font: String
|
||||||
|
calculated: String
|
||||||
|
status_incomplete: String
|
||||||
|
status_draft: String
|
||||||
|
status_review: String
|
||||||
|
status_done: String
|
||||||
|
incomplete: String
|
||||||
|
draft: String
|
||||||
|
review: String
|
||||||
|
done: String
|
||||||
|
status: String
|
||||||
|
transcribers: String
|
||||||
|
translators: String
|
||||||
|
proofreaders: String
|
||||||
|
transcript_notice: String
|
||||||
|
translation_notice: String
|
||||||
|
source_language: String
|
||||||
|
pronouns: String
|
||||||
|
no_category: String
|
||||||
|
item: String
|
||||||
|
items: String
|
||||||
|
content: String
|
||||||
|
result: String
|
||||||
|
results: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteInterface {
|
type WebsiteInterface {
|
||||||
|
@ -2790,6 +2873,38 @@ type WebsiteInterface {
|
||||||
group_by: String
|
group_by: String
|
||||||
select_option_sidebar: String
|
select_option_sidebar: String
|
||||||
group: String
|
group: String
|
||||||
|
settings: String
|
||||||
|
theme: String
|
||||||
|
light: String
|
||||||
|
auto: String
|
||||||
|
dark: String
|
||||||
|
font_size: String
|
||||||
|
player_name: String
|
||||||
|
currency: String
|
||||||
|
font: String
|
||||||
|
calculated: String
|
||||||
|
status_incomplete: String
|
||||||
|
status_draft: String
|
||||||
|
status_review: String
|
||||||
|
status_done: String
|
||||||
|
incomplete: String
|
||||||
|
draft: String
|
||||||
|
review: String
|
||||||
|
done: String
|
||||||
|
status: String
|
||||||
|
transcribers: String
|
||||||
|
translators: String
|
||||||
|
proofreaders: String
|
||||||
|
transcript_notice: String
|
||||||
|
translation_notice: String
|
||||||
|
source_language: String
|
||||||
|
pronouns: String
|
||||||
|
no_category: String
|
||||||
|
item: String
|
||||||
|
items: String
|
||||||
|
content: String
|
||||||
|
result: String
|
||||||
|
results: String
|
||||||
createdAt: DateTime
|
createdAt: DateTime
|
||||||
updatedAt: DateTime
|
updatedAt: DateTime
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||||
import { GetStaticProps } from "next";
|
import { GetStaticProps } from "next";
|
||||||
import AppLayout from "components/AppLayout";
|
import AppLayout from "components/AppLayout";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import NavOption from "components/PanelComponents/NavOption";
|
||||||
|
|
||||||
interface AboutUsProps extends AppStaticProps {}
|
interface AboutUsProps extends AppStaticProps {}
|
||||||
|
|
||||||
|
@ -15,6 +16,15 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
|
||||||
title={langui.about_us}
|
title={langui.about_us}
|
||||||
description={langui.about_us_description}
|
description={langui.about_us_description}
|
||||||
/>
|
/>
|
||||||
|
<NavOption title="Accord’s Handbook" url="/about-us/handbook" border />
|
||||||
|
<NavOption
|
||||||
|
title="Site information"
|
||||||
|
url="/about-us/site-information"
|
||||||
|
border
|
||||||
|
/>
|
||||||
|
<NavOption title="FAQ" url="/about-us/faq" border />
|
||||||
|
<NavOption title="Sharing Policy" url="/about-us/sharing-policy" border />
|
||||||
|
<NavOption title="Contact us" url="/about-us/contact" border />
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import AppLayout from "components/AppLayout";
|
||||||
|
import Markdawn from "components/Markdown/Markdawn";
|
||||||
|
import ReturnButton, {
|
||||||
|
ReturnButtonType,
|
||||||
|
} from "components/PanelComponents/ReturnButton";
|
||||||
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
|
import { getPost } from "graphql/operations";
|
||||||
|
import { GetPostQuery } from "graphql/operations-types";
|
||||||
|
import { GetStaticProps } from "next";
|
||||||
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import { prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
|
interface SiteInfoProps extends AppStaticProps {
|
||||||
|
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SiteInformation(props: SiteInfoProps): JSX.Element {
|
||||||
|
const { langui, post } = props;
|
||||||
|
const contentPanel = (
|
||||||
|
<ContentPanel>
|
||||||
|
<ReturnButton
|
||||||
|
href="/about-us"
|
||||||
|
displayOn={ReturnButtonType.Both}
|
||||||
|
langui={langui}
|
||||||
|
title={langui.about_us}
|
||||||
|
className="mb-10"
|
||||||
|
/>
|
||||||
|
{post.translations.length > 0 && (
|
||||||
|
<Markdawn text={post.translations[0].body} />
|
||||||
|
)}
|
||||||
|
</ContentPanel>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navTitle={
|
||||||
|
post.translations.length > 0
|
||||||
|
? post.translations[0].title
|
||||||
|
: prettySlug(post.slug)
|
||||||
|
}
|
||||||
|
contentPanel={contentPanel}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
const props: SiteInfoProps = {
|
||||||
|
...(await getAppStaticProps(context)),
|
||||||
|
post: (
|
||||||
|
await getPost({
|
||||||
|
slug: "site-information",
|
||||||
|
language_code: context.locale || "en",
|
||||||
|
})
|
||||||
|
).posts.data[0].attributes,
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
props: props,
|
||||||
|
};
|
||||||
|
};
|
|
@ -26,6 +26,7 @@ import Chip from "components/Chip";
|
||||||
import ReactTooltip from "react-tooltip";
|
import ReactTooltip from "react-tooltip";
|
||||||
import RecorderChip from "components/RecorderChip";
|
import RecorderChip from "components/RecorderChip";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import TOC from "components/Markdown/TOC";
|
||||||
|
|
||||||
interface ContentReadProps extends AppStaticProps {
|
interface ContentReadProps extends AppStaticProps {
|
||||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
||||||
|
@ -141,6 +142,24 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
||||||
)}
|
)}
|
||||||
</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>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
|
@ -157,7 +176,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
||||||
|
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
|
|
||||||
{content.text_set.length > 0 && (
|
{content.text_set.length > 0 && content.text_set[0].text && (
|
||||||
<Markdawn text={content.text_set[0].text} />
|
<Markdawn text={content.text_set[0].text} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,10 @@ import SubPanel from "components/Panels/SubPanel";
|
||||||
import ContentPanel, {
|
import ContentPanel, {
|
||||||
ContentPanelWidthSizes,
|
ContentPanelWidthSizes,
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import { GetContentsQuery } from "graphql/operations-types";
|
import {
|
||||||
|
GetContentsQuery,
|
||||||
|
GetWebsiteInterfaceQuery,
|
||||||
|
} from "graphql/operations-types";
|
||||||
import { getContents } from "graphql/operations";
|
import { getContents } from "graphql/operations";
|
||||||
import PanelHeader from "components/PanelComponents/PanelHeader";
|
import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||||
import AppLayout from "components/AppLayout";
|
import AppLayout from "components/AppLayout";
|
||||||
|
@ -12,6 +15,7 @@ import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import Select from "components/Select";
|
import Select from "components/Select";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import Chip from "components/Chip";
|
||||||
|
|
||||||
interface ContentsProps extends AppStaticProps {
|
interface ContentsProps extends AppStaticProps {
|
||||||
contents: GetContentsQuery["contents"]["data"];
|
contents: GetContentsQuery["contents"]["data"];
|
||||||
|
@ -25,11 +29,11 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
||||||
|
|
||||||
const [groups, setGroups] = useState<GroupContentItems>(
|
const [groups, setGroups] = useState<GroupContentItems>(
|
||||||
getGroups(groupingMethod, contents)
|
getGroups(langui, groupingMethod, contents)
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setGroups(getGroups(groupingMethod, contents));
|
setGroups(getGroups(langui, groupingMethod, contents));
|
||||||
}, [langui, groupingMethod, contents]);
|
}, [langui, groupingMethod, contents]);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
|
@ -61,9 +65,14 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
{name && (
|
{name && (
|
||||||
<h2
|
<h2
|
||||||
key={"h2" + name}
|
key={"h2" + name}
|
||||||
className="text-2xl pb-2 pt-10 first-of-type:pt-0"
|
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
|
<Chip>{`${items.length} ${
|
||||||
|
items.length <= 1
|
||||||
|
? langui.result.toLowerCase()
|
||||||
|
: langui.results.toLowerCase()
|
||||||
|
}`}</Chip>
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
|
@ -127,6 +136,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function getGroups(
|
function getGroups(
|
||||||
|
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
|
||||||
groupByType: number,
|
groupByType: number,
|
||||||
items: ContentsProps["contents"]
|
items: ContentsProps["contents"]
|
||||||
): GroupContentItems {
|
): GroupContentItems {
|
||||||
|
@ -150,11 +160,11 @@ function getGroups(
|
||||||
typeGroup.set("Bakuken", []);
|
typeGroup.set("Bakuken", []);
|
||||||
typeGroup.set("YoRHa", []);
|
typeGroup.set("YoRHa", []);
|
||||||
typeGroup.set("YoRHa Boys", []);
|
typeGroup.set("YoRHa Boys", []);
|
||||||
typeGroup.set("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("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);
|
||||||
|
|
|
@ -1,146 +1,48 @@
|
||||||
import AppLayout from "components/AppLayout";
|
import AppLayout from "components/AppLayout";
|
||||||
|
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/operations-types";
|
||||||
import { GetStaticProps } from "next";
|
import { GetStaticProps } from "next";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import { prettySlug } from "queries/helpers";
|
||||||
|
|
||||||
interface HomeProps extends AppStaticProps {}
|
interface HomeProps extends AppStaticProps {
|
||||||
|
post: GetPostQuery["posts"]["data"][number]["attributes"];
|
||||||
|
}
|
||||||
|
|
||||||
export default function Home(props: HomeProps): JSX.Element {
|
export default function Home(props: HomeProps): JSX.Element {
|
||||||
|
const { post } = props;
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel autoformat>
|
<ContentPanel>
|
||||||
<div className="grid place-items-center place-content-center w-full gap-5 text-center">
|
{post.translations.length > 0 && (
|
||||||
<div className="[mask:url('/icons/accords.svg')] [mask-size:contain] [mask-repeat:no-repeat] [mask-position:center] w-32 aspect-square mobile:w-[50vw] bg-black" />
|
<Markdawn text={post.translations[0].body} />
|
||||||
<h1 className="text-5xl mb-0">Accord’s Library</h1>
|
)}
|
||||||
<h2 className="mt-0">Discover • Analyse • Translate • Archive</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>What is this?</h2>
|
|
||||||
<p>
|
|
||||||
Accord’s Library aims at gathering and archiving all of Yoko
|
|
||||||
Taro’s work. Yoko Taro is a Japanese video game director and
|
|
||||||
scenario writer. He is best-known for his work on the NieR and
|
|
||||||
Drakengard (Drag-on Dragoon) franchises. To complement his games, Yoko
|
|
||||||
Taro likes to publish side materials in the form of books, novellas,
|
|
||||||
artbooks, stage plays, manga, drama CDs, and comics. Those side
|
|
||||||
materials can be very difficult to find. His work goes all the way back
|
|
||||||
to 2003, and most of them are out of print after having been released
|
|
||||||
solely in Japan, sometimes in limited quantities. Their prices on the
|
|
||||||
second hand market have skyrocketed, ranging all the way to hundreds if
|
|
||||||
not thousand of dollars for the rarest items.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This is where this library takes its meaning, in trying to help the
|
|
||||||
community grow by providing translators, writers, and wiki’s
|
|
||||||
contributors a simple way to access these records filled with stories,
|
|
||||||
artworks, and knowledge.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
We are a small group of Yoko Taro’s fans that decided to join
|
|
||||||
forces and create a website and a community. Our motto is{" "}
|
|
||||||
<strong>Discover • Analyze • Translate • Archive</strong> (D.A.T.A. for
|
|
||||||
short). We started with the goal of gathering and archiving as much
|
|
||||||
side-materials/merch as possible. But since then, our ambition grew and
|
|
||||||
we decided to create a full-fledged website that will also include news
|
|
||||||
articles, lore, summaries, translations, and transcriptions. Hopefully
|
|
||||||
one day, we will be up there in the list of notable resources for
|
|
||||||
Drakengard and NieR fans.
|
|
||||||
</p>
|
|
||||||
<h2>What’s on this website?</h2>
|
|
||||||
<p>
|
|
||||||
<strong>
|
|
||||||
<a href="https://accords-library.com/compendium/">The Compendium</a>
|
|
||||||
</strong>
|
|
||||||
: This is where we will list every NieR/DOD/other Yoko Tato merch,
|
|
||||||
games, books, novel, stage play, CD... well everything! For each, we
|
|
||||||
will provide photos and/or scans of the content, information about what
|
|
||||||
it is, when and how it was released, size, initial price...
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>
|
|
||||||
<a href="https://accords-library.com/news/">News</a>
|
|
||||||
</strong>
|
|
||||||
: Yes because we also want to create our own content! So there you will
|
|
||||||
find translations, transcriptions, unboxing, news about future
|
|
||||||
merch/game releases, maybe some guides. We don’t see this website
|
|
||||||
as being purely a showcase of our work, but also of the community, and
|
|
||||||
as such, we will be accepting applications for becoming contributors on
|
|
||||||
the website. For the applicant, there is no deadline or article quota,
|
|
||||||
it merely means that we will have access to the website Post Writing
|
|
||||||
tools and will be able to submit a draft that can be published once
|
|
||||||
verified by an editor. Anyway, that’s at least the plan, we will
|
|
||||||
think more about this until the website’s official launch.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>
|
|
||||||
<a href="https://accords-library.com/data/">Data</a>
|
|
||||||
</strong>
|
|
||||||
: There we will publish lore/knowledge about the Yokoverse: Dictionary,
|
|
||||||
Timeline, Weapons Stories, Game summaries... We have not yet decided how
|
|
||||||
deep we want to go as they are already quite a few resources out there.{" "}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>
|
|
||||||
<a
|
|
||||||
href="https://gallery.accords-library.com/posts"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>
|
|
||||||
Gallery
|
|
||||||
</a>
|
|
||||||
</strong>
|
|
||||||
: A fully tagged Danbooru-styled gallery with currently more than a
|
|
||||||
thousand unique artworks. If you are unfamiliar with this kind of
|
|
||||||
gallery, it comes with a powerful search function that allows you to
|
|
||||||
search for specific images: want to search for images with both Caim and
|
|
||||||
Inuart, just type{" "}
|
|
||||||
<kbd>
|
|
||||||
<a
|
|
||||||
href="https://gallery.accords-library.com/posts/query=Caim%20Inuart"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>
|
|
||||||
Caim Inuart
|
|
||||||
</a>
|
|
||||||
</kbd>
|
|
||||||
. If you want images of Devola OR Popola, you can use a comma{" "}
|
|
||||||
<kbd>
|
|
||||||
<a
|
|
||||||
href="https://gallery.accords-library.com/posts/query=Popola%2CDevola"
|
|
||||||
data-type="URL"
|
|
||||||
data-id="https://gallery.accords-library.com/posts/query=Popola%2CDevola"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>
|
|
||||||
Popola,Devola
|
|
||||||
</a>
|
|
||||||
</kbd>
|
|
||||||
. You can also negate a tag: i.e. images of 9S without any pods around,
|
|
||||||
search for{" "}
|
|
||||||
<kbd>
|
|
||||||
<a
|
|
||||||
href="https://gallery.accords-library.com/posts/query=9S%20-Pods"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer noopener"
|
|
||||||
>
|
|
||||||
9S -Pods
|
|
||||||
</a>
|
|
||||||
</kbd>
|
|
||||||
. Anyway, there is a lot more to it, you can click on "Syntax
|
|
||||||
help" next to the Search button for even neater functions. Btw, you
|
|
||||||
can create an account to favorite, upvote/downvote posts, or if you want
|
|
||||||
to help tagging them. There isn’t currently a way for new users to
|
|
||||||
upload images, you’ll have to contact us first and we can decide
|
|
||||||
to enable this function on your account.
|
|
||||||
</p>
|
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AppLayout navTitle={"Home"} contentPanel={contentPanel} {...props} />;
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navTitle={
|
||||||
|
post.translations.length > 0
|
||||||
|
? post.translations[0].title
|
||||||
|
: prettySlug(post.slug)
|
||||||
|
}
|
||||||
|
contentPanel={contentPanel}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
const props: HomeProps = {
|
const props: HomeProps = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
|
post: (
|
||||||
|
await getPost({
|
||||||
|
slug: "home",
|
||||||
|
language_code: context.locale || "en",
|
||||||
|
})
|
||||||
|
).posts.data[0].attributes,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -218,13 +218,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{item.categories.data.length > 0 && (
|
{item.categories.data.length > 0 && (
|
||||||
<div>
|
<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-items-center place-content-start 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}>
|
<Chip key={category.id}>{category.attributes.name}</Chip>
|
||||||
{category.attributes.short}
|
|
||||||
</Chip>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { useEffect, useState } from "react";
|
||||||
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
||||||
import Switch from "components/Switch";
|
import Switch from "components/Switch";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import Chip from "components/Chip";
|
||||||
|
|
||||||
interface LibraryProps extends AppStaticProps {
|
interface LibraryProps extends AppStaticProps {
|
||||||
items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
|
items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
|
||||||
|
@ -116,9 +117,14 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
{name && (
|
{name && (
|
||||||
<h2
|
<h2
|
||||||
key={"h2" + name}
|
key={"h2" + name}
|
||||||
className="text-2xl pb-2 pt-10 first-of-type:pt-0"
|
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
|
<Chip>{`${items.length} ${
|
||||||
|
items.length <= 1
|
||||||
|
? langui.result.toLowerCase()
|
||||||
|
: langui.results.toLowerCase()
|
||||||
|
}`}</Chip>
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
|
@ -188,11 +194,11 @@ function getGroups(
|
||||||
typeGroup.set("Bakuken", []);
|
typeGroup.set("Bakuken", []);
|
||||||
typeGroup.set("YoRHa", []);
|
typeGroup.set("YoRHa", []);
|
||||||
typeGroup.set("YoRHa Boys", []);
|
typeGroup.set("YoRHa Boys", []);
|
||||||
typeGroup.set("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("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);
|
||||||
|
|
|
@ -19,14 +19,12 @@ import { useRouter } from "next/router";
|
||||||
import ReactTooltip from "react-tooltip";
|
import ReactTooltip from "react-tooltip";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
|
||||||
interface DataChronologyProps extends AppStaticProps {
|
interface ChronologyProps extends AppStaticProps {
|
||||||
chronologyItems: GetChronologyItemsQuery["chronologyItems"]["data"];
|
chronologyItems: GetChronologyItemsQuery["chronologyItems"]["data"];
|
||||||
chronologyEras: GetErasQuery["chronologyEras"]["data"];
|
chronologyEras: GetErasQuery["chronologyEras"]["data"];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DataChronology(
|
export default function Chronology(props: ChronologyProps): JSX.Element {
|
||||||
props: DataChronologyProps
|
|
||||||
): JSX.Element {
|
|
||||||
useTesting(props);
|
useTesting(props);
|
||||||
const { chronologyItems, chronologyEras } = props;
|
const { chronologyItems, chronologyEras } = props;
|
||||||
|
|
||||||
|
@ -133,7 +131,7 @@ export default function DataChronology(
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
const props: DataChronologyProps = {
|
const props: ChronologyProps = {
|
||||||
...(await getAppStaticProps(context)),
|
...(await getAppStaticProps(context)),
|
||||||
chronologyItems: (
|
chronologyItems: (
|
||||||
await getChronologyItems({
|
await getChronologyItems({
|
||||||
|
@ -148,7 +146,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function useTesting(props: DataChronologyProps) {
|
function useTesting(props: ChronologyProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { chronologyItems, chronologyEras } = props;
|
const { chronologyItems, chronologyEras } = props;
|
||||||
chronologyEras.map((era) => {
|
chronologyEras.map((era) => {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
|
||||||
interface WikiProps extends AppStaticProps {}
|
interface WikiProps extends AppStaticProps {}
|
||||||
|
|
||||||
export default function Hubs(props: WikiProps): JSX.Element {
|
export default function Wiki(props: WikiProps): JSX.Element {
|
||||||
const { langui } = props;
|
const { langui } = props;
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
|
|
@ -256,3 +256,20 @@ export function sortContent(
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function slugify(str: string): string {
|
||||||
|
return str
|
||||||
|
.replace(/[ÀÁÂÃÄÅàáâãäåæÆ]/g, "a")
|
||||||
|
.replace(/[çÇ]/g, "c")
|
||||||
|
.replace(/[ðÐ]/g, "d")
|
||||||
|
.replace(/[ÈÉÊËéèêë]/g, "e")
|
||||||
|
.replace(/[ÏïÎîÍíÌì]/g, "i")
|
||||||
|
.replace(/[Ññ]/g, "n")
|
||||||
|
.replace(/[øØœŒÕõÔôÓóÒò]/g, "o")
|
||||||
|
.replace(/[ÜüÛûÚúÙù]/g, "u")
|
||||||
|
.replace(/[ŸÿÝý]/g, "y")
|
||||||
|
.replace(/[^a-z0-9- ]/gi, "")
|
||||||
|
.trim()
|
||||||
|
.replace(/ /gi, "-")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
@apply bg-dark text-light;
|
@apply bg-dark text-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mark {
|
||||||
|
@apply bg-mid px-2
|
||||||
|
}
|
||||||
|
|
||||||
/* SCROLLBARS STYLING */
|
/* SCROLLBARS STYLING */
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -42,45 +46,82 @@
|
||||||
@apply bg-dark rounded-full border-[3px] border-solid border-light;
|
@apply bg-dark rounded-full border-[3px] border-solid border-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CHANGE PROSE DEFAULTS */
|
/* CHANGE FORMATTED DEFAULTS */
|
||||||
|
|
||||||
.prose,
|
.formatted h1,
|
||||||
.prose p,
|
.formatted h2,
|
||||||
.prose h1,
|
.formatted h3,
|
||||||
.prose h2,
|
.formatted h4,
|
||||||
.prose h3,
|
.formatted h5,
|
||||||
.prose h4,
|
.formatted h6 {
|
||||||
.prose h5,
|
@apply text-center;
|
||||||
.prose h6,
|
|
||||||
.prose a,
|
|
||||||
.prose strong {
|
|
||||||
@apply text-black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose a {
|
.formatted h1 {
|
||||||
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark;
|
@apply text-4xl my-16;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose footer {
|
.formatted h1 + h2 {
|
||||||
|
@apply -mt-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted h2 {
|
||||||
|
@apply text-3xl my-12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted h2 + h3 {
|
||||||
|
@apply -mt-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted h3 {
|
||||||
|
@apply text-2xl my-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted h3 + h4 {
|
||||||
|
@apply -mt-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted h4 {
|
||||||
|
@apply text-xl my-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted h5 {
|
||||||
|
@apply text-lg my-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted p,
|
||||||
|
.formatted strong {
|
||||||
|
@apply my-2 text-justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted footer {
|
||||||
@apply border-t-[3px] border-dotted pt-6;
|
@apply border-t-[3px] border-dotted pt-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose footer > div {
|
.formatted footer > div {
|
||||||
@apply my-2 px-6 py-4 rounded-xl;
|
@apply my-2 px-6 py-4 rounded-xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose footer > div:target {
|
.formatted footer > div:target {
|
||||||
@apply bg-mid shadow-inner-sm shadow-shade;
|
@apply bg-mid shadow-inner-sm shadow-shade;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose li::marker {
|
.formatted li::marker {
|
||||||
@apply text-dark;
|
@apply text-dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose blockquote {
|
.formatted blockquote {
|
||||||
@apply border-l-dark;
|
@apply border-l-dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.formatted ul {
|
||||||
|
@apply list-disc pl-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formatted ol {
|
||||||
|
@apply list-decimal pl-4;
|
||||||
|
}
|
||||||
|
|
||||||
/* INPUT */
|
/* INPUT */
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
|
|
@ -72,7 +72,6 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
require("@tailwindcss/typography"),
|
|
||||||
|
|
||||||
plugin(function ({ addUtilities }) {
|
plugin(function ({ addUtilities }) {
|
||||||
addUtilities({
|
addUtilities({
|
||||||
|
|
Loading…
Reference in New Issue