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 { GetStaticPropsContext } from "next";
|
||||
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 {
|
||||
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 = (
|
||||
<SubPanel>
|
||||
<PanelHeader
|
||||
|
@ -18,20 +56,127 @@ export default function Wiki(props: Immutable<Props>): JSX.Element {
|
|||
title={langui.wiki}
|
||||
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 />
|
||||
</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(
|
||||
context: GetStaticPropsContext
|
||||
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||
const sdk = getReadySdk();
|
||||
const pages = await sdk.getWikiPagesPreviews({});
|
||||
if (!pages.wikiPages?.data) return { notFound: true };
|
||||
const props: Props = {
|
||||
...(await getAppStaticProps(context)),
|
||||
pages: pages.wikiPages.data,
|
||||
};
|
||||
return {
|
||||
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