From e8237dcc62697b5a46a6f3255ca93b00bb69b589 Mon Sep 17 00:00:00 2001 From: Allan Lasser Date: Thu, 11 Apr 2024 19:18:01 -0400 Subject: [PATCH 01/11] Adds breadcrumbs to global navigation Debug Debug Debug Fix breadcrumb trail Breadcrumbs Cleanup breadcrumb generation with a util fn Update document breadcrumb href Reorganize breadcrumbs --- src/lib/components/MainLayout.svelte | 26 ++------ .../components/accounts/Breadcrumbs.svelte | 65 +++++++++++++++++++ .../stories/Breadcrumbs.stories.svelte | 64 ++++++++++++++++++ src/lib/utils/index.ts | 1 + src/lib/utils/navigation.ts | 13 ++++ src/lib/utils/tests/navigation.test.ts | 23 +++++++ src/routes/+layout.svelte | 1 + src/routes/+layout.ts | 2 +- src/routes/app/+layout.svelte | 6 +- src/routes/app/+layout.ts | 10 ++- src/routes/app/sidebar/AddOns.svelte | 1 - src/routes/documents/[id]-[slug]/+layout.ts | 21 +++++- 12 files changed, 200 insertions(+), 33 deletions(-) create mode 100644 src/lib/components/accounts/Breadcrumbs.svelte create mode 100644 src/lib/components/accounts/stories/Breadcrumbs.stories.svelte create mode 100644 src/lib/utils/navigation.ts create mode 100644 src/lib/utils/tests/navigation.test.ts diff --git a/src/lib/components/MainLayout.svelte b/src/lib/components/MainLayout.svelte index 1d2716f27..9e8103e7f 100644 --- a/src/lib/components/MainLayout.svelte +++ b/src/lib/components/MainLayout.svelte @@ -1,21 +1,22 @@ + + + + + + diff --git a/src/lib/components/accounts/stories/Breadcrumbs.stories.svelte b/src/lib/components/accounts/stories/Breadcrumbs.stories.svelte new file mode 100644 index 000000000..285cbb7ca --- /dev/null +++ b/src/lib/components/accounts/stories/Breadcrumbs.stories.svelte @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + +

DocumentCloud

+
+
diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index af9443a45..9e936e597 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1 +1,2 @@ export { isErrorCode, isRedirectCode } from "./api"; +export { breadcrumbTrail } from "./navigation"; diff --git a/src/lib/utils/navigation.ts b/src/lib/utils/navigation.ts new file mode 100644 index 000000000..87c37ad8c --- /dev/null +++ b/src/lib/utils/navigation.ts @@ -0,0 +1,13 @@ +type Breadcrumb = { href?: string; title: string }; +type Parent = () => Promise<{ breadcrumbs?: Array }>; + +/** Returns a trail of breadcrumbs, built upon the parent's trail. + * Primarily for use in `+layout.ts` and `+page.ts` files. + */ +export async function breadcrumbTrail( + parent: Parent, + crumbs: Array = [], +) { + const { breadcrumbs: trail = [] } = await parent(); + return trail.concat(crumbs); +} diff --git a/src/lib/utils/tests/navigation.test.ts b/src/lib/utils/tests/navigation.test.ts new file mode 100644 index 000000000..5bf0d6a29 --- /dev/null +++ b/src/lib/utils/tests/navigation.test.ts @@ -0,0 +1,23 @@ +import { vi, describe, it, expect, beforeEach, afterEach } from "vitest"; +import { breadcrumbTrail } from "../navigation"; + +describe("breadcrumbTrail", () => { + it("returns an empty array as a base case", async () => { + const parent = vi.fn().mockResolvedValue({}); + expect(await breadcrumbTrail(parent)).toEqual([]); + }); + it("returns the parent's breadcrumb trail, if it exists", async () => { + const parentTrail = [{ href: "/first", title: "First Level" }]; + const parent = vi.fn().mockResolvedValue({ breadcrumbs: parentTrail }); + expect(await breadcrumbTrail(parent)).toEqual(parentTrail); + }); + it("concats the provided trail onto the parent's trail", async () => { + const parentTrail = [{ href: "/first", title: "First Level" }]; + const childTrail = [{ href: "/second", title: "Second Level" }]; + const parent = vi.fn().mockResolvedValue({ breadcrumbs: parentTrail }); + expect(await breadcrumbTrail(parent, childTrail)).toEqual([ + ...parentTrail, + ...childTrail, + ]); + }); +}); diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 02758e22c..2a9d01ad0 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,6 +1,7 @@ diff --git a/src/routes/app/+layout.ts b/src/routes/app/+layout.ts index 9ff57d834..1faa34a41 100644 --- a/src/routes/app/+layout.ts +++ b/src/routes/app/+layout.ts @@ -1,14 +1,18 @@ -import { getPinnedAddons } from "@/lib/api/addons"; import * as projects from "$lib/api/projects"; +import { getPinnedAddons } from "$lib/api/addons"; +import { breadcrumbTrail } from "$lib/utils/navigation"; -export async function load({ url, fetch }) { +export async function load({ url, fetch, parent }) { const pinnedAddons = getPinnedAddons(fetch); const pinnedProjects = projects .list({ pinned: true }, fetch) .then((r) => r.results); - + const breadcrumbs = await breadcrumbTrail(parent, [ + { href: "/app", title: "Documents" }, // TODO: move document manager to `/documents` route + ]); return { pinnedAddons, pinnedProjects, + breadcrumbs, }; } diff --git a/src/routes/app/sidebar/AddOns.svelte b/src/routes/app/sidebar/AddOns.svelte index 138ec47d5..778d6fabd 100644 --- a/src/routes/app/sidebar/AddOns.svelte +++ b/src/routes/app/sidebar/AddOns.svelte @@ -3,7 +3,6 @@ import type { AddOnListItem } from "@/addons/types"; import { Book16, Hourglass24, Pin24, Plug16 } from "svelte-octicons"; - import Action from "$lib/components/common/Action.svelte"; import Empty from "$lib/components/common/Empty.svelte"; import Flex from "$lib/components/common/Flex.svelte"; diff --git a/src/routes/documents/[id]-[slug]/+layout.ts b/src/routes/documents/[id]-[slug]/+layout.ts index f404e07fb..ab90aede8 100644 --- a/src/routes/documents/[id]-[slug]/+layout.ts +++ b/src/routes/documents/[id]-[slug]/+layout.ts @@ -6,10 +6,16 @@ import { redirect } from "@sveltejs/kit"; import * as documents from "@/lib/api/documents"; -import { getPinnedAddons } from "$lib/api/addons.js"; +import type { Document } from "@/lib/api/types"; +import { getPinnedAddons } from "$lib/api/addons"; +import { breadcrumbTrail } from "$lib/utils/navigation"; + +function documentPath(document: Document) { + return `/documents/${document.id}-${document.slug}`; +} /** @type {import('./$types').PageLoad} */ -export async function load({ fetch, params }) { +export async function load({ fetch, params, parent }) { const document = await documents.get(+params.id, fetch); if (document.slug !== params.slug) { @@ -17,8 +23,17 @@ export async function load({ fetch, params }) { redirect(302, canonical.pathname); } + const breadcrumbs = await breadcrumbTrail(parent, [ + { href: "/app", title: "Documents" }, // TODO: move document manager to `/documents` route + { href: documentPath(document), title: document.title }, + ]); + // stream this const pinnedAddons = getPinnedAddons(fetch); - return { document, pinnedAddons }; + return { + document, + pinnedAddons, + breadcrumbs, + }; } From 9d7dad5694befcb1e467b1d06b8391b19b56cc36 Mon Sep 17 00:00:00 2001 From: Allan Lasser Date: Fri, 12 Apr 2024 10:58:29 -0400 Subject: [PATCH 02/11] Re-org nav components --- src/lib/components/MainLayout.svelte | 4 ++-- .../components/{accounts => navigation}/Breadcrumbs.svelte | 0 src/lib/components/{accounts => navigation}/OrgMenu.svelte | 0 src/lib/components/{accounts => navigation}/UserMenu.svelte | 0 .../stories/Breadcrumbs.stories.svelte | 0 .../{accounts => navigation}/stories/OrgMenu.stories.svelte | 0 6 files changed, 2 insertions(+), 2 deletions(-) rename src/lib/components/{accounts => navigation}/Breadcrumbs.svelte (100%) rename src/lib/components/{accounts => navigation}/OrgMenu.svelte (100%) rename src/lib/components/{accounts => navigation}/UserMenu.svelte (100%) rename src/lib/components/{accounts => navigation}/stories/Breadcrumbs.stories.svelte (100%) rename src/lib/components/{accounts => navigation}/stories/OrgMenu.stories.svelte (100%) diff --git a/src/lib/components/MainLayout.svelte b/src/lib/components/MainLayout.svelte index 9e8103e7f..3721fdf71 100644 --- a/src/lib/components/MainLayout.svelte +++ b/src/lib/components/MainLayout.svelte @@ -9,8 +9,8 @@ import Button from "./common/Button.svelte"; import Flex from "./common/Flex.svelte"; import SignedIn from "./common/SignedIn.svelte"; - import UserMenu from "./accounts/UserMenu.svelte"; - import OrgMenu from "./accounts/OrgMenu.svelte"; + import UserMenu from "./navigation/UserMenu.svelte"; + import OrgMenu from "./navigation/OrgMenu.svelte"; import { SIGN_IN_URL } from "@/config/config"; import Breadcrumbs from "./navigation/Breadcrumbs.svelte"; diff --git a/src/lib/components/accounts/Breadcrumbs.svelte b/src/lib/components/navigation/Breadcrumbs.svelte similarity index 100% rename from src/lib/components/accounts/Breadcrumbs.svelte rename to src/lib/components/navigation/Breadcrumbs.svelte diff --git a/src/lib/components/accounts/OrgMenu.svelte b/src/lib/components/navigation/OrgMenu.svelte similarity index 100% rename from src/lib/components/accounts/OrgMenu.svelte rename to src/lib/components/navigation/OrgMenu.svelte diff --git a/src/lib/components/accounts/UserMenu.svelte b/src/lib/components/navigation/UserMenu.svelte similarity index 100% rename from src/lib/components/accounts/UserMenu.svelte rename to src/lib/components/navigation/UserMenu.svelte diff --git a/src/lib/components/accounts/stories/Breadcrumbs.stories.svelte b/src/lib/components/navigation/stories/Breadcrumbs.stories.svelte similarity index 100% rename from src/lib/components/accounts/stories/Breadcrumbs.stories.svelte rename to src/lib/components/navigation/stories/Breadcrumbs.stories.svelte diff --git a/src/lib/components/accounts/stories/OrgMenu.stories.svelte b/src/lib/components/navigation/stories/OrgMenu.stories.svelte similarity index 100% rename from src/lib/components/accounts/stories/OrgMenu.stories.svelte rename to src/lib/components/navigation/stories/OrgMenu.stories.svelte From b111ed6ecf840d35baac0eb0059711b690ea11bd Mon Sep 17 00:00:00 2001 From: Allan Lasser Date: Fri, 12 Apr 2024 14:05:04 -0400 Subject: [PATCH 03/11] Adds LanguageMenu --- .storybook/preview.ts | 6 +- src/lib/components/MainLayout.svelte | 1 + .../components/navigation/LanguageMenu.svelte | 60 +++++++++++++++++++ .../stories/LanguageMenu.stories.svelte | 17 ++++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 src/lib/components/navigation/LanguageMenu.svelte create mode 100644 src/lib/components/navigation/stories/LanguageMenu.stories.svelte diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 6802bc389..90518e863 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -5,7 +5,7 @@ import UserContextDecorator from "./decorators/UserContextDecorator.svelte"; import OrgContextDecorator from "./decorators/OrgContextDecorator.svelte"; import "@/style/kit.css"; -import "../src/lib/i18n/index.js"; +import "@/lib/i18n/index.js"; // Initialize MSW initialize({ @@ -29,7 +29,9 @@ const preview: Preview = { stores: { page: { url: "/", - data: {}, + data: { + breadcrumbs: [], + }, }, }, }, diff --git a/src/lib/components/MainLayout.svelte b/src/lib/components/MainLayout.svelte index 3721fdf71..1db75da98 100644 --- a/src/lib/components/MainLayout.svelte +++ b/src/lib/components/MainLayout.svelte @@ -59,6 +59,7 @@ Sign In + {#if $$slots.action}
+ {#if $$slots.action}