From 0a4a0477ff6c571128dad95a96d80a6b259b7ae0 Mon Sep 17 00:00:00 2001 From: Daniel O'Connell Date: Fri, 15 Mar 2024 19:58:09 +0100 Subject: [PATCH] Handle articles in multiple sections --- app/components/Article/KeepGoing/index.tsx | 12 +++++++--- app/components/ArticlesDropdown/index.tsx | 21 +++++++++++++--- app/components/ArticlesNav/Menu.tsx | 8 ++++++- app/hooks/useToC.tsx | 28 ++++++++++++++++++---- app/routes/questions.$questionId.$.tsx | 5 ++-- 5 files changed, 60 insertions(+), 14 deletions(-) diff --git a/app/components/Article/KeepGoing/index.tsx b/app/components/Article/KeepGoing/index.tsx index 8a431d47..b08e2016 100644 --- a/app/components/Article/KeepGoing/index.tsx +++ b/app/components/Article/KeepGoing/index.tsx @@ -1,3 +1,4 @@ +import {useLocation} from 'react-router-dom' import Button from '~/components/Button' import ListTable from '~/components/Table' import {ArrowRight} from '~/components/icons-generated' @@ -24,7 +25,11 @@ const NextArticle = ({section, next, first}: NextArticleProps) =>
{next.title}
- @@ -33,9 +38,10 @@ const NextArticle = ({section, next, first}: NextArticleProps) => ) export const KeepGoing = ({pageid, relatedQuestions}: Question) => { + const location = useLocation() const {findSection, getArticle, getNext} = useToC() - const section = findSection(pageid) - const next = getNext(pageid) + const section = findSection(location?.state?.section || pageid) + const next = getNext(pageid, section?.pageid) const hasRelated = relatedQuestions && relatedQuestions.length > 0 const skipNext = nonContinueSections.includes(section?.pageid || '') diff --git a/app/components/ArticlesDropdown/index.tsx b/app/components/ArticlesDropdown/index.tsx index 652cf5d9..f99f9650 100644 --- a/app/components/ArticlesDropdown/index.tsx +++ b/app/components/ArticlesDropdown/index.tsx @@ -22,9 +22,19 @@ export const ArticlesDropdown = ({toc, categories}: ArticlesDropdownProps) => { const hide = () => setShown(true) useEffect(() => setShown(false), [shown]) const mobile = useIsMobile() - const Link = ({to, text, className}: {to: string; text: string; className?: string}) => ( + const Link = ({ + to, + text, + pageid, + className, + }: { + to: string + text: string + pageid?: string + className?: string + }) => (
- + {text}
@@ -44,7 +54,12 @@ export const ArticlesDropdown = ({toc, categories}: ArticlesDropdownProps) => { {toc .filter((item) => item.category === category) .map((item: TOCItem) => ( - + ))}
) diff --git a/app/components/ArticlesNav/Menu.tsx b/app/components/ArticlesNav/Menu.tsx index 2657063a..35d143c8 100644 --- a/app/components/ArticlesNav/Menu.tsx +++ b/app/components/ArticlesNav/Menu.tsx @@ -31,7 +31,13 @@ const Title = ({article, path, current}: Article) => { return ( - {!article.hasText ? article.title : {article.title}} + {!article.hasText ? ( + article.title + ) : ( + + {article.title} + + )} {!isHeader && } ) diff --git a/app/hooks/useToC.tsx b/app/hooks/useToC.tsx index 0f73bfbe..5db75854 100644 --- a/app/hooks/useToC.tsx +++ b/app/hooks/useToC.tsx @@ -22,15 +22,29 @@ const useToC = () => { } const findSection = (pageid: string): TOCItem | undefined => { - return (toc || []).filter(checkPath(pageid))[0] + const checker = checkPath(pageid) + // Articles can be in multiple sections, or even be sections. It's assumed here that + // the highest level usage should be used, so assuming article "ABC", with the following + // paths: + // * ["123", "432", "ABC"] + // * ["123", "ABC"] + // * ["324", "ABC"] + // * ["ABC"] + // Then that the shorter the path, the better + return (toc || []) + .filter(checker) + .sort((a, b) => (checker(a)?.length || 20) - (checker(b)?.length || 20))[0] } - const getPath = (pageid: string) => { + const getPath = (pageid: string, sectionId?: string) => { if (!toc || toc.length === 0) return undefined - return toc.map(checkPath(pageid)).filter(identity)[0] + const paths = toc.map(checkPath(pageid)).filter(identity) + + if (sectionId) return paths.filter((p) => p && p[0] === sectionId)[0] + return paths[0] } - const getNext = (pageid: string): TOCItem | undefined => { + const getNext = (pageid: string, sectionId?: string): TOCItem | undefined => { type NextItem = { current?: string next?: TOCItem @@ -47,7 +61,11 @@ const useToC = () => { return {current: previous} } - return toc?.map((section) => findNext('', section).next).filter(identity)[0] + // Assume that next articles must always be in the same section + return toc + ?.filter(({pageid}) => pageid === sectionId) + .map((section) => findNext('', section).next) + .filter(identity)[0] } return { diff --git a/app/routes/questions.$questionId.$.tsx b/app/routes/questions.$questionId.$.tsx index 9c5b953f..6b8fe542 100644 --- a/app/routes/questions.$questionId.$.tsx +++ b/app/routes/questions.$questionId.$.tsx @@ -82,7 +82,7 @@ export default function RenderArticle() { const pageid = params.questionId ?? '😱' const {data, tags} = useLoaderData() const {findSection, getArticle, getPath} = useToC() - const section = findSection(pageid) + const section = findSection(location?.state?.section || pageid) useEffect(() => { const getGlossary = async () => { @@ -119,11 +119,12 @@ export default function RenderArticle() { )} + {section && ( )}