From 8de571a030f23edfe371f034bfff124690f35a8a Mon Sep 17 00:00:00 2001 From: DrMint Date: Sat, 12 Mar 2022 13:23:09 +0100 Subject: [PATCH 1/4] Removed tailwindcss/typo and use custom class instead --- package-lock.json | 50 -------- package.json | 1 - src/components/Markdown/Markdawn.tsx | 99 +++++++++++++++- src/components/Markdown/SceneBreak.tsx | 15 --- src/components/Markdown/TOC.tsx | 153 +++++++++++++++++++++++++ src/components/Panels/ContentPanel.tsx | 9 +- src/tailwind.css | 79 ++++++++++--- 7 files changed, 312 insertions(+), 94 deletions(-) delete mode 100644 src/components/Markdown/SceneBreak.tsx create mode 100644 src/components/Markdown/TOC.tsx diff --git a/package-lock.json b/package-lock.json index 8718301..3c95d9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,6 @@ "turndown": "^7.1.1" }, "devDependencies": { - "@tailwindcss/typography": "^0.5.2", "@types/node": "17.0.21", "@types/react": "17.0.40", "@types/react-dom": "^17.0.13", @@ -455,20 +454,6 @@ "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", "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": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -2405,18 +2390,6 @@ "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": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3950,17 +3923,6 @@ "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", "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": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -5394,18 +5356,6 @@ "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": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/package.json b/package.json index 20c6682..661ba85 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "turndown": "^7.1.1" }, "devDependencies": { - "@tailwindcss/typography": "^0.5.2", "@types/node": "17.0.21", "@types/react": "17.0.40", "@types/react-dom": "^17.0.13", diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx index 38bf661..6414a1e 100644 --- a/src/components/Markdown/Markdawn.tsx +++ b/src/components/Markdown/Markdawn.tsx @@ -1,6 +1,9 @@ +import HorizontalLine from "components/HorizontalLine"; +import InsetBox from "components/InsetBox"; import { useAppLayout } from "contexts/AppLayoutContext"; import Markdown from "markdown-to-jsx"; -import SceneBreak from "./SceneBreak"; +import { slugify } from "queries/helpers"; +import React from "react"; type ScenBreakProps = { className?: string; @@ -9,15 +12,31 @@ type ScenBreakProps = { export default function Markdawn(props: ScenBreakProps): JSX.Element { const appLayout = useAppLayout(); + const text = preprocessMarkDawn(props.text); - if (props.text) { + if (text) { return ( { + return
; + }, + }, + SceneBreak: { + component: (props: { id: string }) => { + return ( +
+ * * * +
+ ); + }, }, player: { component: () => { @@ -28,12 +47,80 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { ); }, }, + Transcript: { + component: (props) => { + return ( +
+ {props.children} +
+ ); + }, + }, + Line: { + component: (props) => { + return ( + <> + + {props.name} + +

{props.children}

+ + ); + }, + }, + InsetBox: { + component: (props) => { + return {props.children}; + }, + }, + li: { + component: (props: { children: React.ReactNode }) => { + return ( +
  • 100 + ? "my-4" + : "" + } + > + {props.children} +
  • + ); + }, + }, + Highlight: { + component: (props: { children: React.ReactNode }) => { + return {props.children}; + }, + }, + footer: { + component: (props: { children: React.ReactNode }) => { + return ( + <> + +
    {props.children}
    + + ); + }, + }, }, }} > - {props.text} + {text}
    ); } return <>; } + +export function preprocessMarkDawn(text: string): string { + let scenebreakIndex = 0; + const result = text.split("\n").map((line) => { + if (line === "* * *" || line === "---") { + scenebreakIndex++; + return ``; + } + return line; + }); + return result.join("\n"); +} diff --git a/src/components/Markdown/SceneBreak.tsx b/src/components/Markdown/SceneBreak.tsx deleted file mode 100644 index a636120..0000000 --- a/src/components/Markdown/SceneBreak.tsx +++ /dev/null @@ -1,15 +0,0 @@ -type ScenBreakProps = { - className?: string; -}; - -export default function SceneBreak(props: ScenBreakProps): JSX.Element { - return ( -
    - * * * -
    - ); -} diff --git a/src/components/Markdown/TOC.tsx b/src/components/Markdown/TOC.tsx new file mode 100644 index 0000000..ff0c15f --- /dev/null +++ b/src/components/Markdown/TOC.tsx @@ -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 ( +
    +

    Table of content

    +
      +
    1. + + {{toc.title}} + +
    2. + {toc.children.map((h2, h2Index) => ( + <> +
    3. + {`${h2Index + 1}. `} + + {{h2.title}} + +
    4. +
        + {h2.children.map((h3, h3Index) => ( +
      1. + {`${h2Index + 1}.${ + h3Index + 1 + }. `} + + {{h3.title}} + +
      2. + ))} +
      + + ))} +
    +
    + ); +} + +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(`= 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; +} diff --git a/src/components/Panels/ContentPanel.tsx b/src/components/Panels/ContentPanel.tsx index 5b0dfa5..513f864 100644 --- a/src/components/Panels/ContentPanel.tsx +++ b/src/components/Panels/ContentPanel.tsx @@ -12,12 +12,15 @@ export enum ContentPanelWidthSizes { export default function ContentPanel(props: ContentPanelProps): JSX.Element { const width = props.width ? props.width : ContentPanelWidthSizes.default; const widthCSS = - width === ContentPanelWidthSizes.default ? "max-w-[45rem]" : "w-full"; - const prose = props.autoformat ? "prose text-justify" : ""; + width === ContentPanelWidthSizes.default ? "max-w-2xl" : "w-full"; return (
    -
    +
    {props.children}
    diff --git a/src/tailwind.css b/src/tailwind.css index e1aa100..a17a243 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -24,6 +24,10 @@ @apply bg-dark text-light; } + mark { + @apply bg-mid px-2 + } + /* SCROLLBARS STYLING */ * { @@ -42,45 +46,82 @@ @apply bg-dark rounded-full border-[3px] border-solid border-light; } - /* CHANGE PROSE DEFAULTS */ + /* CHANGE FORMATTED DEFAULTS */ - .prose, - .prose p, - .prose h1, - .prose h2, - .prose h3, - .prose h4, - .prose h5, - .prose h6, - .prose a, - .prose strong { - @apply text-black; + .formatted h1, + .formatted h2, + .formatted h3, + .formatted h4, + .formatted h5, + .formatted h6 { + @apply text-center; } - .prose a { - @apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark; + .formatted h1 { + @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; } - .prose footer > div { + .formatted footer > div { @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; } - .prose li::marker { + .formatted li::marker { @apply text-dark; } - .prose blockquote { + .formatted blockquote { @apply border-l-dark; } + .formatted ul { + @apply list-disc pl-4; + } + + .formatted ol { + @apply list-decimal pl-4; + } + /* INPUT */ input { From 6d3a9c84b30e4ecc2438e07df384989549b3000a Mon Sep 17 00:00:00 2001 From: DrMint Date: Sat, 12 Mar 2022 13:26:41 +0100 Subject: [PATCH 2/4] Use pages from Strapi instead of hardcoded ones --- src/graphql/operation.graphql | 80 ++++++++++++ src/graphql/operations-types.ts | 110 +++++++++++++++++ src/graphql/operations.ts | 9 ++ src/graphql/schema.graphql | 117 +++++++++++++++++- src/pages/about-us/index.tsx | 10 ++ src/pages/about-us/site-information.tsx | 60 +++++++++ src/pages/index.tsx | 156 +++++------------------- 7 files changed, 414 insertions(+), 128 deletions(-) create mode 100644 src/pages/about-us/site-information.tsx diff --git a/src/graphql/operation.graphql b/src/graphql/operation.graphql index 0d7a7be..cefdb37 100644 --- a/src/graphql/operation.graphql +++ b/src/graphql/operation.graphql @@ -109,6 +109,12 @@ query getWebsiteInterface($language_code: String) { translation_notice source_language 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 + } + } + } + } +} diff --git a/src/graphql/operations-types.ts b/src/graphql/operations-types.ts index 7735c06..972010f 100644 --- a/src/graphql/operations-types.ts +++ b/src/graphql/operations-types.ts @@ -48,6 +48,13 @@ export enum Enum_Componentmetadatavideo_Resolution { QuadHd_2160p = "QuadHD_2160p", } +export enum Enum_Componenttranslationsposts_Status { + Incomplete = "Incomplete", + Draft = "Draft", + Review = "Review", + Done = "Done", +} + export enum Enum_Componenttranslationschronologyitem_Status { Incomplete = "Incomplete", Draft = "Draft", @@ -191,6 +198,12 @@ export type GetWebsiteInterfaceQuery = { translation_notice: string; source_language: 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; + language_code: InputMaybe; +}>; + +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; + }; + }; + }; + }>; + }; + }>; + }; +}; diff --git a/src/graphql/operations.ts b/src/graphql/operations.ts index 28541db..e309b2f 100644 --- a/src/graphql/operations.ts +++ b/src/graphql/operations.ts @@ -23,6 +23,8 @@ import { GetLibraryItemsPreviewQueryVariables, GetLibraryItemsSlugsQuery, GetLibraryItemsSlugsQueryVariables, + GetPostQuery, + GetPostQueryVariables, GetWebsiteInterfaceQuery, GetWebsiteInterfaceQueryVariables, } from "graphql/operations-types"; @@ -141,3 +143,10 @@ export async function getLanguages( const query = getQueryFromOperations("getLanguages"); return await graphQL(query, JSON.stringify(variables)); } + +export async function getPost( + variables: GetPostQueryVariables +): Promise { + const query = getQueryFromOperations("getPost"); + return await graphQL(query, JSON.stringify(variables)); +} diff --git a/src/graphql/schema.graphql b/src/graphql/schema.graphql index 69d7f5f..cf8f6ed 100644 --- a/src/graphql/schema.graphql +++ b/src/graphql/schema.graphql @@ -1060,6 +1060,8 @@ input ComponentTranslationsPostsFiltersInput { Status: StringFilterInput title: StringFilterInput excerpt: StringFilterInput + body: StringFilterInput + language: LanguageFiltersInput and: [ComponentTranslationsPostsFiltersInput] or: [ComponentTranslationsPostsFiltersInput] not: ComponentTranslationsPostsFiltersInput @@ -1071,6 +1073,8 @@ input ComponentTranslationsPostsInput { title: String excerpt: String thumbnail: ID + body: String + language: ID } type ComponentTranslationsPosts { @@ -1079,6 +1083,8 @@ type ComponentTranslationsPosts { title: String! excerpt: String thumbnail: UploadFileEntityResponse + body: String + language: LanguageEntityResponse } enum ENUM_COMPONENTTRANSLATIONSSCANSET_STATUS { @@ -1648,6 +1654,7 @@ input CurrencyFiltersInput { symbol: StringFilterInput code: StringFilterInput rate_to_usd: FloatFilterInput + display_decimals: BooleanFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput and: [CurrencyFiltersInput] @@ -1659,12 +1666,14 @@ input CurrencyInput { symbol: String code: String rate_to_usd: Float + display_decimals: Boolean } type Currency { symbol: String! code: String! - rate_to_usd: Float + rate_to_usd: Float! + display_decimals: Boolean! createdAt: DateTime updatedAt: DateTime } @@ -1916,6 +1925,7 @@ input LibraryItemFiltersInput { digital: BooleanFilterInput primary: BooleanFilterInput submerchs: MerchItemFiltersInput + categories: CategoryFiltersInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput and: [LibraryItemFiltersInput] @@ -1942,6 +1952,7 @@ input LibraryItemInput { digital: Boolean primary: Boolean submerchs: [ID] + categories: [ID] } type LibraryItem { @@ -1987,6 +1998,11 @@ type LibraryItem { pagination: PaginationArg = {} sort: [String] = [] ): MerchItemRelationResponseCollection + categories( + filters: CategoryFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): CategoryRelationResponseCollection createdAt: DateTime updatedAt: DateTime } @@ -2107,6 +2123,7 @@ input PostFiltersInput { authors: RecorderFiltersInput slug: StringFilterInput categories: CategoryFiltersInput + hidden: BooleanFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput publishedAt: DateTimeFilterInput @@ -2120,6 +2137,7 @@ input PostInput { slug: String categories: [ID] translations: [ComponentTranslationsPostsInput] + hidden: Boolean publishedAt: DateTime } @@ -2140,6 +2158,7 @@ type Post { pagination: PaginationArg = {} sort: [String] = [] ): [ComponentTranslationsPosts] + hidden: Boolean! createdAt: DateTime updatedAt: DateTime publishedAt: DateTime @@ -2619,6 +2638,38 @@ input WebsiteInterfaceFiltersInput { group_by: StringFilterInput select_option_sidebar: 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 updatedAt: DateTimeFilterInput and: [WebsiteInterfaceFiltersInput] @@ -2707,6 +2758,38 @@ input WebsiteInterfaceInput { group_by: String select_option_sidebar: 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 { @@ -2790,6 +2873,38 @@ type WebsiteInterface { group_by: String select_option_sidebar: 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 updatedAt: DateTime } diff --git a/src/pages/about-us/index.tsx b/src/pages/about-us/index.tsx index 93d8cd2..32fdb35 100644 --- a/src/pages/about-us/index.tsx +++ b/src/pages/about-us/index.tsx @@ -3,6 +3,7 @@ import PanelHeader from "components/PanelComponents/PanelHeader"; import { GetStaticProps } from "next"; import AppLayout from "components/AppLayout"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import NavOption from "components/PanelComponents/NavOption"; interface AboutUsProps extends AppStaticProps {} @@ -15,6 +16,15 @@ export default function AboutUs(props: AboutUsProps): JSX.Element { title={langui.about_us} description={langui.about_us_description} /> + + + + + ); return ( diff --git a/src/pages/about-us/site-information.tsx b/src/pages/about-us/site-information.tsx new file mode 100644 index 0000000..8ff04c8 --- /dev/null +++ b/src/pages/about-us/site-information.tsx @@ -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 = ( + + + {post.translations.length > 0 && ( + + )} + + ); + + return ( + 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, + }; +}; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 374325c..5bdd564 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,146 +1,48 @@ import AppLayout from "components/AppLayout"; +import Markdawn from "components/Markdown/Markdawn"; 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 HomeProps extends AppStaticProps {} +interface HomeProps extends AppStaticProps { + post: GetPostQuery["posts"]["data"][number]["attributes"]; +} export default function Home(props: HomeProps): JSX.Element { + const { post } = props; const contentPanel = ( - -
    -
    -

    Accord’s Library

    -

    Discover • Analyse • Translate • Archive

    -
    - -

    What is this?

    -

    - 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.  -

    -

    - 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. -

    -

    - 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{" "} - Discover • Analyze • Translate • Archive (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. -

    -

    What’s on this website?

    -

    - - The Compendium - - : 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... -

    -

    - - News - - : 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. -

    -

    - - Data - - : 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.{" "} -

    -

    - - - Gallery - - - : 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{" "} - - - Caim Inuart - - - . If you want images of Devola OR Popola, you can use a comma{" "} - - - Popola,Devola - - - . You can also negate a tag: i.e. images of 9S without any pods around, - search for{" "} - - - 9S -Pods - - - . 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. -

    + + {post.translations.length > 0 && ( + + )} ); - return ; + return ( + 0 + ? post.translations[0].title + : prettySlug(post.slug) + } + contentPanel={contentPanel} + {...props} + /> + ); } export const getStaticProps: GetStaticProps = async (context) => { const props: HomeProps = { ...(await getAppStaticProps(context)), + post: ( + await getPost({ + slug: "home", + language_code: context.locale || "en", + }) + ).posts.data[0].attributes, }; return { props: props, From b213447c4968e1e55ad2e46291d35eb64d8f96b3 Mon Sep 17 00:00:00 2001 From: DrMint Date: Sat, 12 Mar 2022 13:27:21 +0100 Subject: [PATCH 3/4] Content pages now display the table of content --- src/components/Content/ThumbnailHeader.tsx | 40 +++++++++++++++------- src/components/Panels/MainPanel.tsx | 13 ++++++- src/pages/contents/[slug]/read.tsx | 15 ++++++++ src/pages/contents/index.tsx | 22 ++++++++---- src/pages/library/[slug].tsx | 8 ++--- src/pages/library/index.tsx | 12 +++++-- src/queries/helpers.ts | 17 +++++++++ 7 files changed, 100 insertions(+), 27 deletions(-) diff --git a/src/components/Content/ThumbnailHeader.tsx b/src/components/Content/ThumbnailHeader.tsx index 5ae6da6..b9bfd44 100644 --- a/src/components/Content/ThumbnailHeader.tsx +++ b/src/components/Content/ThumbnailHeader.tsx @@ -2,10 +2,11 @@ import { GetContentQuery, GetWebsiteInterfaceQuery, } from "graphql/operations-types"; -import { prettySlug } from "queries/helpers"; +import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers"; import Button from "components/Button"; import Img, { ImageQuality } from "components/Img"; import InsetBox from "components/InsetBox"; +import Chip from "components/Chip"; export type ThumbnailHeaderProps = { content: { @@ -39,7 +40,18 @@ export default function ThumbnailHeader(
    )}
    -
    +
    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[0].pre_title}

    @@ -54,22 +66,26 @@ export default function ThumbnailHeader(
    {content.type && ( -
    +

    {langui.type}

    - +
    + + {content.type.data.attributes.titles.length > 0 + ? content.type.data.attributes.titles[0].title + : prettySlug(content.type.data.attributes.slug)} + +
    )} {content.categories.data.length > 0 && ( -
    +

    {langui.categories}

    - {content.categories.data.map((category) => ( - - ))} +
    + {content.categories.data.map((category) => ( + {category.attributes.name} + ))} +
    )}
    diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx index f1928fa..5ea88c6 100644 --- a/src/components/Panels/MainPanel.tsx +++ b/src/components/Panels/MainPanel.tsx @@ -117,6 +117,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { onClick={() => appLayout.setMainPanelOpen(false)} /> + {/* + appLayout.setMainPanelOpen(false)} /> + + */} @@ -147,7 +151,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { reduced={appLayout.mainPanelReduced && isDesktop} onClick={() => appLayout.setMainPanelOpen(false)} /> - + {/* appLayout.setMainPanelOpen(false)} /> + + */} appLayout.setMainPanelOpen(false)} /> + {/* + appLayout.setMainPanelOpen(false)} /> + + */} + )} + + + 0 + ? prettyinlineTitle( + content.titles[0].pre_title, + content.titles[0].title, + content.titles[0].subtitle + ) + : prettySlug(content.slug) + } + /> ); const contentPanel = ( diff --git a/src/pages/contents/index.tsx b/src/pages/contents/index.tsx index be8b767..77fe5ed 100644 --- a/src/pages/contents/index.tsx +++ b/src/pages/contents/index.tsx @@ -3,7 +3,10 @@ import SubPanel from "components/Panels/SubPanel"; import ContentPanel, { ContentPanelWidthSizes, } from "components/Panels/ContentPanel"; -import { GetContentsQuery } from "graphql/operations-types"; +import { + GetContentsQuery, + GetWebsiteInterfaceQuery, +} from "graphql/operations-types"; import { getContents } from "graphql/operations"; import PanelHeader from "components/PanelComponents/PanelHeader"; import AppLayout from "components/AppLayout"; @@ -12,6 +15,7 @@ import { prettyinlineTitle, prettySlug } from "queries/helpers"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import Select from "components/Select"; import { useEffect, useState } from "react"; +import Chip from "components/Chip"; interface ContentsProps extends AppStaticProps { contents: GetContentsQuery["contents"]["data"]; @@ -25,11 +29,11 @@ export default function Contents(props: ContentsProps): JSX.Element { const [groupingMethod, setGroupingMethod] = useState(-1); const [groups, setGroups] = useState( - getGroups(groupingMethod, contents) + getGroups(langui, groupingMethod, contents) ); useEffect(() => { - setGroups(getGroups(groupingMethod, contents)); + setGroups(getGroups(langui, groupingMethod, contents)); }, [langui, groupingMethod, contents]); const subPanel = ( @@ -61,9 +65,14 @@ export default function Contents(props: ContentsProps): JSX.Element { {name && (

    {name} + {`${items.length} ${ + items.length <= 1 + ? langui.result.toLowerCase() + : langui.results.toLowerCase() + }`}

    )}
    { }; function getGroups( + langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"], groupByType: number, items: ContentsProps["contents"] ): GroupContentItems { @@ -150,11 +160,11 @@ function getGroups( typeGroup.set("Bakuken", []); typeGroup.set("YoRHa", []); typeGroup.set("YoRHa Boys", []); - typeGroup.set("No category", []); + typeGroup.set(langui.no_category, []); items.map((item) => { if (item.attributes.categories.data.length === 0) { - typeGroup.get("No category")?.push(item); + typeGroup.get(langui.no_category)?.push(item); } else { item.attributes.categories.data.map((category) => { typeGroup.get(category.attributes.name)?.push(item); diff --git a/src/pages/library/[slug].tsx b/src/pages/library/[slug].tsx index d37c98a..7fcd1fe 100644 --- a/src/pages/library/[slug].tsx +++ b/src/pages/library/[slug].tsx @@ -218,13 +218,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
    {item.categories.data.length > 0 && ( -
    +

    {langui.categories}

    -
    +
    {item.categories.data.map((category) => ( - - {category.attributes.short} - + {category.attributes.name} ))}
    diff --git a/src/pages/library/index.tsx b/src/pages/library/index.tsx index ed121d9..37e6008 100644 --- a/src/pages/library/index.tsx +++ b/src/pages/library/index.tsx @@ -17,6 +17,7 @@ import { useEffect, useState } from "react"; import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers"; import Switch from "components/Switch"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import Chip from "components/Chip"; interface LibraryProps extends AppStaticProps { items: GetLibraryItemsPreviewQuery["libraryItems"]["data"]; @@ -116,9 +117,14 @@ export default function Library(props: LibraryProps): JSX.Element { {name && (

    {name} + {`${items.length} ${ + items.length <= 1 + ? langui.result.toLowerCase() + : langui.results.toLowerCase() + }`}

    )}
    { if (item.attributes.categories.data.length === 0) { - typeGroup.get("No category")?.push(item); + typeGroup.get(langui.no_category)?.push(item); } else { item.attributes.categories.data.map((category) => { typeGroup.get(category.attributes.name)?.push(item); diff --git a/src/queries/helpers.ts b/src/queries/helpers.ts index 6e30470..bbf5786 100644 --- a/src/queries/helpers.ts +++ b/src/queries/helpers.ts @@ -256,3 +256,20 @@ export function sortContent( 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(); +} From 28ac9012ffec0c08cb554acc1ed84213d0e34e73 Mon Sep 17 00:00:00 2001 From: DrMint Date: Sat, 12 Mar 2022 14:03:26 +0100 Subject: [PATCH 4/4] Fixed errors that prevented building --- src/components/Switch.tsx | 2 +- src/pages/contents/[slug]/read.tsx | 32 +++++++++++++++++------------- src/pages/wiki/chronology.tsx | 10 ++++------ src/pages/wiki/index.tsx | 2 +- tailwind.config.js | 1 - 5 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx index 6f33b96..72cb871 100644 --- a/src/components/Switch.tsx +++ b/src/components/Switch.tsx @@ -6,7 +6,7 @@ export type SwitchProps = { className?: string; }; -export default function Select(props: SwitchProps): JSX.Element { +export default function Switch(props: SwitchProps): JSX.Element { return (
    )} - - 0 - ? prettyinlineTitle( - content.titles[0].pre_title, - content.titles[0].title, - content.titles[0].subtitle - ) - : prettySlug(content.slug) - } - /> + {content.text_set.length > 0 && content.text_set[0].text && ( + <> + + 0 + ? prettyinlineTitle( + content.titles[0].pre_title, + content.titles[0].title, + content.titles[0].subtitle + ) + : prettySlug(content.slug) + } + /> + + )} ); const contentPanel = ( @@ -172,7 +176,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { - {content.text_set.length > 0 && ( + {content.text_set.length > 0 && content.text_set[0].text && ( )}
    diff --git a/src/pages/wiki/chronology.tsx b/src/pages/wiki/chronology.tsx index 1a58ac2..b006c03 100644 --- a/src/pages/wiki/chronology.tsx +++ b/src/pages/wiki/chronology.tsx @@ -19,14 +19,12 @@ import { useRouter } from "next/router"; import ReactTooltip from "react-tooltip"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; -interface DataChronologyProps extends AppStaticProps { +interface ChronologyProps extends AppStaticProps { chronologyItems: GetChronologyItemsQuery["chronologyItems"]["data"]; chronologyEras: GetErasQuery["chronologyEras"]["data"]; } -export default function DataChronology( - props: DataChronologyProps -): JSX.Element { +export default function Chronology(props: ChronologyProps): JSX.Element { useTesting(props); const { chronologyItems, chronologyEras } = props; @@ -133,7 +131,7 @@ export default function DataChronology( } export const getStaticProps: GetStaticProps = async (context) => { - const props: DataChronologyProps = { + const props: ChronologyProps = { ...(await getAppStaticProps(context)), chronologyItems: ( await getChronologyItems({ @@ -148,7 +146,7 @@ export const getStaticProps: GetStaticProps = async (context) => { }; }; -function useTesting(props: DataChronologyProps) { +function useTesting(props: ChronologyProps) { const router = useRouter(); const { chronologyItems, chronologyEras } = props; chronologyEras.map((era) => { diff --git a/src/pages/wiki/index.tsx b/src/pages/wiki/index.tsx index 1b0b1f1..463b482 100644 --- a/src/pages/wiki/index.tsx +++ b/src/pages/wiki/index.tsx @@ -6,7 +6,7 @@ import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; interface WikiProps extends AppStaticProps {} -export default function Hubs(props: WikiProps): JSX.Element { +export default function Wiki(props: WikiProps): JSX.Element { const { langui } = props; const subPanel = ( diff --git a/tailwind.config.js b/tailwind.config.js index 4a84db7..0f9f6b4 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -72,7 +72,6 @@ module.exports = { }, }, plugins: [ - require("@tailwindcss/typography"), plugin(function ({ addUtilities }) { addUtilities({