From d1d055de2931ad5504ccd95966cd99ef3258aa1c Mon Sep 17 00:00:00 2001
From: DrMint
Date: Mon, 11 Jul 2022 02:35:09 +0200
Subject: [PATCH] Improved the wiki section
---
src/components/Inputs/Select.tsx | 17 +-
src/components/Wiki/DefinitionCard.tsx | 18 +-
src/graphql/fragments/source.graphql | 24 +++
src/graphql/operations/getWikiPage.graphql | 20 +-
.../operations/getWikiPagesPreviews.graphql | 20 +-
src/pages/wiki/[slug]/index.tsx | 87 +++++++--
src/pages/wiki/index.tsx | 183 +++++++++++-------
7 files changed, 278 insertions(+), 91 deletions(-)
create mode 100644 src/graphql/fragments/source.graphql
diff --git a/src/components/Inputs/Select.tsx b/src/components/Inputs/Select.tsx
index 0eed39f..abf3f73 100644
--- a/src/components/Inputs/Select.tsx
+++ b/src/components/Inputs/Select.tsx
@@ -1,4 +1,10 @@
-import { Dispatch, Fragment, SetStateAction, useState } from "react";
+import {
+ Dispatch,
+ Fragment,
+ SetStateAction,
+ useCallback,
+ useState,
+} from "react";
import { Ico, Icon } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
import { useToggle } from "hooks/useToggle";
@@ -29,6 +35,11 @@ export const Select = ({
const [opened, setOpened] = useState(false);
const toggleOpened = useToggle(setOpened);
+ const tryToggling = useCallback(() => {
+ const optionCount = options.length + (state === -1 ? 1 : 0);
+ if (optionCount > 1) toggleOpened();
+ }, [options.length, state, toggleOpened]);
+
return (
-
+
{state === -1 ? "—" : options[state]}
{state >= 0 && allowEmpty && (
@@ -59,7 +70,7 @@ export const Select = ({
/>
)}
diff --git a/src/components/Wiki/DefinitionCard.tsx b/src/components/Wiki/DefinitionCard.tsx
index 75151d7..447278a 100644
--- a/src/components/Wiki/DefinitionCard.tsx
+++ b/src/components/Wiki/DefinitionCard.tsx
@@ -4,6 +4,8 @@ import { ToolTip } from "components/ToolTip";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { getStatusDescription } from "helpers/others";
import { useSmartLanguage } from "hooks/useSmartLanguage";
+import Link from "next/link";
+import { Button } from "components/Inputs/Button";
/*
* ╭─────────────╮
@@ -11,7 +13,10 @@ import { useSmartLanguage } from "hooks/useSmartLanguage";
*/
interface Props {
- source?: string;
+ source?: {
+ name?: string;
+ url?: string;
+ };
translations: {
language: string | undefined;
definition: string | null | undefined;
@@ -79,9 +84,16 @@ const DefinitionCard = ({
)}
- {`${langui.source}: ${source}`}
-
{selectedTranslation?.definition}
+
+ {source?.url && source.name && (
+
+
+
+ )}
>
);
};
diff --git a/src/graphql/fragments/source.graphql b/src/graphql/fragments/source.graphql
new file mode 100644
index 0000000..9316d6e
--- /dev/null
+++ b/src/graphql/fragments/source.graphql
@@ -0,0 +1,24 @@
+fragment source on Source {
+ name
+ content {
+ data {
+ attributes {
+ slug
+ }
+ }
+ }
+ ranged_content {
+ data {
+ attributes {
+ slug
+ library_item {
+ data {
+ attributes {
+ slug
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/graphql/operations/getWikiPage.graphql b/src/graphql/operations/getWikiPage.graphql
index cc3a8e1..b22db19 100644
--- a/src/graphql/operations/getWikiPage.graphql
+++ b/src/graphql/operations/getWikiPage.graphql
@@ -20,6 +20,24 @@ query getWikiPage($slug: String, $language_code: String) {
}
}
}
+ tags {
+ data {
+ id
+ attributes {
+ slug
+ titles(filters: { language: { code: { eq: $language_code } } }) {
+ language {
+ data {
+ attributes {
+ code
+ }
+ }
+ }
+ title
+ }
+ }
+ }
+ }
translations {
title
aliases {
@@ -73,7 +91,7 @@ query getWikiPage($slug: String, $language_code: String) {
source {
data {
attributes {
- name
+ ...source
}
}
}
diff --git a/src/graphql/operations/getWikiPagesPreviews.graphql b/src/graphql/operations/getWikiPagesPreviews.graphql
index 3fc402c..9925e99 100644
--- a/src/graphql/operations/getWikiPagesPreviews.graphql
+++ b/src/graphql/operations/getWikiPagesPreviews.graphql
@@ -1,4 +1,4 @@
-query getWikiPagesPreviews {
+query getWikiPagesPreviews($language_code: String) {
wikiPages(pagination: { limit: -1 }) {
data {
id
@@ -20,6 +20,24 @@ query getWikiPagesPreviews {
}
}
}
+ tags {
+ data {
+ id
+ attributes {
+ slug
+ titles(filters: { language: { code: { eq: $language_code } } }) {
+ language {
+ data {
+ attributes {
+ code
+ }
+ }
+ }
+ title
+ }
+ }
+ }
+ }
translations {
title
aliases {
diff --git a/src/pages/wiki/[slug]/index.tsx b/src/pages/wiki/[slug]/index.tsx
index 8854ade..d15223f 100644
--- a/src/pages/wiki/[slug]/index.tsx
+++ b/src/pages/wiki/[slug]/index.tsx
@@ -23,6 +23,9 @@ import {
} from "helpers/others";
import { WikiPageWithTranslations } from "helpers/types";
import { useSmartLanguage } from "hooks/useSmartLanguage";
+import { prettySlug } from "helpers/formatters";
+import { useLightBox } from "hooks/useLightBox";
+import { getAssetURL, ImageQuality } from "helpers/img";
interface Props extends AppStaticProps {
page: WikiPageWithTranslations;
@@ -45,6 +48,8 @@ const WikiPage = ({
),
});
+ const [openLightBox, LightBox] = useLightBox();
+
const subPanel = useMemo(
() => (
@@ -63,6 +68,8 @@ const WikiPage = ({
const contentPanel = useMemo(
() => (
+
+
{`(${selectedTranslation.aliases
.map((alias) => alias?.alias)
- .join(", ")})`}
+ .join("・")})`}
)}
@@ -93,19 +100,63 @@ const WikiPage = ({
text-center"
>
{page.thumbnail?.data?.attributes && (
-
+
{
+ if (page.thumbnail?.data?.attributes?.url) {
+ openLightBox([
+ getAssetURL(
+ page.thumbnail.data.attributes.url,
+ ImageQuality.Large
+ ),
+ ]);
+ }
+ }}
+ />
)}
-
- {langui.categories}
-
-
- {filterHasAttributes(page.categories?.data, [
- "attributes",
- ] as const).map((category) => (
-
- ))}
-
+ {page.categories?.data && page.categories.data.length > 0 && (
+ <>
+
+ {langui.categories}
+
+
+
+ {filterHasAttributes(page.categories.data, [
+ "attributes",
+ ] as const).map((category) => (
+
+ ))}
+
+ >
+ )}
+
+ {page.tags?.data && page.tags.data.length > 0 && (
+ <>
+
+ {/* TODO: Add Tags to langui */}
+ {"Tags"}
+
+
+ {filterHasAttributes(page.tags?.data, [
+ "attributes",
+ ] as const).map((tag) => (
+
+ ))}
+
+ >
+ )}
@@ -124,7 +175,13 @@ const WikiPage = ({
<>
({
language: translation?.language?.data?.attributes?.code,
definition: translation?.definition,
@@ -149,9 +206,7 @@ const WikiPage = ({
languageSwitcherProps,
languages,
langui,
- page.categories?.data,
- page.definitions,
- page.thumbnail?.data?.attributes,
+ page,
selectedTranslation,
]
);
diff --git a/src/pages/wiki/index.tsx b/src/pages/wiki/index.tsx
index 0f8d75a..c4d0a17 100644
--- a/src/pages/wiki/index.tsx
+++ b/src/pages/wiki/index.tsx
@@ -1,5 +1,5 @@
import { GetStaticProps } from "next";
-import { Fragment, useMemo, useState } from "react";
+import { useCallback, useMemo, useState } from "react";
import { AppLayout } from "components/AppLayout";
import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
@@ -7,7 +7,7 @@ import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico";
import { getReadySdk } from "graphql/sdk";
-import { GetWikiPagesPreviewsQuery } from "graphql/generated";
+import { GetWikiPageQuery, GetWikiPagesPreviewsQuery } from "graphql/generated";
import {
ContentPanel,
ContentPanelWidthSizes,
@@ -19,8 +19,12 @@ import { Switch } from "components/Inputs/Switch";
import { TextInput } from "components/Inputs/TextInput";
import { WithLabel } from "components/Inputs/WithLabel";
import { useMediaHoverable } from "hooks/useMediaQuery";
-import { filterHasAttributes } from "helpers/others";
+import { filterDefined, filterHasAttributes, isDefined } from "helpers/others";
import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholder";
+import { SmartList } from "components/SmartList";
+import { Select } from "components/Inputs/Select";
+import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
+import { prettySlug } from "helpers/formatters";
/*
* ╭─────────────╮
@@ -30,6 +34,7 @@ import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholde
const DEFAULT_FILTERS_STATE = {
searchName: "",
keepInfoVisible: true,
+ groupingMethod: -1,
};
/*
@@ -52,13 +57,13 @@ const Wiki = ({
const [searchName, setSearchName] = useState(
DEFAULT_FILTERS_STATE.searchName
);
- const [keepInfoVisible, setKeepInfoVisible] = useState(
- DEFAULT_FILTERS_STATE.keepInfoVisible
+
+ const [groupingMethod, setGroupingMethod] = useState(
+ DEFAULT_FILTERS_STATE.groupingMethod
);
- const filteredPages = useMemo(
- () => filterPages(pages, searchName),
- [pages, searchName]
+ const [keepInfoVisible, setKeepInfoVisible] = useState(
+ DEFAULT_FILTERS_STATE.keepInfoVisible
);
const subPanel = useMemo(
@@ -77,6 +82,19 @@ const Wiki = ({
setState={setSearchName}
/>
+
+ }
+ />
+
{hoverable && (
),
- [hoverable, keepInfoVisible, langui, searchName]
+ [groupingMethod, hoverable, keepInfoVisible, langui, searchName]
+ );
+
+ const groupingFunction = useCallback(
+ (
+ item: SelectiveNonNullable<
+ NonNullable["data"][number],
+ "attributes" | "id"
+ >
+ ): string[] => {
+ switch (groupingMethod) {
+ case 0: {
+ const categories = filterHasAttributes(
+ item.attributes.categories?.data,
+ ["attributes"] as const
+ );
+ if (categories.length > 0) {
+ return categories.map((category) => category.attributes.name);
+ }
+ return [langui.no_category ?? "No category"];
+ }
+ default: {
+ return [""];
+ }
+ }
+ },
+ [groupingMethod, langui]
);
const contentPanel = useMemo(
() => (
-
- {filteredPages.length === 0 && (
+ item.id}
+ renderItem={({ item }) => (
+ <>
+ {isDefined(item.attributes.translations) && (
+ ({
+ title: translation?.title,
+ subtitle:
+ translation?.aliases && translation.aliases.length > 0
+ ? translation.aliases
+ .map((alias) => alias?.alias)
+ .join("・")
+ : undefined,
+ description: translation?.summary,
+ language: translation?.language?.data?.attributes?.code,
+ })
+ )}
+ thumbnail={item.attributes.thumbnail?.data?.attributes}
+ thumbnailAspectRatio={"4/3"}
+ thumbnailRounded
+ thumbnailForceAspectRatio
+ languages={languages}
+ slug={item.attributes.slug}
+ keepInfoVisible={keepInfoVisible}
+ topChips={filterHasAttributes(item.attributes.tags?.data, [
+ "attributes",
+ ] as const).map(
+ (tag) =>
+ tag.attributes.titles?.[0]?.title ??
+ prettySlug(tag.attributes.slug)
+ )}
+ bottomChips={filterHasAttributes(
+ item.attributes.categories?.data,
+ ["attributes"] as const
+ ).map((category) => category.attributes.short)}
+ />
+ )}
+ >
+ )}
+ renderWhenEmpty={() => (
)}
- {filterHasAttributes(filteredPages, [
- "id",
- "attributes.translations",
- ] as const).map((page) => (
-
- ({
- title: translation?.title,
- subtitle:
- translation?.aliases && translation.aliases.length > 0
- ? translation.aliases
- .map((alias) => alias?.alias)
- .join(" | ")
- : undefined,
- 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 ?? ""
- )}
- />
-
- ))}
-
+ langui={langui}
+ className="grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))]"
+ searchingTerm={searchName}
+ searchingBy={(item) =>
+ filterDefined(item.attributes.translations)
+ .map(
+ (translation) =>
+ `${translation.title} ${filterDefined(translation.aliases)
+ .map((alias) => alias.alias)
+ .join(" ")}`
+ )
+ .join(" ")
+ }
+ groupingFunction={groupingFunction}
+ />
),
- [filteredPages, keepInfoVisible, languages, langui]
+ [groupingFunction, keepInfoVisible, languages, langui, pages, searchName]
);
return (
@@ -180,7 +244,9 @@ export default Wiki;
export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk();
- const pages = await sdk.getWikiPagesPreviews({});
+ const pages = await sdk.getWikiPagesPreviews({
+ language_code: context.locale ?? "en",
+ });
if (!pages.wikiPages?.data) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
@@ -202,20 +268,3 @@ const sortPages = (pages: Props["pages"]): Props["pages"] =>
const slugB = b.attributes?.slug ?? "";
return slugA.localeCompare(slugB);
});
-
-// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
-
-const filterPages = (posts: Props["pages"], searchName: string) =>
- posts.filter((post) => {
- if (searchName.length > 1) {
- if (
- post.attributes?.translations?.[0]?.title
- .toLowerCase()
- .includes(searchName.toLowerCase()) === true
- ) {
- return true;
- }
- return false;
- }
- return true;
- });