Added basic wiki

This commit is contained in:
DrMint 2022-06-12 13:52:32 +02:00
parent 4b1a9d570f
commit b0fb445518
5 changed files with 374 additions and 3 deletions

View File

@ -0,0 +1,103 @@
query getWikiPage($slug: String, $language_code: String) {
wikiPages(filters: { slug: { eq: $slug } }) {
data {
id
attributes {
slug
thumbnail {
data {
attributes {
...uploadImage
}
}
}
categories {
data {
id
attributes {
name
short
}
}
}
translations {
title
aliases {
alias
}
summary
language {
data {
attributes {
code
}
}
}
body {
source_language {
data {
attributes {
code
}
}
}
status
body
authors {
data {
id
attributes {
...recorderChip
}
}
}
translators {
data {
id
attributes {
...recorderChip
}
}
}
proofreaders {
data {
id
attributes {
...recorderChip
}
}
}
}
}
definitions {
source {
data {
attributes {
name
}
}
}
translations {
language {
data {
attributes {
code
}
}
}
source_language {
data {
attributes {
code
}
}
}
status
definition
}
}
}
}
}
}

View File

@ -0,0 +1,40 @@
query getWikiPagesPreviews {
wikiPages(pagination: { limit: -1 }) {
data {
id
attributes {
slug
thumbnail {
data {
attributes {
...uploadImage
}
}
}
categories {
data {
id
attributes {
name
short
}
}
}
translations {
title
aliases {
alias
}
summary
language {
data {
attributes {
code
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,9 @@
query getWikiPagesSlugs {
wikiPages(pagination: { limit: -1 }) {
data {
attributes {
slug
}
}
}
}

View File

@ -0,0 +1,74 @@
import { AppLayout } from "components/AppLayout";
import { ContentPanel } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel";
import { GetWikiPageQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { Immutable } from "helpers/types";
import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
interface Props extends AppStaticProps {
page: NonNullable<
NonNullable<GetWikiPageQuery["wikiPages"]>["data"][number]["attributes"]
>;
}
export default function WikiPage(props: Immutable<Props>): JSX.Element {
const { page, langui } = props;
const subPanel = <SubPanel>Hello</SubPanel>;
const contentPanel = <ContentPanel>{page.slug}</ContentPanel>;
return (
<AppLayout
navTitle={langui.news}
subPanel={subPanel}
contentPanel={contentPanel}
{...props}
/>
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = context.params?.slug ? context.params.slug.toString() : "";
const page = await sdk.getWikiPage({
language_code: context.locale ?? "en",
slug: slug,
});
if (!page.wikiPages?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
page: page.wikiPages.data[0].attributes,
};
return {
props: props,
};
}
export async function getStaticPaths(
context: GetStaticPathsContext
): Promise<GetStaticPathsResult> {
const sdk = getReadySdk();
const contents = await sdk.getWikiPagesSlugs();
const paths: GetStaticPathsResult["paths"] = [];
contents.wikiPages?.data.map((wikiPage) => {
context.locales?.map((local) => {
if (wikiPage.attributes)
paths.push({
params: { slug: wikiPage.attributes.slug },
locale: local,
});
});
});
return {
paths,
fallback: "blocking",
};
}

View File

@ -6,11 +6,49 @@ import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types"; import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next"; import { GetStaticPropsContext } from "next";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { getReadySdk } from "graphql/sdk";
import { GetWikiPagesPreviewsQuery } from "graphql/generated";
import {
ContentPanel,
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import { Fragment, useEffect, useState } from "react";
import { TranslatedPreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine";
import { Button } from "components/Inputs/Button";
import { Switch } from "components/Inputs/Switch";
import { TextInput } from "components/Inputs/TextInput";
import { WithLabel } from "components/Inputs/WithLabel";
import { useMediaHoverable } from "hooks/useMediaQuery";
interface Props extends AppStaticProps {} interface Props extends AppStaticProps {
pages: NonNullable<GetWikiPagesPreviewsQuery["wikiPages"]>["data"];
}
const defaultFiltersState = {
searchName: "",
keepInfoVisible: true,
};
export default function Wiki(props: Immutable<Props>): JSX.Element { export default function Wiki(props: Immutable<Props>): JSX.Element {
const { langui } = props; const { langui, languages } = props;
const pages = sortPages(props.pages);
const hoverable = useMediaHoverable();
const [searchName, setSearchName] = useState(defaultFiltersState.searchName);
const [keepInfoVisible, setKeepInfoVisible] = useState(
defaultFiltersState.keepInfoVisible
);
const [filteredPages, setFilteredPages] = useState(
filterPages(pages, searchName)
);
useEffect(() => {
setFilteredPages(filterPages(pages, searchName));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchName]);
const subPanel = ( const subPanel = (
<SubPanel> <SubPanel>
<PanelHeader <PanelHeader
@ -18,20 +56,127 @@ export default function Wiki(props: Immutable<Props>): JSX.Element {
title={langui.wiki} title={langui.wiki}
description={langui.wiki_description} description={langui.wiki_description}
/> />
<TextInput
className="mb-6 w-full"
placeholder={langui.search_title ?? undefined}
state={searchName}
setState={setSearchName}
/>
{hoverable && (
<WithLabel
label={langui.always_show_info}
input={
<Switch setState={setKeepInfoVisible} state={keepInfoVisible} />
}
/>
)}
<Button
className="mt-8"
text={langui.reset_all_filters}
icon={Icon.Replay}
onClick={() => {
setSearchName(defaultFiltersState.searchName);
setKeepInfoVisible(defaultFiltersState.keepInfoVisible);
}}
/>
<HorizontalLine />
{/* TODO: Langui */}
<p className="mb-4 font-headers text-xl">Special Pages</p>
<NavOption title={langui.chronology} url="/wiki/chronology" border /> <NavOption title={langui.chronology} url="/wiki/chronology" border />
</SubPanel> </SubPanel>
); );
return <AppLayout navTitle={langui.wiki} subPanel={subPanel} {...props} />; const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.Large}>
<div
className="grid grid-cols-2 items-end gap-8
desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))] mobile:gap-4"
>
{filteredPages.map((page) => (
<Fragment key={page.id}>
{page.attributes && (
<TranslatedPreviewCard
href={`/wiki/${page.attributes.slug}`}
translations={page.attributes.translations?.map(
(translation) => ({
title: translation?.title,
description: translation?.summary,
language: translation?.language?.data?.attributes?.code,
})
)}
thumbnail={page.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio={"4/3"}
thumbnailRounded
thumbnailForceAspectRatio
languages={languages}
slug={page.attributes.slug}
keepInfoVisible={keepInfoVisible}
bottomChips={page.attributes.categories?.data.map(
(category) => category.attributes?.short ?? ""
)}
/>
)}
</Fragment>
))}
</div>
</ContentPanel>
);
return (
<AppLayout
navTitle={langui.wiki}
subPanel={subPanel}
contentPanel={contentPanel}
subPanelIcon={Icon.Search}
{...props}
/>
);
} }
export async function getStaticProps( export async function getStaticProps(
context: GetStaticPropsContext context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> { ): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const pages = await sdk.getWikiPagesPreviews({});
if (!pages.wikiPages?.data) return { notFound: true };
const props: Props = { const props: Props = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
pages: pages.wikiPages.data,
}; };
return { return {
props: props, props: props,
}; };
} }
function sortPages(
pages: Immutable<Props["pages"]>
): Immutable<Props["pages"]> {
const sortedPages = [...pages] as Props["pages"];
sortedPages.sort((a, b) => {
const slugA = a.attributes?.slug ?? "";
const slugB = b.attributes?.slug ?? "";
return slugA.localeCompare(slugB);
});
return sortedPages as Immutable<Props["pages"]>;
}
function filterPages(posts: Immutable<Props["pages"]>, searchName: string) {
return [...posts].filter((post) => {
if (searchName.length > 1) {
if (
post.attributes?.translations?.[0]?.title
.toLowerCase()
.includes(searchName.toLowerCase())
) {
return true;
}
return false;
}
return true;
});
}