Added basic wiki
This commit is contained in:
parent
4b1a9d570f
commit
b0fb445518
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
query getWikiPagesSlugs {
|
||||||
|
wikiPages(pagination: { limit: -1 }) {
|
||||||
|
data {
|
||||||
|
attributes {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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",
|
||||||
|
};
|
||||||
|
}
|
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue