diff --git a/next.config.js b/next.config.js index f8dd901..5d7877c 100644 --- a/next.config.js +++ b/next.config.js @@ -3,7 +3,7 @@ module.exports = { swcMinify: true, reactStrictMode: true, i18n: { - locales: ["en", "fr", "ja", "es"], + locales: ["en", "fr", "ja", "es", "pt-br"], defaultLocale: "en", }, images: { diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 97fc640..0d713ee 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -1,7 +1,4 @@ -import { - GetWebsiteInterfaceQuery, - StrapiImage, -} from "graphql/operations-types"; +import { StrapiImage } from "graphql/operations-types"; import MainPanel from "./Panels/MainPanel"; import Head from "next/head"; import { useSwipeable } from "react-swipeable"; diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx new file mode 100644 index 0000000..921879a --- /dev/null +++ b/src/components/LanguageSwitcher.tsx @@ -0,0 +1,40 @@ +import { + GetLanguagesQuery, + GetWebsiteInterfaceQuery, +} from "graphql/operations-types"; +import { NextRouter } from "next/router"; +import { prettyLanguage } from "queries/helpers"; +import Button from "./Button"; + +type HorizontalLineProps = { + className?: string; + locales: string[]; + router: NextRouter; + languages: GetLanguagesQuery["languages"]["data"]; + langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]; +}; + +export default function HorizontalLine( + props: HorizontalLineProps +): JSX.Element { + const { locales, router, langui } = props; + return ( +
+
+

{langui.language_switch_message}

+
+ {locales.map((locale, index) => ( + + ))} +
+
+
+ ); +} diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx index 4cb08c1..36e8e1f 100644 --- a/src/components/Markdown/Markdawn.tsx +++ b/src/components/Markdown/Markdawn.tsx @@ -5,18 +5,22 @@ 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 { slugify } from "queries/helpers"; import React, { useState } from "react"; -type ScenBreakProps = { +type MarkdawnProps = { className?: string; text: string; + router: NextRouter; }; -export default function Markdawn(props: ScenBreakProps): JSX.Element { +export default function Markdawn(props: MarkdawnProps): JSX.Element { const appLayout = useAppLayout(); const text = preprocessMarkDawn(props.text); + const { router } = props; + const [lightboxOpen, setLightboxOpen] = useState(false); const [lightboxImages, setLightboxImages] = useState([""]); const [lightboxIndex, setLightboxIndex] = useState(0); @@ -43,12 +47,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { children: React.ReactNode; }) => { return ( -
-

- {props.children} -

+

+ {props.children} -

+ ); }, }, @@ -59,12 +61,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { children: React.ReactNode; }) => { return ( -
-

- {props.children} -

+

+ {props.children} -

+ ); }, }, @@ -75,12 +75,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { children: React.ReactNode; }) => { return ( -
-

- {props.children} -

+

+ {props.children} -

+ ); }, }, @@ -91,12 +89,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { children: React.ReactNode; }) => { return ( -
-

- {props.children} -

+

+ {props.children} -

+ ); }, }, @@ -107,12 +103,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { children: React.ReactNode; }) => { return ( -
-
- {props.children} -
+
+ {props.children} -
+ ); }, }, @@ -123,12 +117,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { children: React.ReactNode; }) => { return ( -
-
- {props.children} -
+
+ {props.children} -
+ ); }, }, @@ -151,6 +143,28 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { ); }, }, + IntraLink: { + component: (props: { + children: React.ReactNode; + target?: string; + page?: string; + }) => { + const slug = props.target + ? slugify(props.target) + : slugify(props.children?.toString()); + return ( + + router.replace( + `${props.page ? props.page : ""}#${slug}` + ) + } + > + {props.children} + + ); + }, + }, player: { component: () => { return ( @@ -219,6 +233,25 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { ); }, }, + blockquote: { + component: (props: { + children: React.ReactNode; + cite?: string; + }) => { + return ( +
+ {props.cite ? ( + <> + “{props.children}” + — {props.cite} + + ) : ( + props.children + )} +
+ ); + }, + }, img: { component: (props: { alt: string; @@ -230,7 +263,7 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { }) => { return (
{ setLightboxOpen(true); setLightboxImages([ @@ -280,8 +313,12 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { function HeaderToolTip(props: { id: string }) { return ( - - + + { @@ -301,6 +338,8 @@ function HeaderToolTip(props: { id: string }) { } export function preprocessMarkDawn(text: string): string { + if (!text) return ""; + let scenebreakIndex = 0; const visitedSlugs: string[] = []; diff --git a/src/components/Markdown/TOC.tsx b/src/components/Markdown/TOC.tsx index 8e50a0e..aed7dfb 100644 --- a/src/components/Markdown/TOC.tsx +++ b/src/components/Markdown/TOC.tsx @@ -49,7 +49,7 @@ function TOCLevel(props: TOCLevelProps): JSX.Element { > {`${parentNumbering}${ childIndex + 1 - }.`} + }.`}{" "} router.replace(`#${child.slug}`)}> {{child.title}} diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx index a705e48..11789ce 100644 --- a/src/components/Panels/MainPanel.tsx +++ b/src/components/Panels/MainPanel.tsx @@ -64,7 +64,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { } flex-wrap gap-2`} > {"Open settings"}} + content={

{langui.open_settings}

} placement="right" className="text-left" disabled={!appLayout.mainPanelReduced} @@ -91,7 +91,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { {router.locale && ( {"Change language"}} + content={

{langui.change_language}

} placement="right" className="text-left" disabled={!appLayout.mainPanelReduced} @@ -110,7 +110,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { )} {"Open search"}} + content={

{langui.open_search}

} placement="right" className="text-left" disabled={!appLayout.mainPanelReduced} @@ -155,18 +155,17 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { onClick={() => appLayout.setMainPanelOpen(false)} /> - {/* - appLayout.setMainPanelOpen(false)} /> + {/* + ; }; @@ -1737,3 +1747,77 @@ export type GetPostsPreviewQuery = { }>; }; }; + +export type GetPostLanguagesQueryVariables = Exact<{ + slug: InputMaybe; +}>; + +export type GetPostLanguagesQuery = { + __typename: "Query"; + posts: { + __typename: "PostEntityResponseCollection"; + data: Array<{ + __typename: "PostEntity"; + attributes: { + __typename: "Post"; + translations: Array<{ + __typename: "ComponentTranslationsPosts"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { __typename: "Language"; code: string }; + }; + }; + }>; + }; + }>; + }; +}; + +export type GetContentLanguagesQueryVariables = Exact<{ + slug: InputMaybe; +}>; + +export type GetContentLanguagesQuery = { + __typename: "Query"; + contents: { + __typename: "ContentEntityResponseCollection"; + data: Array<{ + __typename: "ContentEntity"; + attributes: { + __typename: "Content"; + text_set: Array<{ + __typename: "ComponentSetsTextSet"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { __typename: "Language"; code: string }; + }; + }; + }>; + video_set: Array<{ + __typename: "ComponentSetsVideoSet"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { __typename: "Language"; code: string }; + }; + }; + }>; + audio_set: Array<{ + __typename: "ComponentSetsAudioSet"; + language: { + __typename: "LanguageEntityResponse"; + data: { + __typename: "LanguageEntity"; + attributes: { __typename: "Language"; code: string }; + }; + }; + }>; + }; + }>; + }; +}; diff --git a/src/graphql/operations.ts b/src/graphql/operations.ts index 74a55f2..e1342cd 100644 --- a/src/graphql/operations.ts +++ b/src/graphql/operations.ts @@ -3,6 +3,8 @@ import { readFileSync } from "fs"; import { GetChronologyItemsQuery, GetChronologyItemsQueryVariables, + GetContentLanguagesQuery, + GetContentLanguagesQueryVariables, GetContentQuery, GetContentQueryVariables, GetContentsQuery, @@ -23,6 +25,8 @@ import { GetLibraryItemsPreviewQueryVariables, GetLibraryItemsSlugsQuery, GetLibraryItemsSlugsQueryVariables, + GetPostLanguagesQuery, + GetPostLanguagesQueryVariables, GetPostQuery, GetPostQueryVariables, GetPostsPreviewQuery, @@ -168,3 +172,17 @@ export async function getPostsPreview( const query = getQueryFromOperations("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"); + return await graphQL(query, JSON.stringify(variables)); +} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index b073451..1f34c1a 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,8 +1,10 @@ import type { AppProps } from "next/app"; import "tailwind.css"; import "@fontsource/zen-maru-gothic/500.css"; +import "@fontsource/zen-maru-gothic/900.css"; import "@fontsource/vollkorn/700.css"; import "@fontsource/opendyslexic/400.css"; +import "@fontsource/opendyslexic/700.css"; import "@fontsource/material-icons"; import { AppContextProvider } from "contexts/AppLayoutContext"; diff --git a/src/pages/about-us/accords-handbook.tsx b/src/pages/about-us/accords-handbook.tsx new file mode 100644 index 0000000..bdfa474 --- /dev/null +++ b/src/pages/about-us/accords-handbook.tsx @@ -0,0 +1,102 @@ +import AppLayout from "components/AppLayout"; +import LanguageSwitcher from "components/LanguageSwitcher"; +import Markdawn from "components/Markdown/Markdawn"; +import TOC from "components/Markdown/TOC"; +import ReturnButton, { + ReturnButtonType, +} from "components/PanelComponents/ReturnButton"; +import ContentPanel from "components/Panels/ContentPanel"; +import SubPanel from "components/Panels/SubPanel"; +import { getPost, getPostLanguages } from "graphql/operations"; +import { GetPostQuery } from "graphql/operations-types"; +import { GetStaticProps } from "next"; +import { useRouter } from "next/router"; +import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { 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 router = useRouter(); + + const subPanel = ( + + + {post.translations.length > 0 && post.translations[0].body && ( + + )} + + ); + + const contentPanel = ( + + + {locales.includes(router.locale || "en") ? ( + + ) : ( + + )} + + ); + + return ( + 0 + ? post.translations[0].title + : prettySlug(post.slug) + } + subPanel={subPanel} + contentPanel={contentPanel} + {...props} + /> + ); +} + +export const getStaticProps: GetStaticProps = async (context) => { + const slug = "accords-handbook"; + const props: AccordsHandbookProps = { + ...(await getAppStaticProps(context)), + post: ( + await getPost({ + slug: slug, + language_code: context.locale || "en", + }) + ).posts.data[0].attributes, + locales: ( + await getPostLanguages({ slug: slug }) + ).posts.data[0].attributes.translations.map((translation) => { + return 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 32fdb35..089983e 100644 --- a/src/pages/about-us/index.tsx +++ b/src/pages/about-us/index.tsx @@ -16,15 +16,19 @@ 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/legality.tsx b/src/pages/about-us/legality.tsx new file mode 100644 index 0000000..f67a28a --- /dev/null +++ b/src/pages/about-us/legality.tsx @@ -0,0 +1,100 @@ +import AppLayout from "components/AppLayout"; +import LanguageSwitcher from "components/LanguageSwitcher"; +import Markdawn from "components/Markdown/Markdawn"; +import TOC from "components/Markdown/TOC"; +import ReturnButton, { + ReturnButtonType, +} from "components/PanelComponents/ReturnButton"; +import ContentPanel from "components/Panels/ContentPanel"; +import SubPanel from "components/Panels/SubPanel"; +import { getPost, getPostLanguages } from "graphql/operations"; +import { GetPostQuery } from "graphql/operations-types"; +import { GetStaticProps } from "next"; +import { useRouter } from "next/router"; +import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { prettySlug } from "queries/helpers"; + +interface SiteInfoProps extends AppStaticProps { + post: GetPostQuery["posts"]["data"][number]["attributes"]; + locales: string[]; +} + +export default function SiteInformation(props: SiteInfoProps): JSX.Element { + const { langui, post, locales } = props; + const router = useRouter(); + + const subPanel = ( + + + {post.translations.length > 0 && post.translations[0].body && ( + + )} + + ); + + const contentPanel = ( + + + {locales.includes(router.locale || "en") ? ( + + ) : ( + + )} + + ); + + return ( + 0 + ? post.translations[0].title + : prettySlug(post.slug) + } + subPanel={subPanel} + contentPanel={contentPanel} + {...props} + /> + ); +} + +export const getStaticProps: GetStaticProps = async (context) => { + const slug = "legality"; + const props: SiteInfoProps = { + ...(await getAppStaticProps(context)), + post: ( + await getPost({ + slug: slug, + language_code: context.locale || "en", + }) + ).posts.data[0].attributes, + locales: ( + await getPostLanguages({ slug: slug }) + ).posts.data[0].attributes.translations.map((translation) => { + return 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 new file mode 100644 index 0000000..f0a9a25 --- /dev/null +++ b/src/pages/about-us/sharing-policy.tsx @@ -0,0 +1,100 @@ +import AppLayout from "components/AppLayout"; +import LanguageSwitcher from "components/LanguageSwitcher"; +import Markdawn from "components/Markdown/Markdawn"; +import TOC from "components/Markdown/TOC"; +import ReturnButton, { + ReturnButtonType, +} from "components/PanelComponents/ReturnButton"; +import ContentPanel from "components/Panels/ContentPanel"; +import SubPanel from "components/Panels/SubPanel"; +import { getPost, getPostLanguages } from "graphql/operations"; +import { GetPostQuery } from "graphql/operations-types"; +import { GetStaticProps } from "next"; +import { useRouter } from "next/router"; +import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { 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 router = useRouter(); + + const subPanel = ( + + + {post.translations.length > 0 && post.translations[0].body && ( + + )} + + ); + + const contentPanel = ( + + + {locales.includes(router.locale || "en") ? ( + + ) : ( + + )} + + ); + + return ( + 0 + ? post.translations[0].title + : prettySlug(post.slug) + } + subPanel={subPanel} + contentPanel={contentPanel} + {...props} + /> + ); +} + +export const getStaticProps: GetStaticProps = async (context) => { + const slug = "sharing-policy"; + const props: SharingPolicyProps = { + ...(await getAppStaticProps(context)), + post: ( + await getPost({ + slug: "sharing-policy", + language_code: context.locale || "en", + }) + ).posts.data[0].attributes, + locales: ( + await getPostLanguages({ slug: slug }) + ).posts.data[0].attributes.translations.map((translation) => { + return translation.language.data.attributes.code; + }), + }; + return { + props: props, + }; +}; diff --git a/src/pages/about-us/site-information.tsx b/src/pages/about-us/site-information.tsx deleted file mode 100644 index 8ff04c8..0000000 --- a/src/pages/about-us/site-information.tsx +++ /dev/null @@ -1,60 +0,0 @@ -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/contents/[slug]/read.tsx b/src/pages/contents/[slug]/read.tsx index c770ebf..745e4c3 100644 --- a/src/pages/contents/[slug]/read.tsx +++ b/src/pages/contents/[slug]/read.tsx @@ -1,5 +1,9 @@ import { GetStaticPaths, GetStaticProps } from "next"; -import { getContentsSlugs, getContentText } from "graphql/operations"; +import { + getContentLanguages, + getContentsSlugs, + getContentText, +} from "graphql/operations"; import { GetContentTextQuery } from "graphql/operations-types"; import ContentPanel from "components/Panels/ContentPanel"; import HorizontalLine from "components/HorizontalLine"; @@ -25,15 +29,17 @@ import RecorderChip from "components/RecorderChip"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import TOC from "components/Markdown/TOC"; import ToolTip from "components/ToolTip"; +import LanguageSwitcher from "components/LanguageSwitcher"; 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 } = props; + const { langui, content, languages, locales } = props; const router = useRouter(); const subPanel = ( @@ -186,8 +192,15 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { - {content.text_set.length > 0 && content.text_set[0].text && ( - + {locales.includes(router.locale || "en") ? ( + + ) : ( + )}
@@ -235,9 +248,10 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { } export const getStaticProps: GetStaticProps = async (context) => { + const slug = context.params?.slug?.toString() || ""; const content = ( await getContentText({ - slug: context.params?.slug?.toString() || "", + slug: slug, language_code: context.locale || "en", }) ).contents.data[0]; @@ -245,6 +259,11 @@ export const getStaticProps: GetStaticProps = async (context) => { ...(await getAppStaticProps(context)), content: content.attributes, contentId: content.id, + locales: ( + await getContentLanguages({ slug: slug }) + ).contents.data[0].attributes.text_set.map((translation) => { + return translation.language.data.attributes.code; + }), }; return { props: props, diff --git a/src/pages/editor.tsx b/src/pages/editor.tsx index 825ed90..b770c0e 100644 --- a/src/pages/editor.tsx +++ b/src/pages/editor.tsx @@ -7,11 +7,13 @@ import { useCallback, useState } from "react"; import Markdawn from "components/Markdown/Markdawn"; import Script from "next/script"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { useRouter } from "next/router"; interface EditorProps extends AppStaticProps {} export default function Editor(props: EditorProps): JSX.Element { const { langui } = props; + const router = useRouter(); const handleInput = useCallback((e) => { setMarkdown(e.target.value); @@ -76,7 +78,7 @@ export default function Editor(props: EditorProps): JSX.Element {

Preview

- +
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index d65e0d6..e771302 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,18 +1,23 @@ import AppLayout from "components/AppLayout"; +import LanguageSwitcher from "components/LanguageSwitcher"; import Markdawn from "components/Markdown/Markdawn"; import ContentPanel from "components/Panels/ContentPanel"; -import { getPost } from "graphql/operations"; +import { getPost, getPostLanguages } from "graphql/operations"; import { GetPostQuery } from "graphql/operations-types"; import { GetStaticProps } from "next"; +import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { 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 } = props; + const { post, locales } = props; + const router = useRouter(); + const contentPanel = (
@@ -22,8 +27,15 @@ export default function Home(props: HomeProps): JSX.Element { Discover • Analyse • Translate • Archive
- {post.translations.length > 0 && ( - + {locales.includes(router.locale || "en") ? ( + + ) : ( + )}
); @@ -42,14 +54,20 @@ export default function Home(props: HomeProps): JSX.Element { } export const getStaticProps: GetStaticProps = async (context) => { + const slug = "home"; const props: HomeProps = { ...(await getAppStaticProps(context)), post: ( await getPost({ - slug: "home", + slug: slug, language_code: context.locale || "en", }) ).posts.data[0].attributes, + locales: ( + await getPostLanguages({ slug: slug }) + ).posts.data[0].attributes.translations.map((translation) => { + return translation.language.data.attributes.code; + }), }; return { props: props, diff --git a/src/pages/news/[slug].tsx b/src/pages/news/[slug].tsx index 3a7334a..bafb633 100644 --- a/src/pages/news/[slug].tsx +++ b/src/pages/news/[slug].tsx @@ -2,6 +2,7 @@ import AppLayout from "components/AppLayout"; import Chip from "components/Chip"; import ThumbnailHeader from "components/Content/ThumbnailHeader"; import HorizontalLine from "components/HorizontalLine"; +import LanguageSwitcher from "components/LanguageSwitcher"; import Markdawn from "components/Markdown/Markdawn"; import TOC from "components/Markdown/TOC"; import ReturnButton, { @@ -11,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, getPostsSlugs } from "graphql/operations"; +import { getPost, getPostLanguages, getPostsSlugs } from "graphql/operations"; import { GetPostQuery, StrapiImage } from "graphql/operations-types"; import { GetStaticPaths, GetStaticProps } from "next"; import { useRouter } from "next/router"; @@ -21,10 +22,11 @@ import { prettySlug, getStatusDescription } 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, postId, langui } = props; + const { post, locales, langui } = props; const router = useRouter(); const thumbnail: StrapiImage | undefined = @@ -107,8 +109,15 @@ export default function LibrarySlug(props: PostProps): JSX.Element { - {post.translations.length > 0 && post.translations[0].body && ( - + {locales.includes(router.locale || "en") ? ( + + ) : ( + )} ); @@ -130,9 +139,10 @@ export default function LibrarySlug(props: PostProps): JSX.Element { } export const getStaticProps: GetStaticProps = async (context) => { + const slug = context.params?.slug?.toString() || ""; const post = ( await getPost({ - slug: context.params?.slug?.toString() || "", + slug: slug, language_code: context.locale || "en", }) ).posts.data[0]; @@ -140,6 +150,11 @@ export const getStaticProps: GetStaticProps = async (context) => { ...(await getAppStaticProps(context)), post: post.attributes, postId: post.id, + locales: ( + await getPostLanguages({ slug: slug }) + ).posts.data[0].attributes.translations.map((translation) => { + return translation.language.data.attributes.code; + }), }; return { props: props, diff --git a/src/pages/news/index.tsx b/src/pages/news/index.tsx index 7aa352a..82c361a 100644 --- a/src/pages/news/index.tsx +++ b/src/pages/news/index.tsx @@ -5,7 +5,9 @@ import AppLayout from "components/AppLayout"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { GetPostsPreviewQuery } from "graphql/operations-types"; import { getPostsPreview } from "graphql/operations"; -import ContentPanel, { ContentPanelWidthSizes } from "components/Panels/ContentPanel"; +import ContentPanel, { + ContentPanelWidthSizes, +} from "components/Panels/ContentPanel"; import PostsPreview from "components/News/PostsPreview"; interface NewsProps extends AppStaticProps { diff --git a/src/pages/wiki/chronology.tsx b/src/pages/wiki/chronology.tsx index f31f9e4..d892db9 100644 --- a/src/pages/wiki/chronology.tsx +++ b/src/pages/wiki/chronology.tsx @@ -17,6 +17,9 @@ import { import InsetBox from "components/InsetBox"; import { useRouter } from "next/router"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import ReturnButton, { + ReturnButtonType, +} from "components/PanelComponents/ReturnButton"; interface ChronologyProps extends AppStaticProps { chronologyItems: GetChronologyItemsQuery["chronologyItems"]["data"]; @@ -60,6 +63,14 @@ export default function Chronology(props: ChronologyProps): JSX.Element { const subPanel = ( + + {chronologyEras.map((era) => ( + + {chronologyItemYearGroups.map((era, eraIndex) => ( <> + ); diff --git a/src/queries/helpers.ts b/src/queries/helpers.ts index 9e7200c..7393aa1 100644 --- a/src/queries/helpers.ts +++ b/src/queries/helpers.ts @@ -274,8 +274,9 @@ export function getStatusDescription( } } -export function slugify(str: string): string { - return str +export function slugify(string: string | undefined): string { + if (!string) return ""; + return string .replace(/[ÀÁÂÃÄÅàáâãäåæÆ]/g, "a") .replace(/[çÇ]/g, "c") .replace(/[ðÐ]/g, "d") diff --git a/src/tailwind.css b/src/tailwind.css index 14a9584..80f03cd 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -54,7 +54,7 @@ .formatted h4, .formatted h5, .formatted h6 { - @apply text-center; + @apply text-center flex gap-3 justify-center; } .formatted h1 { @@ -94,6 +94,10 @@ @apply my-2 text-justify; } + .formatted strong { + @apply font-black; + } + .formatted footer { @apply border-t-[3px] border-dotted pt-6; } @@ -122,6 +126,14 @@ @apply list-decimal pl-4; } + .formatted blockquote { + @apply border-2 border-mid rounded-lg p-5 text-center my-8; + } + + .formatted blockquote cite { + @apply text-dark block; + } + /* INPUT */ input {