From a085a8b95c0c0ff3b8087188d8dd640c9f434f9f Mon Sep 17 00:00:00 2001 From: DrMint Date: Sun, 27 Feb 2022 08:17:58 +0100 Subject: [PATCH] Added testing and display recorders info --- .gitignore | 4 + package-lock.json | 32 +- package.json | 4 +- public/site.webmanifest | 50 ++- run_accords_build.sh | 2 +- run_accords_testing.sh | 2 + src/components/AppLayout.tsx | 62 ++-- src/components/Chip.tsx | 15 +- .../Chronology/ChronologyItemComponent.tsx | 6 +- src/components/Content/ThumbnailHeader.tsx | 6 +- src/components/Img.tsx | 50 ++- src/components/PanelComponents/NavOption.tsx | 17 +- src/components/Panels/MainPanel.tsx | 3 + src/components/RecorderChip.tsx | 60 ++++ src/graphql/operation.graphql | 42 ++- src/graphql/operations-types.ts | 52 ++- src/graphql/schema.graphql | 321 ++++++++++++++++-- src/pages/_document.tsx | 11 +- src/pages/contents/[slug]/index.tsx | 3 + src/pages/contents/[slug]/read.tsx | 207 ++++++++++- src/pages/wiki/chronology.tsx | 57 ++-- src/queries/helpers.ts | 65 +++- src/tailwind.css | 4 + testing_logs/.gitkeep | 0 tsconfig.json | 1 + 25 files changed, 914 insertions(+), 162 deletions(-) create mode 100755 run_accords_testing.sh create mode 100644 src/components/RecorderChip.tsx create mode 100644 testing_logs/.gitkeep diff --git a/.gitignore b/.gitignore index 88b6f0d..027613e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +/testing_logs/* + # dependencies /node_modules /.pnp @@ -35,3 +37,5 @@ yarn-error.log* # typescript *.tsbuildinfo + +!.gitkeep diff --git a/package-lock.json b/package-lock.json index 69604da..5628ae9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "accords-library.com", "dependencies": { "@fontsource/material-icons": "^4.5.2", "@fontsource/material-icons-rounded": "^4.5.2", @@ -21,6 +22,7 @@ "@tailwindcss/typography": "^0.5.2", "@types/node": "17.0.18", "@types/react": "17.0.39", + "@types/react-dom": "^17.0.11", "eslint": "8.9.0", "eslint-config-next": "12.1.0", "tailwindcss": "^3.0.23", @@ -496,6 +498,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-dom": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/scheduler": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", @@ -976,7 +987,6 @@ "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -2510,17 +2520,6 @@ "integrity": "sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==", "dependencies": { "@next/env": "12.1.0", - "@next/swc-android-arm64": "12.1.0", - "@next/swc-darwin-arm64": "12.1.0", - "@next/swc-darwin-x64": "12.1.0", - "@next/swc-linux-arm-gnueabihf": "12.1.0", - "@next/swc-linux-arm64-gnu": "12.1.0", - "@next/swc-linux-arm64-musl": "12.1.0", - "@next/swc-linux-x64-gnu": "12.1.0", - "@next/swc-linux-x64-musl": "12.1.0", - "@next/swc-win32-arm64-msvc": "12.1.0", - "@next/swc-win32-ia32-msvc": "12.1.0", - "@next/swc-win32-x64-msvc": "12.1.0", "caniuse-lite": "^1.0.30001283", "postcss": "8.4.5", "styled-jsx": "5.0.0", @@ -3986,6 +3985,15 @@ "csstype": "^3.0.2" } }, + "@types/react-dom": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/scheduler": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", diff --git a/package.json b/package.json index f295064..5044c59 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint", - "text": "NODE_ENV=test next build" + "lint": "next lint" }, "dependencies": { "@fontsource/material-icons": "^4.5.2", @@ -25,6 +24,7 @@ "@tailwindcss/typography": "^0.5.2", "@types/node": "17.0.18", "@types/react": "17.0.39", + "@types/react-dom": "^17.0.11", "eslint": "8.9.0", "eslint-config-next": "12.1.0", "tailwindcss": "^3.0.23", diff --git a/public/site.webmanifest b/public/site.webmanifest index 4308fbd..6828582 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1,11 +1,10 @@ { - "name": "Accord's Library", - "short_name": "Accord's Lib", - "start_url": ".", - "display": "standalone", "background_color": "#FFEDD8", - "theme_color": "#FFEDD8", + "categories": ["books", "education", "entertainment", "news", "games"], "description": "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.", + "dir": "auto", + "display": "fullscreen", + "icons": [ { "src": "/android-chrome-192x192.png", @@ -17,5 +16,44 @@ "sizes": "512x512", "type": "image/png" } - ] + ], + + "name": "Accord's Library", + "short_name": "Accord's Lib", + "start_url": ".", + + "shortcuts": [ + { + "name": "Library", + "url": "/library", + "description": "Browse all physical and digital media" + }, + { + "name": "Contents", + "url": "/contents", + "description": "Explore all content and filter by type or category" + }, + { + "name": "Wiki", + "url": "/wiki", + "description": "An encyclopedia for everything related to DrakeNieR" + }, + { + "name": "Chronicles", + "url": "/chronicles", + "description": "Experience all events and content in chronological order" + }, + { + "name": "News", + "url": "/news", + "description": "All the latest info" + }, + { + "name": "Gallery", + "url": "/gallery", + "description": "Thousands of offcial artworks" + } + ], + + "theme_color": "#FFEDD8" } diff --git a/run_accords_build.sh b/run_accords_build.sh index 2e23821..e63f0de 100755 --- a/run_accords_build.sh +++ b/run_accords_build.sh @@ -1 +1 @@ -npx next build +npx next build \ No newline at end of file diff --git a/run_accords_testing.sh b/run_accords_testing.sh new file mode 100755 index 0000000..0ea2be6 --- /dev/null +++ b/run_accords_testing.sh @@ -0,0 +1,2 @@ +NODE_ENV=test +npx next build |& tee ./testing_logs/$(date +"%Y-%m-%d---%H-%M-%S").log \ No newline at end of file diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 3bac0e7..40f5890 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -7,7 +7,7 @@ import Head from "next/head"; import { useSwipeable } from "react-swipeable"; import { useRouter } from "next/router"; import Button from "components/Button"; -import { getOgImage, prettyLanguage } from "queries/helpers"; +import { getOgImage, OgImage, prettyLanguage } from "queries/helpers"; import { useMediaCoarse, useMediaMobile } from "hooks/useMediaQuery"; import ReactTooltip from "react-tooltip"; import { useAppLayout } from "contexts/AppLayoutContext"; @@ -22,10 +22,10 @@ type AppLayoutProps = { navTitle: string; thumbnail?: StrapiImage; description?: string; + extra?: React.ReactNode; }; export default function AppLayout(props: AppLayoutProps): JSX.Element { - const titlePrefix = "Accord’s Library"; const router = useRouter(); const isMobile = useMediaMobile(); const isCoarse = useMediaCoarse(); @@ -75,9 +75,21 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { const turnSubIntoContent = props.subPanel && !props.contentPanel; - const ogImage = getOgImage(ImageQuality.Og, props.thumbnail); + const titlePrefix = "Accord’s Library"; + const metaImage: OgImage = props.thumbnail + ? getOgImage(ImageQuality.Og, props.thumbnail) + : { + image: "/default_og.jpg", + width: 1200, + height: 630, + alt: "Accord's Library Logo", + }; const ogTitle = props.title ? props.title : props.navTitle; + const metaDescription = props.description + ? props.description + : "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."; + return (
- - + + )} - {ogImage && ( - <> - - - - - - - + + + + + + + - - - )} + {/* Navbar */} @@ -263,6 +265,8 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg after:!border-r-light text-left !text-black" />
+ + {props.extra}
); } diff --git a/src/components/Chip.tsx b/src/components/Chip.tsx index 20b4c6b..e490ddc 100644 --- a/src/components/Chip.tsx +++ b/src/components/Chip.tsx @@ -1,12 +1,25 @@ type ChipProps = { className?: string; children: React.ReactChild | React.ReactChild[]; + "data-tip"?: string; + "data-for"?: string; + "data-html"?: boolean; + "data-multiline"?: boolean; }; export default function Chip(props: ChipProps): JSX.Element { return (
{props.children}
diff --git a/src/components/Chronology/ChronologyItemComponent.tsx b/src/components/Chronology/ChronologyItemComponent.tsx index 2afe59b..090fb92 100644 --- a/src/components/Chronology/ChronologyItemComponent.tsx +++ b/src/components/Chronology/ChronologyItemComponent.tsx @@ -87,7 +87,7 @@ export default function ChronologyItemComponent(
{translation.status !== Enum_Componenttranslationschronologyitem_Status.Done && ( -
- {translation.status} -
+ {translation.status} + )} {translation.title ?

{translation.title}

: ""}
diff --git a/src/components/Content/ThumbnailHeader.tsx b/src/components/Content/ThumbnailHeader.tsx index 4f18163..13f1c3a 100644 --- a/src/components/Content/ThumbnailHeader.tsx +++ b/src/components/Content/ThumbnailHeader.tsx @@ -5,6 +5,7 @@ import { import { prettySlug } from "queries/helpers"; import Button from "components/Button"; import Img, { ImageQuality } from "components/Img"; +import InsetBox from "components/InsetBox"; export type ThumbnailHeaderProps = { content: { @@ -25,7 +26,7 @@ export default function ThumbnailHeader( return ( <> -
+
{content.thumbnail.data ? ( + {content.titles.length > 0 && content.titles[0].description && ( + {content.titles[0].description} + )} ); } diff --git a/src/components/Img.tsx b/src/components/Img.tsx index 76262bd..8723bbb 100644 --- a/src/components/Img.tsx +++ b/src/components/Img.tsx @@ -56,6 +56,7 @@ type ImgProps = { layout?: ImageProps["layout"]; objectFit?: ImageProps["objectFit"]; priority?: ImageProps["priority"]; + rawImg?: boolean; }; export default function Img(props: ImgProps): JSX.Element { @@ -64,20 +65,37 @@ export default function Img(props: ImgProps): JSX.Element { props.image.height, props.quality ? props.quality : ImageQuality.Small ); - return ( - {props.alt - ); + + if (props.rawImg) { + return ( + // eslint-disable-next-line @next/next/no-img-element + {props.alt + ); + } else { + return ( + {props.alt + ); + } } diff --git a/src/components/PanelComponents/NavOption.tsx b/src/components/PanelComponents/NavOption.tsx index df91024..be793d4 100644 --- a/src/components/PanelComponents/NavOption.tsx +++ b/src/components/PanelComponents/NavOption.tsx @@ -1,6 +1,7 @@ import { useRouter } from "next/router"; import Link from "next/link"; import { MouseEventHandler } from "react"; +import ReactDOMServer from "react-dom/server"; type NavOptionProps = { url: string; @@ -29,16 +30,14 @@ export default function NavOption(props: NavOptionProps): JSX.Element { onClick={props.onClick} data-html data-multiline - data-tip={` -
-

${props.title}

- ${ - props.subtitle - ? `

${props.subtitle}

` - : "" - } + data-tip={ReactDOMServer.renderToStaticMarkup( +
+

{props.title}

+ {props.subtitle && ( +

{props.subtitle}

+ )}
- `} + )} data-for={props.tooltipId} className={`grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${ props.icon ? "text-left" : "text-center" diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx index 4db6f4f..1ac3b2f 100644 --- a/src/components/Panels/MainPanel.tsx +++ b/src/components/Panels/MainPanel.tsx @@ -183,6 +183,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { )}

@@ -201,12 +202,14 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {

+ )} + data-for={"RecordersTooltip"} + data-multiline + data-html + > + {recorder.attributes.anonymize + ? `Recorder#${recorder.attributes.anonymous_code}` + : recorder.attributes.username} + + ); +} diff --git a/src/graphql/operation.graphql b/src/graphql/operation.graphql index f55d745..c73773f 100644 --- a/src/graphql/operation.graphql +++ b/src/graphql/operation.graphql @@ -73,7 +73,7 @@ query getWebsiteInterface($language_code: String) { } query getEras($language_code: String) { - chronologyEras { + chronologyEras(sort: "starting_year") { data { id attributes { @@ -730,6 +730,7 @@ query getContent($slug: String, $language_code: String) { pre_title title subtitle + description } categories { data { @@ -817,6 +818,7 @@ query getContentText($slug: String, $language_code: String) { pre_title title subtitle + description } categories { data { @@ -875,16 +877,28 @@ query getContentText($slug: String, $language_code: String) { source_language { data { attributes { - name + code } } } transcribers { data { + id attributes { username anonymize anonymous_code + pronouns + bio(filters: { language: { code: { eq: $language_code } } }) { + bio + } + languages { + data { + attributes { + code + } + } + } avatar { data { attributes { @@ -902,10 +916,22 @@ query getContentText($slug: String, $language_code: String) { } translators { data { + id attributes { username anonymize anonymous_code + pronouns + bio(filters: { language: { code: { eq: $language_code } } }) { + bio + } + languages { + data { + attributes { + code + } + } + } avatar { data { attributes { @@ -923,10 +949,22 @@ query getContentText($slug: String, $language_code: String) { } proofreaders { data { + id attributes { username anonymize anonymous_code + pronouns + bio(filters: { language: { code: { eq: $language_code } } }) { + bio + } + languages { + data { + attributes { + code + } + } + } avatar { data { attributes { diff --git a/src/graphql/operations-types.ts b/src/graphql/operations-types.ts index 0aeff4e..50863f1 100644 --- a/src/graphql/operations-types.ts +++ b/src/graphql/operations-types.ts @@ -996,6 +996,7 @@ export type GetContentQuery = { pre_title: string; title: string; subtitle: string; + description: string; }>; categories: { __typename: "CategoryRelationResponseCollection"; @@ -1116,6 +1117,7 @@ export type GetContentTextQuery = { pre_title: string; title: string; subtitle: string; + description: string; }>; categories: { __typename: "CategoryRelationResponseCollection"; @@ -1194,18 +1196,34 @@ export type GetContentTextQuery = { __typename: "LanguageEntityResponse"; data: { __typename: "LanguageEntity"; - attributes: { __typename: "Language"; name: string }; + attributes: { __typename: "Language"; code: string }; }; }; transcribers: { __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: { @@ -1228,11 +1246,27 @@ export type GetContentTextQuery = { __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: { @@ -1255,11 +1289,27 @@ export type GetContentTextQuery = { __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: { diff --git a/src/graphql/schema.graphql b/src/graphql/schema.graphql index d16a8c1..890a052 100644 --- a/src/graphql/schema.graphql +++ b/src/graphql/schema.graphql @@ -398,6 +398,23 @@ type ComponentCollectionsComponentLibraryObiBelt { inside_full: UploadFileEntityResponse } +input ComponentCollectionsComponentTitlesFiltersInput { + title: StringFilterInput + and: [ComponentCollectionsComponentTitlesFiltersInput] + or: [ComponentCollectionsComponentTitlesFiltersInput] + not: ComponentCollectionsComponentTitlesFiltersInput +} + +input ComponentCollectionsComponentTitlesInput { + id: ID + title: String +} + +type ComponentCollectionsComponentTitles { + id: ID! + title: String! +} + input ComponentCollectionsComponentWeaponStoryFiltersInput { source: SourceFiltersInput categories: CategoryFiltersInput @@ -428,6 +445,17 @@ type ComponentCollectionsComponentWeaponStory { ): CategoryRelationResponseCollection } +type ComponentCollectionsComponentWikiDefinition { + id: ID! + definition: String + categories( + filters: CategoryFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): CategoryRelationResponseCollection + source: SourceEntityResponse +} + type ComponentMetadataAudio { id: ID! subtype: AudioSubtypeEntityResponse @@ -771,6 +799,69 @@ type ComponentSetsVideoSet { notes: String } +enum ENUM_COMPONENTSETSWIKISET_STATUS { + Incomplete + Draft + Review + Done +} + +input ComponentSetsWikiSetFiltersInput { + language: LanguageFiltersInput + status: StringFilterInput + summary: StringFilterInput + body: StringFilterInput + source_language: LanguageFiltersInput + authors: RecorderFiltersInput + translators: RecorderFiltersInput + proofreaders: RecorderFiltersInput + and: [ComponentSetsWikiSetFiltersInput] + or: [ComponentSetsWikiSetFiltersInput] + not: ComponentSetsWikiSetFiltersInput +} + +input ComponentSetsWikiSetInput { + id: ID + language: ID + status: ENUM_COMPONENTSETSWIKISET_STATUS + titles: [ComponentCollectionsComponentTitlesInput] + summary: String + body: String + source_language: ID + authors: [ID] + translators: [ID] + proofreaders: [ID] +} + +type ComponentSetsWikiSet { + id: ID! + language: LanguageEntityResponse + status: ENUM_COMPONENTSETSWIKISET_STATUS! + titles( + filters: ComponentCollectionsComponentTitlesFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): [ComponentCollectionsComponentTitles] + summary: String + body: String + source_language: LanguageEntityResponse + authors( + filters: RecorderFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): RecorderRelationResponseCollection + translators( + filters: RecorderFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): RecorderRelationResponseCollection + proofreaders( + filters: RecorderFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): RecorderRelationResponseCollection +} + type ComponentSourceUrlSource { id: ID! title: String @@ -794,9 +885,30 @@ type ComponentTranslationsAudioSets { credits: ComponentBasicsCredits! } +input ComponentTranslationsBioFiltersInput { + language: LanguageFiltersInput + bio: StringFilterInput + and: [ComponentTranslationsBioFiltersInput] + or: [ComponentTranslationsBioFiltersInput] + not: ComponentTranslationsBioFiltersInput +} + +input ComponentTranslationsBioInput { + id: ID + language: ID + bio: String +} + +type ComponentTranslationsBio { + id: ID! + language: LanguageEntityResponse + bio: String +} + input ComponentTranslationsChronologyEraFiltersInput { title: StringFilterInput language: LanguageFiltersInput + description: StringFilterInput and: [ComponentTranslationsChronologyEraFiltersInput] or: [ComponentTranslationsChronologyEraFiltersInput] not: ComponentTranslationsChronologyEraFiltersInput @@ -806,12 +918,14 @@ input ComponentTranslationsChronologyEraInput { id: ID title: String language: ID + description: String } type ComponentTranslationsChronologyEra { id: ID! - title: String + title: String! language: LanguageEntityResponse + description: String } enum ENUM_COMPONENTTRANSLATIONSCHRONOLOGYITEM_STATUS { @@ -1017,6 +1131,7 @@ input ComponentTranslationsTitleFiltersInput { title: StringFilterInput subtitle: StringFilterInput pre_title: StringFilterInput + description: StringFilterInput and: [ComponentTranslationsTitleFiltersInput] or: [ComponentTranslationsTitleFiltersInput] not: ComponentTranslationsTitleFiltersInput @@ -1028,6 +1143,7 @@ input ComponentTranslationsTitleInput { title: String subtitle: String pre_title: String + description: String } type ComponentTranslationsTitle { @@ -1036,6 +1152,7 @@ type ComponentTranslationsTitle { title: String! subtitle: String pre_title: String + description: String } enum ENUM_COMPONENTTRANSLATIONSVIDEOSETS_STATUS { @@ -2051,6 +2168,7 @@ input RecorderFiltersInput { anonymize: BooleanFilterInput anonymous_code: StringFilterInput languages: LanguageFiltersInput + pronouns: StringFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput and: [RecorderFiltersInput] @@ -2064,6 +2182,8 @@ input RecorderInput { anonymous_code: String avatar: ID languages: [ID] + pronouns: String + bio: [ComponentTranslationsBioInput] } type Recorder { @@ -2076,6 +2196,12 @@ type Recorder { pagination: PaginationArg = {} sort: [String] = [] ): LanguageRelationResponseCollection + pronouns: String + bio( + filters: ComponentTranslationsBioFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): [ComponentTranslationsBio] createdAt: DateTime updatedAt: DateTime } @@ -2359,12 +2485,7 @@ input WebsiteInterfaceFiltersInput { language: LanguageFiltersInput main_library: StringFilterInput main_library_description: StringFilterInput - main_hub: StringFilterInput - main_hub_description: StringFilterInput - main_chronology: StringFilterInput - main_chronology_description: StringFilterInput main_news: StringFilterInput - main_data: StringFilterInput main_merch: StringFilterInput main_gallery: StringFilterInput main_archives: StringFilterInput @@ -2394,13 +2515,6 @@ input WebsiteInterfaceFiltersInput { global_price: StringFilterInput library_item_physical_size: StringFilterInput library_item_type_information: StringFilterInput - chronology_description: StringFilterInput - chronology_timelines: StringFilterInput - chronology_timelines_description: StringFilterInput - chronology_overview: StringFilterInput - chronology_overview_description: StringFilterInput - chronology_walkthrough: StringFilterInput - chronology_walkthrough_description: StringFilterInput library_item_front_matter: StringFilterInput library_item_back_matter: StringFilterInput library_item_type_textual: StringFilterInput @@ -2419,6 +2533,21 @@ input WebsiteInterfaceFiltersInput { global_hardcover: StringFilterInput global_left_to_right: StringFilterInput global_right_to_left: StringFilterInput + main_wiki: StringFilterInput + main_wiki_description: StringFilterInput + main_chronicles: StringFilterInput + main_chronicles_description: StringFilterInput + library_items: StringFilterInput + library_items_description: StringFilterInput + library_content: StringFilterInput + library_content_description: StringFilterInput + wiki_description: StringFilterInput + news_description: StringFilterInput + chronicles_description: StringFilterInput + gallery_description: StringFilterInput + archives_description: StringFilterInput + about_us_description: StringFilterInput + merch_description: StringFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput and: [WebsiteInterfaceFiltersInput] @@ -2430,12 +2559,7 @@ input WebsiteInterfaceInput { language: ID main_library: String main_library_description: String - main_hub: String - main_hub_description: String - main_chronology: String - main_chronology_description: String main_news: String - main_data: String main_merch: String main_gallery: String main_archives: String @@ -2465,13 +2589,6 @@ input WebsiteInterfaceInput { global_price: String library_item_physical_size: String library_item_type_information: String - chronology_description: String - chronology_timelines: String - chronology_timelines_description: String - chronology_overview: String - chronology_overview_description: String - chronology_walkthrough: String - chronology_walkthrough_description: String library_item_front_matter: String library_item_back_matter: String library_item_type_textual: String @@ -2490,18 +2607,28 @@ input WebsiteInterfaceInput { global_hardcover: String global_left_to_right: String global_right_to_left: String + main_wiki: String + main_wiki_description: String + main_chronicles: String + main_chronicles_description: String + library_items: String + library_items_description: String + library_content: String + library_content_description: String + wiki_description: String + news_description: String + chronicles_description: String + gallery_description: String + archives_description: String + about_us_description: String + merch_description: String } type WebsiteInterface { language: LanguageEntityResponse main_library: String main_library_description: String - main_hub: String - main_hub_description: String - main_chronology: String - main_chronology_description: String main_news: String - main_data: String main_merch: String main_gallery: String main_archives: String @@ -2531,13 +2658,6 @@ type WebsiteInterface { global_price: String library_item_physical_size: String library_item_type_information: String - chronology_description: String - chronology_timelines: String - chronology_timelines_description: String - chronology_overview: String - chronology_overview_description: String - chronology_walkthrough: String - chronology_walkthrough_description: String library_item_front_matter: String library_item_back_matter: String library_item_type_textual: String @@ -2556,6 +2676,21 @@ type WebsiteInterface { global_hardcover: String global_left_to_right: String global_right_to_left: String + main_wiki: String + main_wiki_description: String + main_chronicles: String + main_chronicles_description: String + library_items: String + library_items_description: String + library_content: String + library_content_description: String + wiki_description: String + news_description: String + chronicles_description: String + gallery_description: String + archives_description: String + about_us_description: String + merch_description: String createdAt: DateTime updatedAt: DateTime } @@ -2574,6 +2709,91 @@ type WebsiteInterfaceEntityResponseCollection { meta: ResponseCollectionMeta! } +input WikiPageFiltersInput { + id: IDFilterInput + slug: StringFilterInput + type: WikiPageTypeFiltersInput + createdAt: DateTimeFilterInput + updatedAt: DateTimeFilterInput + and: [WikiPageFiltersInput] + or: [WikiPageFiltersInput] + not: WikiPageFiltersInput +} + +input WikiPageInput { + slug: String + thumbnail: ID + wiki_set: [ComponentSetsWikiSetInput] + type: ID +} + +type WikiPage { + slug: String! + thumbnail: UploadFileEntityResponse + wiki_set( + filters: ComponentSetsWikiSetFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): [ComponentSetsWikiSet] + type: WikiPageTypeEntityResponse + createdAt: DateTime + updatedAt: DateTime +} + +type WikiPageEntity { + id: ID + attributes: WikiPage +} + +type WikiPageEntityResponse { + data: WikiPageEntity +} + +type WikiPageEntityResponseCollection { + data: [WikiPageEntity!]! + meta: ResponseCollectionMeta! +} + +input WikiPageTypeFiltersInput { + id: IDFilterInput + slug: StringFilterInput + createdAt: DateTimeFilterInput + updatedAt: DateTimeFilterInput + and: [WikiPageTypeFiltersInput] + or: [WikiPageTypeFiltersInput] + not: WikiPageTypeFiltersInput +} + +input WikiPageTypeInput { + slug: String + titles: [ComponentTranslationsSimpleTitleInput] +} + +type WikiPageType { + slug: String! + titles( + filters: ComponentTranslationsSimpleTitleFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): [ComponentTranslationsSimpleTitle] + createdAt: DateTime + updatedAt: DateTime +} + +type WikiPageTypeEntity { + id: ID + attributes: WikiPageType +} + +type WikiPageTypeEntityResponse { + data: WikiPageTypeEntity +} + +type WikiPageTypeEntityResponseCollection { + data: [WikiPageTypeEntity!]! + meta: ResponseCollectionMeta! +} + union GenericMorph = ComponentBasicsCredits | ComponentBasicsDatepicker @@ -2585,7 +2805,9 @@ union GenericMorph = | ComponentCollectionsComponentLibraryDustJacket | ComponentCollectionsComponentLibraryImages | ComponentCollectionsComponentLibraryObiBelt + | ComponentCollectionsComponentTitles | ComponentCollectionsComponentWeaponStory + | ComponentCollectionsComponentWikiDefinition | ComponentMetadataAudio | ComponentMetadataBooks | ComponentMetadataGame @@ -2606,8 +2828,10 @@ union GenericMorph = | ComponentSetsScanSet | ComponentSetsTextSet | ComponentSetsVideoSet + | ComponentSetsWikiSet | ComponentSourceUrlSource | ComponentTranslationsAudioSets + | ComponentTranslationsBio | ComponentTranslationsChronologyEra | ComponentTranslationsChronologyItem | ComponentTranslationsGlossaryDefinition @@ -2648,6 +2872,8 @@ union GenericMorph = | WeaponStoryGroup | WeaponStoryType | WebsiteInterface + | WikiPage + | WikiPageType input FileInfoInput { name: String @@ -2814,6 +3040,18 @@ type Query { pagination: PaginationArg = {} sort: [String] = [] ): WebsiteInterfaceEntityResponseCollection + wikiPage(id: ID): WikiPageEntityResponse + wikiPages( + filters: WikiPageFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): WikiPageEntityResponseCollection + wikiPageType(id: ID): WikiPageTypeEntityResponse + wikiPageTypes( + filters: WikiPageTypeFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): WikiPageTypeEntityResponseCollection } type Mutation { @@ -2939,6 +3177,15 @@ type Mutation { data: WebsiteInterfaceInput! ): WebsiteInterfaceEntityResponse deleteWebsiteInterface(id: ID!): WebsiteInterfaceEntityResponse + createWikiPage(data: WikiPageInput!): WikiPageEntityResponse + updateWikiPage(id: ID!, data: WikiPageInput!): WikiPageEntityResponse + deleteWikiPage(id: ID!): WikiPageEntityResponse + createWikiPageType(data: WikiPageTypeInput!): WikiPageTypeEntityResponse + updateWikiPageType( + id: ID! + data: WikiPageTypeInput! + ): WikiPageTypeEntityResponse + deleteWikiPageType(id: ID!): WikiPageTypeEntityResponse upload( refId: ID ref: String diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 5cbfe18..506d91b 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -39,7 +39,16 @@ class MyDocument extends Document { - + + 0 ? content.titles[0].description : undefined + } /> ); } diff --git a/src/pages/contents/[slug]/read.tsx b/src/pages/contents/[slug]/read.tsx index fa1d757..e7200ca 100644 --- a/src/pages/contents/[slug]/read.tsx +++ b/src/pages/contents/[slug]/read.tsx @@ -5,6 +5,7 @@ import { getWebsiteInterface, } from "graphql/operations"; import { + Enum_Componentsetstextset_Status, GetContentTextQuery, GetWebsiteInterfaceQuery, } from "graphql/operations-types"; @@ -15,7 +16,18 @@ import ReturnButton from "components/PanelComponents/ReturnButton"; import ThumbnailHeader from "components/Content/ThumbnailHeader"; import AppLayout from "components/AppLayout"; import Markdawn from "components/Markdown/Markdawn"; -import { prettyinlineTitle, prettySlug } from "queries/helpers"; +import { + prettyinlineTitle, + prettyLanguage, + prettySlug, + prettyTestError, + prettyTestWarning, +} from "queries/helpers"; +import Button from "components/Button"; +import { useRouter } from "next/router"; +import Chip from "components/Chip"; +import ReactTooltip from "react-tooltip"; +import RecorderChip from "components/RecorderChip"; type ContentReadProps = { content: GetContentTextQuery; @@ -25,6 +37,10 @@ type ContentReadProps = { export default function ContentRead(props: ContentReadProps): JSX.Element { const content = props.content.contents.data[0].attributes; const langui = props.langui.websiteInterfaces.data[0].attributes; + const router = useRouter(); + + useTesting(props.content); + const subPanel = ( + + + + {content.text_set.length > 0 ? ( +
+

+ {content.text_set[0].source_language.data.attributes.code === + router.locale + ? "This content is a transcript" + : "This content is a fan-translation"} +

+ + {content.text_set[0].source_language.data.attributes.code !== + router.locale && ( +
+

Source language:

+ +
+ )} + +
+

Status:

+ + + {content.text_set[0].status} + +
+ + {content.text_set[0].transcribers.data.length > 0 && ( +
+

Transcribers:

+
+ {content.text_set[0].transcribers.data.map((recorder) => ( + + ))} +
+
+ )} + + {content.text_set[0].translators.data.length > 0 && ( +
+

Translators:

+
+ {content.text_set[0].translators.data.map((recorder) => ( + + ))} +
+
+ )} + + {content.text_set[0].proofreaders.data.length > 0 && ( +
+

Proofreaders:

+
+ {content.text_set[0].proofreaders.data.map((recorder) => ( + + ))} +
+
+ )} +
+ ) : ( + "" + )}
); const contentPanel = ( @@ -50,18 +153,49 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { ); + const extra = ( + <> + + + + + ); + return ( 0 - ? prettyinlineTitle(content.titles[0].pre_title, content.titles[0].title, content.titles[0].subtitle) + ? prettyinlineTitle( + content.titles[0].pre_title, + content.titles[0].title, + content.titles[0].subtitle + ) : prettySlug(content.slug) } thumbnail={content.thumbnail.data.attributes} langui={langui} contentPanel={contentPanel} subPanel={subPanel} + extra={extra} /> ); } @@ -109,3 +243,72 @@ export const getStaticPaths: GetStaticPaths = async (context) => { fallback: false, }; }; + +export function useTesting(content: GetContentTextQuery) { + const router = useRouter(); + const contentAtr = content.contents.data[0].attributes; + if (contentAtr.categories.data.length === 0) { + prettyTestError(router, "Missing categories", ["content"]); + } + + if (contentAtr.ranged_contents.data.length === 0) { + prettyTestWarning(router, "Unconnected to any source", ["content"]); + } + + if (contentAtr.text_set.length === 0) { + prettyTestWarning(router, "Has no textset, nor audioset, nor videoset", [ + "content", + ]); + } + + if (contentAtr.text_set.length > 1) { + console.warn( + prettyTestError(router, "More than one textset for this language", [ + "content", + "text_set", + ]) + ); + } + + if (contentAtr.text_set.length === 1) { + const textset = contentAtr.text_set[0]; + if (!textset.text) { + prettyTestError(router, "Missing text", ["content", "text_set"]); + } + if (!textset.source_language.data) { + prettyTestError(router, "Missing source language", [ + "content", + "text_set", + ]); + } + if (textset.source_language.data.attributes.code === router.locale) { + // This is a transcript + if (textset.transcribers.data.length === 0) { + prettyTestError(router, "Missing transcribers attribution", [ + "content", + "text_set", + ]); + } + if (textset.translators.data.length > 0) { + prettyTestError(router, "Transcripts shouldn't have translators", [ + "content", + "text_set", + ]); + } + } else { + // This is a translation + if (textset.translators.data.length === 0) { + prettyTestError(router, "Missing translators attribution", [ + "content", + "text_set", + ]); + } + if (textset.transcribers.data.length > 0) { + prettyTestError(router, "Translations shouldn't have transcribers", [ + "content", + "text_set", + ]); + } + } + } +} diff --git a/src/pages/wiki/chronology.tsx b/src/pages/wiki/chronology.tsx index ef9d14d..25a51ba 100644 --- a/src/pages/wiki/chronology.tsx +++ b/src/pages/wiki/chronology.tsx @@ -16,7 +16,11 @@ import NavOption from "components/PanelComponents/NavOption"; import ReturnButton from "components/PanelComponents/ReturnButton"; import HorizontalLine from "components/HorizontalLine"; import AppLayout from "components/AppLayout"; -import { prettySlug } from "queries/helpers"; +import { + prettySlug, + prettyTestError, + prettyTestWarning, +} from "queries/helpers"; import InsetBox from "components/InsetBox"; import { useRouter } from "next/router"; import ReactTooltip from "react-tooltip"; @@ -165,41 +169,52 @@ export function useTesting( const router = useRouter(); chronologyEras.chronologyEras.data.map((era) => { if (era.attributes.title.length === 0) { - console.warn( - `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | Missing translation for title and description, using slug instead` + prettyTestError( + router, + "Missing translation for title and description, using slug instead", + ["chronologyEras", era.attributes.slug] ); } else if (era.attributes.title.length > 1) { - console.warn( - `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | More than one title and description` - ); + prettyTestError(router, "More than one title and description", [ + "chronologyEras", + era.attributes.slug, + ]); } else { if (!era.attributes.title[0].title) - console.warn( - `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | Missing title, using slug instead` - ); + prettyTestError(router, "Missing title, using slug instead", [ + "chronologyEras", + era.attributes.slug, + ]); if (!era.attributes.title[0].description) - console.warn( - `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | Missing description` - ); + prettyTestError(router, "Missing description", [ + "chronologyEras", + era.attributes.slug, + ]); } }); chronologyItems.chronologyItems.data.map((item) => { + const date = `${item.attributes.year}/${item.attributes.month}/${item.attributes.day}`; if (!(item.attributes.events.length > 0)) { - console.warn( - `${router.pathname} | ${router.locale} | chronologyItems | ${item.attributes.year}/${item.attributes.month}/${item.attributes.day} | No events for this date` - ); + prettyTestError(router, "No events for this date", [ + "chronologyItems", + date, + ]); } else { item.attributes.events.map((event) => { if (!event.source.data) { - console.warn( - `${router.pathname} | ${router.locale} | chronologyItems | ${item.attributes.year}/${item.attributes.month}/${item.attributes.day} | ${event.id} | No source for this event` - ); + prettyTestError(router, "No source for this event", [ + "chronologyItems", + date, + event.id, + ]); } if (!(event.translations.length > 0)) { - console.warn( - `${router.pathname} | ${router.locale} | chronologyItems | ${item.attributes.year}/${item.attributes.month}/${item.attributes.day} | ${event.id} | No translation for this event` - ); + prettyTestWarning(router, "No translation for this event", [ + "chronologyItems", + date, + event.id, + ]); } }); } diff --git a/src/queries/helpers.ts b/src/queries/helpers.ts index e9f07ff..4b75647 100644 --- a/src/queries/helpers.ts +++ b/src/queries/helpers.ts @@ -8,6 +8,7 @@ import { GetWebsiteInterfaceQuery, StrapiImage, } from "graphql/operations-types"; +import { NextRouter } from "next/router"; export function prettyDate( datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"] @@ -117,6 +118,39 @@ export function prettyLanguage(code: string): string { } } +export function prettyTestWarning( + router: NextRouter, + message: string, + subCategory?: string[] +): void { + prettyTestWritter(TestingLevel.Warning, router, message, subCategory); +} + +export function prettyTestError( + router: NextRouter, + message: string, + subCategory?: string[] +): void { + prettyTestWritter(TestingLevel.Error, router, message, subCategory); +} + +enum TestingLevel { + Warning = "warn", + Error = "error", +} + +function prettyTestWritter( + level: TestingLevel, + { asPath, locale }: NextRouter, + message: string, + subCategory?: string[] +): void { + subCategory?.push(""); + console.warn( + `${level} - ${asPath} | ${locale} | ${subCategory?.join(" | ")}${message}` + ); +} + export function capitalizeString(string: string): string { function capitalizeWord(word: string): string { return word.charAt(0).toUpperCase() + word.substring(1); @@ -131,28 +165,23 @@ export function convertMmToInch(mm: number): string { return (mm * 0.03937008).toPrecision(3); } -type OgImage = { +export type OgImage = { image: string; width: number; height: number; alt: string; }; -export function getOgImage( - quality: ImageQuality, - image?: StrapiImage -): OgImage | undefined { - if (image) { - const imgSize = getImgSizesByQuality( - image.width, - image.height, - quality ? quality : ImageQuality.Small - ); - return { - image: getAssetURL(image.url, quality), - width: imgSize.width, - height: imgSize.height, - alt: image.alternativeText, - }; - } +export function getOgImage(quality: ImageQuality, image: StrapiImage): OgImage { + const imgSize = getImgSizesByQuality( + image.width, + image.height, + quality ? quality : ImageQuality.Small + ); + return { + image: getAssetURL(image.url, quality), + width: imgSize.width, + height: imgSize.height, + alt: image.alternativeText, + }; } diff --git a/src/tailwind.css b/src/tailwind.css index 852c41f..6eea261 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -77,6 +77,10 @@ @apply text-dark; } + .prose blockquote { + @apply border-l-dark + } + } @layer components { diff --git a/testing_logs/.gitkeep b/testing_logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json index a67193d..003a01d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "target": "ESNext", "lib": ["dom", "dom.iterable", "esnext"], + "importHelpers": true, "allowJs": true, "skipLibCheck": true, "strict": true,