diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml deleted file mode 100644 index a5242e0..0000000 --- a/.github/workflows/node.js.yml +++ /dev/null @@ -1,37 +0,0 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions - -name: Node.js CI - -on: -# push: -# branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [16.x] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - run: npm ci - - run: npm run lint - - run: npm run build --if-present - env: - ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} - NEXT_PUBLIC_URL_CMS: ${{ secrets.NEXT_PUBLIC_URL_CMS }} - NEXT_PUBLIC_URL_IMG: ${{ secrets.NEXT_PUBLIC_URL_IMG }} - NEXT_PUBLIC_URL_SELF: ${{ secrets.NEXT_PUBLIC_URL_SELF }} - URL_GRAPHQL: ${{ secrets.URL_GRAPHQL }} diff --git a/README.md b/README.md index 7838a71..a37b4b6 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ # Accords-library.com -[![Node.js CI](https://github.com/Accords-Library/accords-library.com/actions/workflows/node.js.yml/badge.svg?branch=main)](https://github.com/Accords-Library/accords-library.com/actions/workflows/node.js.yml) -[![GitHub](https://img.shields.io/github/license/Accords-Library/accords-library.com?style=flat-square)](https://github.com/Accords-Library/accords-library.com/blob/main/LICENSE) -![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/Accords-Library/accords-library.com?style=flat-square) - ## Technologies #### [Back](https://github.com/Accords-Library/strapi.accords-library.com) diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 9334220..5721da6 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -149,7 +149,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { {/* Background when navbar is opened */}
@@ -27,7 +29,7 @@ export default function HorizontalLine( diff --git a/src/components/Library/LibraryItemsPreview.tsx b/src/components/Library/LibraryItemsPreview.tsx index fc530c6..f667268 100644 --- a/src/components/Library/LibraryItemsPreview.tsx +++ b/src/components/Library/LibraryItemsPreview.tsx @@ -63,7 +63,7 @@ export default function LibraryItemsPreview( ))}
- {(item.release_date ?? item.price) && ( + {(item.release_date || item.price) && (
{item.release_date && (

diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx index db37151..3e7d108 100644 --- a/src/components/Markdown/Markdawn.tsx +++ b/src/components/Markdown/Markdawn.tsx @@ -5,7 +5,7 @@ import LightBox from "components/LightBox"; import ToolTip from "components/ToolTip"; import { useAppLayout } from "contexts/AppLayoutContext"; import Markdown from "markdown-to-jsx"; -import { NextRouter } from "next/router"; +import { useRouter } from "next/router"; import { slugify } from "queries/helpers"; import React, { useState } from "react"; import ReactDOMServer from "react-dom/server"; @@ -13,14 +13,13 @@ import ReactDOMServer from "react-dom/server"; type MarkdawnProps = { className?: string; text: string; - router: NextRouter; }; export default function Markdawn(props: MarkdawnProps): JSX.Element { const appLayout = useAppLayout(); const text = preprocessMarkDawn(props.text); - const { router } = props; + const router = useRouter(); const [lightboxOpen, setLightboxOpen] = useState(false); const [lightboxImages, setLightboxImages] = useState([""]); @@ -41,6 +40,21 @@ export default function Markdawn(props: MarkdawnProps): JSX.Element { options={{ slugify: slugify, overrides: { + a: { + component: (compProps: { + href: string; + children: React.ReactNode; + }) => { + if (compProps.href.startsWith("/")) { + return ( + router.push(compProps.href)}> + {compProps.children} + + ); + } + return {compProps.children}; + }, + }, h1: { component: (compProps: { id: string; @@ -313,7 +327,7 @@ export function preprocessMarkDawn(text: string): string { const visitedSlugs: string[] = []; const result = text.split("\n").map((line) => { - if (line === "* * *" ?? line === "---") { + if (line === "* * *" || line === "---") { scenebreakIndex += 1; return ``; } diff --git a/src/components/Markdown/TOC.tsx b/src/components/Markdown/TOC.tsx index 010702f..430c358 100644 --- a/src/components/Markdown/TOC.tsx +++ b/src/components/Markdown/TOC.tsx @@ -1,16 +1,16 @@ -import { NextRouter } from "next/router"; +import { useRouter } from "next/router"; import { slugify } from "queries/helpers"; import { preprocessMarkDawn } from "./Markdawn"; type TOCProps = { text: string; title?: string; - router: NextRouter; }; export default function TOCComponent(props: TOCProps): JSX.Element { - const { router, text, title } = props; + const { text, title } = props; const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title); + const router = useRouter(); return ( <> @@ -21,11 +21,7 @@ export default function TOCComponent(props: TOCProps): JSX.Element { {{toc.title}}

- +
); @@ -34,11 +30,11 @@ export default function TOCComponent(props: TOCProps): JSX.Element { type TOCLevelProps = { tocchildren: TOC[]; parentNumbering: string; - router: NextRouter; }; function TOCLevel(props: TOCLevelProps): JSX.Element { - const { tocchildren, parentNumbering, router } = props; + const router = useRouter(); + const { tocchildren, parentNumbering } = props; return (
    {tocchildren.map((child, childIndex) => ( @@ -57,7 +53,6 @@ function TOCLevel(props: TOCLevelProps): JSX.Element { ))} diff --git a/src/components/PanelComponents/NavOption.tsx b/src/components/PanelComponents/NavOption.tsx index 2a4377e..c640aa9 100644 --- a/src/components/PanelComponents/NavOption.tsx +++ b/src/components/PanelComponents/NavOption.tsx @@ -1,5 +1,4 @@ import ToolTip from "components/ToolTip"; -import Link from "next/link"; import { useRouter } from "next/router"; import { MouseEventHandler } from "react"; @@ -35,27 +34,32 @@ export default function NavOption(props: NavOptionProps): JSX.Element { className="text-left" disabled={!props.reduced} > - -
    - {props.icon && ( - {props.icon} - )} +
    { + if (props.onClick) props.onClick(event); + if (props.url) { + if (props.url.startsWith("#")) { + router.replace(props.url); + } else { + router.push(props.url); + } + } + }} + className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${ + props.icon ? "text-left" : "text-center" + } ${divCommon}`} + > + {props.icon && ( + {props.icon} + )} - {!props.reduced && ( -
    -

    {props.title}

    - {props.subtitle && ( -

    {props.subtitle}

    - )} -
    - )} -
    - + {!props.reduced && ( +
    +

    {props.title}

    + {props.subtitle &&

    {props.subtitle}

    } +
    + )} +
    ); } diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx index f80b16d..f95ee31 100644 --- a/src/components/Panels/MainPanel.tsx +++ b/src/components/Panels/MainPanel.tsx @@ -109,7 +109,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { )} - {langui.open_search}} placement="right" className="text-left" @@ -130,7 +130,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { search - + */}
diff --git a/src/graphql/operation.graphql b/src/graphql/operation.graphql index f4353e7..bf38c35 100644 --- a/src/graphql/operation.graphql +++ b/src/graphql/operation.graphql @@ -1011,6 +1011,15 @@ query getContentText($slug: String, $language_code: String) { } } } + text_set_languages: text_set { + language { + data { + attributes { + code + } + } + } + } text_set(filters: { language: { code: { eq: $language_code } } }) { status text @@ -1233,6 +1242,15 @@ query getPost($slug: String, $language_code: String) { } } } + translations_languages: translations { + language { + data { + attributes { + code + } + } + } + } translations(filters: { language: { code: { eq: $language_code } } }) { status title @@ -1319,24 +1337,6 @@ query getPostsPreview($language_code: String) { } } -query getPostLanguages($slug: String) { - posts(filters: { slug: { eq: $slug } }) { - data { - attributes { - translations { - language { - data { - attributes { - code - } - } - } - } - } - } - } -} - query getContentLanguages($slug: String) { contents(filters: { slug: { eq: $slug } }) { data { @@ -1372,3 +1372,192 @@ query getContentLanguages($slug: String) { } } } + +query getLibraryItemScans($slug: String, $language_code: String) { + libraryItems(filters: { slug: { eq: $slug } }) { + data { + id + attributes { + slug + title + subtitle + thumbnail { + data { + attributes { + name + alternativeText + caption + width + height + url + } + } + } + contents(pagination: { limit: -1 }) { + data { + id + attributes { + slug + range { + __typename + ... on ComponentRangePageRange { + starting_page + ending_page + } + ... on ComponentRangeTimeRange { + starting_time + ending_time + } + } + scan_set_languages: scan_set { + language { + data { + attributes { + code + } + } + } + } + scan_set( + filters: { + or: [ + { language: { code: { eq: "xx" } } } + { language: { code: { eq: $language_code } } } + ] + } + ) { + status + source_language { + data { + attributes { + code + } + } + } + scanners { + data { + id + attributes { + 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 + } + } + } + } + } + } + cleaners { + 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 + } + } + } + } + } + } + typesetters { + 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 + } + } + } + } + } + } + notes + pages(pagination: { limit: -1 }) { + data { + id + attributes { + name + alternativeText + caption + width + height + url + } + } + } + } + } + } + } + } + } + } +} diff --git a/src/graphql/operations-types.ts b/src/graphql/operations-types.ts index 29dad8b..a07b590 100644 --- a/src/graphql/operations-types.ts +++ b/src/graphql/operations-types.ts @@ -32,7 +32,7 @@ export type Scalars = { * * But to make the type easier to work with, it went through the following transformation: * - Removed ? - * - Removed | null + * - Removed * - Replaced any by unknown */ @@ -74,6 +74,13 @@ export enum Enum_Componentsetstextset_Status { Done = "Done", } +export enum Enum_Componentsetsscanset_Status { + Incomplete = "Incomplete", + Draft = "Draft", + Review = "Review", + Done = "Done", +} + export type StrapiImage = { __typename: "UploadFile"; name: string; @@ -1360,6 +1367,19 @@ export type GetContentTextQuery = { }; }>; }; + text_set_languages: Array<{ + __typename: "ComponentSetsTextSet"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { + __typename: "Language"; + code: string; + }; + }; + }; + }>; text_set: Array<{ __typename: "ComponentSetsTextSet"; status: Enum_Componentsetstextset_Status; @@ -1576,14 +1596,14 @@ export type GetPostQuery = { attributes: { __typename: "Post"; slug: string; - updatedAt: unknown; + updatedAt: any; + hidden: boolean; date: { __typename: "ComponentBasicsDatepicker"; year: number; month: number; day: number; }; - hidden: boolean; authors: { __typename: "RecorderRelationResponseCollection"; data: Array<{ @@ -1629,11 +1649,7 @@ export type GetPostQuery = { data: Array<{ __typename: "CategoryEntity"; id: string; - attributes: { - __typename: "Category"; - name: string; - short: string; - }; + attributes: { __typename: "Category"; name: string; short: string }; }>; }; thumbnail: { @@ -1651,6 +1667,16 @@ export type GetPostQuery = { }; }; }; + translations_languages: Array<{ + __typename: "ComponentTranslationsPosts"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { __typename: "Language"; code: string }; + }; + }; + }>; translations: Array<{ __typename: "ComponentTranslationsPosts"; status: Enum_Componenttranslationsposts_Status; @@ -1833,3 +1859,238 @@ export type GetContentLanguagesQuery = { }>; }; }; + +export type GetLibraryItemScansQueryVariables = Exact<{ + slug: InputMaybe; + language_code: InputMaybe; +}>; + +export type GetLibraryItemScansQuery = { + __typename: "Query"; + libraryItems: { + __typename: "LibraryItemEntityResponseCollection"; + data: Array<{ + __typename: "LibraryItemEntity"; + id: string; + attributes: { + __typename: "LibraryItem"; + slug: string; + title: string; + subtitle: string; + thumbnail: { + __typename: "UploadFileEntityResponse"; + data: { + __typename: "UploadFileEntity"; + attributes: { + __typename: "UploadFile"; + name: string; + alternativeText: string; + caption: string; + width: number; + height: number; + url: string; + }; + }; + }; + contents: { + __typename: "RangedContentRelationResponseCollection"; + data: Array<{ + __typename: "RangedContentEntity"; + id: string; + attributes: { + __typename: "RangedContent"; + slug: string; + range: Array< + | { + __typename: "ComponentRangePageRange"; + starting_page: number; + ending_page: number; + } + | { + __typename: "ComponentRangeTimeRange"; + starting_time: any; + ending_time: any; + } + | { __typename: "ComponentRangeOther" } + | { __typename: "Error" } + >; + scan_set_languages: Array<{ + __typename: "ComponentSetsScanSet"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { + __typename: "Language"; + code: string; + }; + }; + }; + }>; + scan_set: Array<{ + __typename: "ComponentSetsScanSet"; + status: Enum_Componentsetsscanset_Status; + notes: string; + source_language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { + __typename: "Language"; + code: string; + }; + }; + }; + scanners: { + __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; + }; + }; + }; + }; + }>; + }; + cleaners: { + __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; + }; + }; + }; + }; + }>; + }; + typesetters: { + __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; + }; + }; + }; + }; + }>; + }; + pages: { + __typename: "UploadFileRelationResponseCollection"; + data: Array<{ + __typename: "UploadFileEntity"; + id: string; + 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 3c26599..dab516f 100644 --- a/src/graphql/operations.ts +++ b/src/graphql/operations.ts @@ -2,8 +2,6 @@ import { readFileSync } from "fs"; import { GetChronologyItemsQuery, GetChronologyItemsQueryVariables, - GetContentLanguagesQuery, - GetContentLanguagesQueryVariables, GetContentQuery, GetContentQueryVariables, GetContentsQuery, @@ -20,12 +18,12 @@ import { GetLanguagesQueryVariables, GetLibraryItemQuery, GetLibraryItemQueryVariables, + GetLibraryItemScansQuery, + GetLibraryItemScansQueryVariables, GetLibraryItemsPreviewQuery, GetLibraryItemsPreviewQueryVariables, GetLibraryItemsSlugsQuery, GetLibraryItemsSlugsQueryVariables, - GetPostLanguagesQuery, - GetPostLanguagesQueryVariables, GetPostQuery, GetPostQueryVariables, GetPostsPreviewQuery, @@ -172,16 +170,9 @@ export async function getPostsPreview( return await graphQL(query, JSON.stringify(variables)); } -export async function getPostLanguages( - variables: GetPostLanguagesQueryVariables -): Promise { - const query = getQueryFromOperations("getPostLanguages"); - return await graphQL(query, JSON.stringify(variables)); -} - -export async function getContentLanguages( - variables: GetContentLanguagesQueryVariables -): Promise { - const query = getQueryFromOperations("getContentLanguages"); +export async function getLibraryItemScans( + variables: GetLibraryItemScansQueryVariables +): Promise { + const query = getQueryFromOperations("getLibraryItemScans"); return await graphQL(query, JSON.stringify(variables)); } diff --git a/src/graphql/schema.graphql b/src/graphql/schema.graphql index 1514e6c..6a9d013 100644 --- a/src/graphql/schema.graphql +++ b/src/graphql/schema.graphql @@ -242,6 +242,24 @@ type ComponentBasicsDatepicker { day: Int } +enum ENUM_COMPONENTBASICSFILESIZE_UNIT { + kb + mb + gb +} + +input ComponentBasicsFileSizeInput { + id: ID + size: Float + unit: ENUM_COMPONENTBASICSFILESIZE_UNIT +} + +type ComponentBasicsFileSize { + id: ID! + size: Float! + unit: ENUM_COMPONENTBASICSFILESIZE_UNIT! +} + input ComponentBasicsPriceInput { id: ID amount: Float @@ -1268,6 +1286,29 @@ type ComponentTranslationsWeaponStory { language: LanguageEntityResponse } +input ComponentTranslationsWebArchivesFiltersInput { + language: LanguageFiltersInput + description: StringFilterInput + notes: StringFilterInput + and: [ComponentTranslationsWebArchivesFiltersInput] + or: [ComponentTranslationsWebArchivesFiltersInput] + not: ComponentTranslationsWebArchivesFiltersInput +} + +input ComponentTranslationsWebArchivesInput { + id: ID + language: ID + description: String + notes: String +} + +type ComponentTranslationsWebArchives { + id: ID! + language: LanguageEntityResponse + description: String + notes: String +} + input UploadFileFiltersInput { id: IDFilterInput name: StringFilterInput @@ -2137,6 +2178,7 @@ input PostInput { translations: [ComponentTranslationsPostsInput] hidden: Boolean thumbnail: ID + date: ComponentBasicsDatepickerInput } type Post { @@ -2158,6 +2200,7 @@ type Post { ): [ComponentTranslationsPosts] hidden: Boolean! thumbnail: UploadFileEntityResponse + date: ComponentBasicsDatepicker! createdAt: DateTime updatedAt: DateTime } @@ -2554,6 +2597,76 @@ type WeaponStoryTypeEntityResponseCollection { meta: ResponseCollectionMeta! } +enum ENUM_WEBARCHIVE_TYPE { + website + webpage + online_doc +} + +enum ENUM_WEBARCHIVE_FORMAT { + zip + wacz +} + +input WebArchiveFiltersInput { + id: IDFilterInput + type: StringFilterInput + source_url: StringFilterInput + format: StringFilterInput + num_pages: IntFilterInput + author: StringFilterInput + still_online: BooleanFilterInput + createdAt: DateTimeFilterInput + updatedAt: DateTimeFilterInput + and: [WebArchiveFiltersInput] + or: [WebArchiveFiltersInput] + not: WebArchiveFiltersInput +} + +input WebArchiveInput { + type: ENUM_WEBARCHIVE_TYPE + source_url: String + format: ENUM_WEBARCHIVE_FORMAT + date: ComponentBasicsDatepickerInput + num_pages: Int + author: String + still_online: Boolean + size: ComponentBasicsFileSizeInput + descriptions: [ComponentTranslationsWebArchivesInput] +} + +type WebArchive { + type: ENUM_WEBARCHIVE_TYPE! + source_url: String! + format: ENUM_WEBARCHIVE_FORMAT! + date: ComponentBasicsDatepicker! + num_pages: Int + author: String + still_online: Boolean! + size: ComponentBasicsFileSize! + descriptions( + filters: ComponentTranslationsWebArchivesFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): [ComponentTranslationsWebArchives] + createdAt: DateTime + updatedAt: DateTime +} + +type WebArchiveEntity { + id: ID + attributes: WebArchive +} + +type WebArchiveEntityResponse { + data: WebArchiveEntity +} + +type WebArchiveEntityResponseCollection { + data: [WebArchiveEntity!]! + meta: ResponseCollectionMeta! +} + input WebsiteInterfaceFiltersInput { id: IDFilterInput library: StringFilterInput @@ -2668,6 +2781,23 @@ input WebsiteInterfaceFiltersInput { content: StringFilterInput result: StringFilterInput results: StringFilterInput + language_switch_message: StringFilterInput + open_settings: StringFilterInput + change_language: StringFilterInput + open_search: StringFilterInput + chronology: StringFilterInput + accords_handbook: StringFilterInput + legality: StringFilterInput + members: StringFilterInput + sharing_policy: StringFilterInput + contact_us: StringFilterInput + email: StringFilterInput + email_gdpr_notice: StringFilterInput + message: StringFilterInput + send: StringFilterInput + response_invalid_code: StringFilterInput + response_invalid_email: StringFilterInput + response_email_success: StringFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput and: [WebsiteInterfaceFiltersInput] @@ -2788,6 +2918,23 @@ input WebsiteInterfaceInput { content: String result: String results: String + language_switch_message: String + open_settings: String + change_language: String + open_search: String + chronology: String + accords_handbook: String + legality: String + members: String + sharing_policy: String + contact_us: String + email: String + email_gdpr_notice: String + message: String + send: String + response_invalid_code: String + response_invalid_email: String + response_email_success: String } type WebsiteInterface { @@ -2903,6 +3050,23 @@ type WebsiteInterface { content: String result: String results: String + language_switch_message: String + open_settings: String + change_language: String + open_search: String + chronology: String + accords_handbook: String + legality: String + members: String + sharing_policy: String + contact_us: String + email: String + email_gdpr_notice: String + message: String + send: String + response_invalid_code: String + response_invalid_email: String + response_email_success: String createdAt: DateTime updatedAt: DateTime } @@ -3009,6 +3173,7 @@ type WikiPageTypeEntityResponseCollection { union GenericMorph = ComponentBasicsCredits | ComponentBasicsDatepicker + | ComponentBasicsFileSize | ComponentBasicsPrice | ComponentBasicsSize | ComponentCollectionsComponentEvent @@ -3060,6 +3225,7 @@ union GenericMorph = | ComponentTranslationsWeaponStoryStory | ComponentTranslationsWeaponStoryType | ComponentTranslationsWeaponStory + | ComponentTranslationsWebArchives | UploadFile | AudioSubtype | Category @@ -3085,6 +3251,7 @@ union GenericMorph = | WeaponStory | WeaponStoryGroup | WeaponStoryType + | WebArchive | WebsiteInterface | WikiPage | WikiPageType @@ -3253,6 +3420,12 @@ type Query { pagination: PaginationArg = {} sort: [String] = [] ): WeaponStoryTypeEntityResponseCollection + webArchive(id: ID): WebArchiveEntityResponse + webArchives( + filters: WebArchiveFiltersInput + pagination: PaginationArg = {} + sort: [String] = [] + ): WebArchiveEntityResponseCollection websiteInterface(id: ID): WebsiteInterfaceEntityResponse websiteInterfaces( filters: WebsiteInterfaceFiltersInput @@ -3394,6 +3567,9 @@ type Mutation { data: WeaponStoryTypeInput! ): WeaponStoryTypeEntityResponse deleteWeaponStoryType(id: ID!): WeaponStoryTypeEntityResponse + createWebArchive(data: WebArchiveInput!): WebArchiveEntityResponse + updateWebArchive(id: ID!, data: WebArchiveInput!): WebArchiveEntityResponse + deleteWebArchive(id: ID!): WebArchiveEntityResponse createWebsiteInterface( data: WebsiteInterfaceInput! ): WebsiteInterfaceEntityResponse diff --git a/src/pages/about-us/accords-handbook.tsx b/src/pages/about-us/accords-handbook.tsx index 077d404..4c7ab4e 100644 --- a/src/pages/about-us/accords-handbook.tsx +++ b/src/pages/about-us/accords-handbook.tsx @@ -7,23 +7,23 @@ import ReturnButton, { } from "components/PanelComponents/ReturnButton"; import ContentPanel from "components/Panels/ContentPanel"; import SubPanel from "components/Panels/SubPanel"; -import { getPost, getPostLanguages } from "graphql/operations"; +import { getPost } from "graphql/operations"; import { GetPostQuery } from "graphql/operations-types"; import { GetStaticPropsContext } from "next"; import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; -import { prettySlug } from "queries/helpers"; +import { getLocalesFromLanguages, prettySlug } from "queries/helpers"; interface AccordsHandbookProps extends AppStaticProps { post: GetPostQuery["posts"]["data"][number]["attributes"]; - locales: string[]; } export default function AccordsHandbook( props: AccordsHandbookProps ): JSX.Element { - const { langui, post, locales } = props; + const { langui, post } = props; const router = useRouter(); + const locales = getLocalesFromLanguages(post.translations_languages); const subPanel = ( @@ -37,7 +37,6 @@ export default function AccordsHandbook( {post.translations.length > 0 && post.translations[0].body && ( )} @@ -54,11 +53,10 @@ export default function AccordsHandbook( className="mb-10" /> {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -92,11 +90,6 @@ export async function getStaticProps( language_code: context.locale ?? "en", }) ).posts.data[0].attributes, - locales: ( - await getPostLanguages({ slug: slug }) - ).posts.data[0].attributes.translations.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/about-us/contact.tsx b/src/pages/about-us/contact.tsx index eb53e32..a7a6d52 100644 --- a/src/pages/about-us/contact.tsx +++ b/src/pages/about-us/contact.tsx @@ -8,27 +8,27 @@ import ReturnButton, { } from "components/PanelComponents/ReturnButton"; import ContentPanel from "components/Panels/ContentPanel"; import SubPanel from "components/Panels/SubPanel"; -import { getPost, getPostLanguages } from "graphql/operations"; +import { getPost } from "graphql/operations"; import { GetPostQuery } from "graphql/operations-types"; import { GetStaticPropsContext } from "next"; import { useRouter } from "next/router"; import { RequestMailProps, ResponseMailProps } from "pages/api/mail"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; -import { randomInt } from "queries/helpers"; +import { getLocalesFromLanguages, randomInt } from "queries/helpers"; import { useState } from "react"; interface ContactProps extends AppStaticProps { post: GetPostQuery["posts"]["data"][number]["attributes"]; - locales: string[]; } export default function AboutUs(props: ContactProps): JSX.Element { - const { langui, post, locales } = props; + const { langui, post } = props; const router = useRouter(); const [formResponse, setFormResponse] = useState(""); const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">( "stale" ); + const locales = getLocalesFromLanguages(post.translations_languages); const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10)); const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10)); @@ -45,7 +45,6 @@ export default function AboutUs(props: ContactProps): JSX.Element { {post.translations.length > 0 && post.translations[0].body && ( )} @@ -62,11 +61,10 @@ export default function AboutUs(props: ContactProps): JSX.Element { className="mb-10" /> {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -236,11 +234,6 @@ export async function getStaticProps( language_code: context.locale ?? "en", }) ).posts.data[0].attributes, - locales: ( - await getPostLanguages({ slug: slug }) - ).posts.data[0].attributes.translations.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/about-us/index.tsx b/src/pages/about-us/index.tsx index bacee81..ca2d3a9 100644 --- a/src/pages/about-us/index.tsx +++ b/src/pages/about-us/index.tsx @@ -22,7 +22,7 @@ export default function AboutUs(props: AboutUsProps): JSX.Element { border /> - + {/* */} @@ -35,7 +35,6 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element { {post.translations.length > 0 && post.translations[0].body && ( )} @@ -52,11 +51,10 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element { className="mb-10" /> {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -90,11 +88,6 @@ export async function getStaticProps( language_code: context.locale ?? "en", }) ).posts.data[0].attributes, - locales: ( - await getPostLanguages({ slug: slug }) - ).posts.data[0].attributes.translations.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/about-us/sharing-policy.tsx b/src/pages/about-us/sharing-policy.tsx index 9434bd0..e75729b 100644 --- a/src/pages/about-us/sharing-policy.tsx +++ b/src/pages/about-us/sharing-policy.tsx @@ -7,20 +7,20 @@ import ReturnButton, { } from "components/PanelComponents/ReturnButton"; import ContentPanel from "components/Panels/ContentPanel"; import SubPanel from "components/Panels/SubPanel"; -import { getPost, getPostLanguages } from "graphql/operations"; +import { getPost } from "graphql/operations"; import { GetPostQuery } from "graphql/operations-types"; import { GetStaticPropsContext } from "next"; import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; -import { prettySlug } from "queries/helpers"; +import { getLocalesFromLanguages, prettySlug } from "queries/helpers"; interface SharingPolicyProps extends AppStaticProps { post: GetPostQuery["posts"]["data"][number]["attributes"]; - locales: string[]; } export default function SharingPolicy(props: SharingPolicyProps): JSX.Element { - const { langui, post, locales } = props; + const { langui, post } = props; + const locales = getLocalesFromLanguages(post.translations_languages); const router = useRouter(); const subPanel = ( @@ -35,7 +35,6 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element { {post.translations.length > 0 && post.translations[0].body && ( )} @@ -52,11 +51,10 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element { className="mb-10" /> {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -90,11 +88,6 @@ export async function getStaticProps( language_code: context.locale ?? "en", }) ).posts.data[0].attributes, - locales: ( - await getPostLanguages({ slug: slug }) - ).posts.data[0].attributes.translations.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/contents/[slug]/read.tsx b/src/pages/contents/[slug]/read.tsx index 6ac4d36..cbe3e94 100644 --- a/src/pages/contents/[slug]/read.tsx +++ b/src/pages/contents/[slug]/read.tsx @@ -13,11 +13,7 @@ import ContentPanel from "components/Panels/ContentPanel"; import SubPanel from "components/Panels/SubPanel"; import RecorderChip from "components/RecorderChip"; import ToolTip from "components/ToolTip"; -import { - getContentLanguages, - getContentsSlugs, - getContentText, -} from "graphql/operations"; +import { getContentsSlugs, getContentText } from "graphql/operations"; import { GetContentTextQuery } from "graphql/operations-types"; import { GetStaticPathsContext, @@ -27,6 +23,7 @@ import { import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { + getLocalesFromLanguages, getStatusDescription, prettyinlineTitle, prettyLanguage, @@ -38,13 +35,13 @@ import { interface ContentReadProps extends AppStaticProps { content: GetContentTextQuery["contents"]["data"][number]["attributes"]; contentId: GetContentTextQuery["contents"]["data"][number]["id"]; - locales: string[]; } export default function ContentRead(props: ContentReadProps): JSX.Element { useTesting(props); - const { langui, content, languages, locales } = props; + const { langui, content, languages } = props; const router = useRouter(); + const locales = getLocalesFromLanguages(content.text_set_languages); const subPanel = ( @@ -146,7 +143,6 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { 0 ? prettyinlineTitle( @@ -197,11 +193,10 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -263,11 +258,6 @@ export async function getStaticProps( ...(await getAppStaticProps(context)), content: content.attributes, contentId: content.id, - locales: ( - await getContentLanguages({ slug: slug }) - ).contents.data[0].attributes.text_set.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/editor.tsx b/src/pages/editor.tsx index 6d54deb..f919125 100644 --- a/src/pages/editor.tsx +++ b/src/pages/editor.tsx @@ -4,7 +4,6 @@ import ContentPanel, { ContentPanelWidthSizes, } from "components/Panels/ContentPanel"; import { GetStaticPropsContext } from "next"; -import { useRouter } from "next/router"; import Script from "next/script"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { useCallback, useState } from "react"; @@ -13,8 +12,6 @@ import { default as TurndownService } from "turndown"; interface EditorProps extends AppStaticProps {} export default function Editor(props: EditorProps): JSX.Element { - const router = useRouter(); - const handleInput = useCallback((event) => { setMarkdown(event.target.value); }, []); @@ -77,7 +74,7 @@ export default function Editor(props: EditorProps): JSX.Element {

Preview

- +
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index b0e757e..9a75997 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,20 +2,20 @@ import AppLayout from "components/AppLayout"; import LanguageSwitcher from "components/LanguageSwitcher"; import Markdawn from "components/Markdown/Markdawn"; import ContentPanel from "components/Panels/ContentPanel"; -import { getPost, getPostLanguages } from "graphql/operations"; +import { getPost } from "graphql/operations"; import { GetPostQuery } from "graphql/operations-types"; import { GetStaticPropsContext } from "next"; import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; -import { prettySlug } from "queries/helpers"; +import { getLocalesFromLanguages, prettySlug } from "queries/helpers"; interface HomeProps extends AppStaticProps { post: GetPostQuery["posts"]["data"][number]["attributes"]; - locales: string[]; } export default function Home(props: HomeProps): JSX.Element { - const { post, locales } = props; + const { post } = props; + const locales = getLocalesFromLanguages(post.translations_languages); const router = useRouter(); const contentPanel = ( @@ -28,11 +28,10 @@ export default function Home(props: HomeProps): JSX.Element { {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -65,11 +64,6 @@ export async function getStaticProps( language_code: context.locale ?? "en", }) ).posts.data[0].attributes, - locales: ( - await getPostLanguages({ slug: slug }) - ).posts.data[0].attributes.translations.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/library/[slug].tsx b/src/pages/library/[slug]/index.tsx similarity index 96% rename from src/pages/library/[slug].tsx rename to src/pages/library/[slug]/index.tsx index 4fd57d2..5529eaa 100644 --- a/src/pages/library/[slug].tsx +++ b/src/pages/library/[slug]/index.tsx @@ -106,7 +106,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element { )} {item.contents.data.length > 0 && ( - + appLayout.setSubPanelOpen(false)} + /> )}
diff --git a/src/pages/library/[slug]/scans.tsx b/src/pages/library/[slug]/scans.tsx new file mode 100644 index 0000000..970dd43 --- /dev/null +++ b/src/pages/library/[slug]/scans.tsx @@ -0,0 +1,180 @@ +import AppLayout from "components/AppLayout"; +import Img, { getAssetURL, ImageQuality } from "components/Img"; +import LanguageSwitcher from "components/LanguageSwitcher"; +import LightBox from "components/LightBox"; +import NavOption from "components/PanelComponents/NavOption"; +import ReturnButton, { + ReturnButtonType, +} from "components/PanelComponents/ReturnButton"; +import ContentPanel, { + ContentPanelWidthSizes, +} from "components/Panels/ContentPanel"; +import SubPanel from "components/Panels/SubPanel"; +import { useAppLayout } from "contexts/AppLayoutContext"; +import { getLibraryItemScans, getLibraryItemsSlugs } from "graphql/operations"; +import { GetLibraryItemScansQuery } from "graphql/operations-types"; +import { + GetStaticPathsContext, + GetStaticPathsResult, + GetStaticPropsContext, +} from "next"; +import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { prettyinlineTitle, prettySlug, sortContent } from "queries/helpers"; +import { useState } from "react"; + +interface Props extends AppStaticProps { + item: GetLibraryItemScansQuery["libraryItems"]["data"][number]["attributes"]; + itemId: GetLibraryItemScansQuery["libraryItems"]["data"][number]["id"]; +} + +export default function LibrarySlug(props: Props): JSX.Element { + const { item, langui } = props; + const appLayout = useAppLayout(); + + sortContent(item.contents); + + const [lightboxOpen, setLightboxOpen] = useState(false); + const [lightboxImages, setLightboxImages] = useState([""]); + const [lightboxIndex, setLightboxIndex] = useState(0); + + const subPanel = ( + + + + {item.contents.data.map((content) => ( + 0 && + content.attributes.range[0].__typename === "ComponentRangePageRange" + ? `${content.attributes.range[0].starting_page} → ${content.attributes.range[0].ending_page}` + : undefined + } + onClick={() => appLayout.setSubPanelOpen(false)} + border + /> + ))} + + ); + + const contentPanel = ( + + + + + {item.contents.data.map((content) => ( + <> +

+ {prettySlug(content.attributes.slug, item.slug)} +

+ + {content.attributes.scan_set.length > 0 ? ( +
+ {content.attributes.scan_set[0].pages.data.map((page, index) => ( +
{ + setLightboxOpen(true); + setLightboxImages( + content.attributes.scan_set[0].pages.data.map((image) => + getAssetURL(image.attributes.url, ImageQuality.Large) + ) + ); + setLightboxIndex(index); + }} + > + +
+ ))} +
+ ) : ( +
+ language.language.data.attributes.code + )} + languages={props.languages} + langui={props.langui} + href={`#${content.attributes.slug}`} + /> +
+ )} + + ))} +
+ ); + + return ( + + ); +} + +export async function getStaticProps( + context: GetStaticPropsContext +): Promise<{ props: Props }> { + const item = ( + await getLibraryItemScans({ + slug: context.params?.slug?.toString() ?? "", + language_code: context.locale ?? "en", + }) + ).libraryItems.data[0]; + const props: Props = { + ...(await getAppStaticProps(context)), + item: item.attributes, + itemId: item.id, + }; + return { + props: props, + }; +} + +export async function getStaticPaths( + context: GetStaticPathsContext +): Promise { + const libraryItems = await getLibraryItemsSlugs({}); + const paths: GetStaticPathsResult["paths"] = []; + libraryItems.libraryItems.data.map((item) => { + context.locales?.map((local) => { + paths.push({ params: { slug: item.attributes.slug }, locale: local }); + }); + }); + return { + paths, + fallback: false, + }; +} diff --git a/src/pages/news/[slug].tsx b/src/pages/news/[slug].tsx index fb59984..b3de014 100644 --- a/src/pages/news/[slug].tsx +++ b/src/pages/news/[slug].tsx @@ -12,7 +12,7 @@ import ContentPanel from "components/Panels/ContentPanel"; import SubPanel from "components/Panels/SubPanel"; import RecorderChip from "components/RecorderChip"; import ToolTip from "components/ToolTip"; -import { getPost, getPostLanguages, getPostsSlugs } from "graphql/operations"; +import { getPost, getPostsSlugs } from "graphql/operations"; import { GetPostQuery, StrapiImage } from "graphql/operations-types"; import { GetStaticPathsContext, @@ -21,16 +21,20 @@ import { } from "next"; import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; -import { getStatusDescription, prettySlug } from "queries/helpers"; +import { + getLocalesFromLanguages, + getStatusDescription, + prettySlug, +} from "queries/helpers"; interface PostProps extends AppStaticProps { post: GetPostQuery["posts"]["data"][number]["attributes"]; postId: GetPostQuery["posts"]["data"][number]["id"]; - locales: string[]; } export default function LibrarySlug(props: PostProps): JSX.Element { - const { post, locales, langui } = props; + const { post, langui } = props; + const locales = getLocalesFromLanguages(post.translations_languages); const router = useRouter(); const thumbnail: StrapiImage | undefined = @@ -79,7 +83,6 @@ export default function LibrarySlug(props: PostProps): JSX.Element { {post.translations.length > 0 && post.translations[0].body && ( )} @@ -114,11 +117,10 @@ export default function LibrarySlug(props: PostProps): JSX.Element { {locales.includes(router.locale ?? "en") ? ( - + ) : ( @@ -156,11 +158,6 @@ export async function getStaticProps( ...(await getAppStaticProps(context)), post: post.attributes, postId: post.id, - locales: ( - await getPostLanguages({ slug: slug }) - ).posts.data[0].attributes.translations.map( - (translation) => translation.language.data.attributes.code - ), }; return { props: props, diff --git a/src/pages/wiki/chronology.tsx b/src/pages/wiki/chronology.tsx index 68a000f..59ca190 100644 --- a/src/pages/wiki/chronology.tsx +++ b/src/pages/wiki/chronology.tsx @@ -7,6 +7,7 @@ import ReturnButton, { } from "components/PanelComponents/ReturnButton"; import ContentPanel from "components/Panels/ContentPanel"; import SubPanel from "components/Panels/SubPanel"; +import { useAppLayout } from "contexts/AppLayoutContext"; import { getChronologyItems, getEras } from "graphql/operations"; import { GetChronologyItemsQuery, @@ -29,6 +30,7 @@ interface ChronologyProps extends AppStaticProps { export default function Chronology(props: ChronologyProps): JSX.Element { useTesting(props); const { chronologyItems, chronologyEras, langui } = props; + const appLayout = useAppLayout(); // Group by year the Chronology items const chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] = @@ -83,6 +85,7 @@ export default function Chronology(props: ChronologyProps): JSX.Element { } subtitle={`${era.attributes.starting_year} → ${era.attributes.ending_year}`} border + onClick={() => appLayout.setSubPanelOpen(false)} /> ))}
diff --git a/src/queries/helpers.ts b/src/queries/helpers.ts index a7b55dd..c784164 100644 --- a/src/queries/helpers.ts +++ b/src/queries/helpers.ts @@ -232,9 +232,13 @@ export function getOgImage(quality: ImageQuality, image: StrapiImage): OgImage { }; } -export function sortContent( - contents: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]["contents"] -) { +export function sortContent(contents: { + data: { + attributes: { + range: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]["contents"]["data"][number]["attributes"]["range"]; + }; + }[]; +}) { contents.data.sort((a, b) => { if ( a.attributes.range[0].__typename === "ComponentRangePageRange" && @@ -294,3 +298,17 @@ export function slugify(string: string | undefined): string { export function randomInt(min: number, max: number) { return Math.floor(Math.random() * (max - min)) + min; } + +export function getLocalesFromLanguages( + languages: { + language: { + data: { + attributes: { + code: string; + }; + }; + }; + }[] +) { + return languages.map((language) => language.language.data.attributes.code); +}