From c62adb475279a5a7a8f3b3be62648460f6b59edf Mon Sep 17 00:00:00 2001 From: PrzZiomek2 Date: Thu, 2 Apr 2026 17:13:31 +0200 Subject: [PATCH] allow custom breadcrumbs label Summary: Ref T3092 Reviewers: kuba-orlik Reviewed By: kuba-orlik Maniphest Tasks: T3092 Differential Revision: https://hub.sealcode.org/D1681 --- src/back/routes/common/breadcrumbs.tsx | 48 +++++++++++++------------- src/back/routes/hello-page.page.tsx | 3 ++ src/back/routes/url-tree.ts | 33 +++++++++++++++--- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/back/routes/common/breadcrumbs.tsx b/src/back/routes/common/breadcrumbs.tsx index a41e954..f0a9c84 100644 --- a/src/back/routes/common/breadcrumbs.tsx +++ b/src/back/routes/common/breadcrumbs.tsx @@ -43,29 +43,29 @@ function arrow_head() { ); } -export function breadcrumbs(ctx: Context) { - return ( - +export async function breadcrumbs(ctx: Context) { + const breadcrumbs = await Promise.all( + get_breadcrumbs_from_path(ctx.path).map(async (e, i, all) => { + if (!e.actionName) { + return ""; + } + + const breadcrumbLabel = e.breadcrumbLabel?.({ ...ctx }); + const breadcrumbLabelResult = await breadcrumbLabel; + + if (i == all.length - 1) { + return {breadcrumbLabelResult || e.actionName}; + } + return ( + <> + + {i !== 0 ? arrow_tail() : ""} + {breadcrumbLabelResult || e.actionName} + {arrow_head()} + + + ); + }) ); + return ; } diff --git a/src/back/routes/hello-page.page.tsx b/src/back/routes/hello-page.page.tsx index 34bf7f7..244a612 100644 --- a/src/back/routes/hello-page.page.tsx +++ b/src/back/routes/hello-page.page.tsx @@ -2,9 +2,12 @@ import type { Context } from "koa"; import { TempstreamJSX } from "tempstream"; import { Page } from "@sealcode/sealgen"; +import type { BreadcrumbLabel } from "@sealcode/sealgen"; + import html from "src/back/html.js"; export const actionName = "HelloPage"; +export const breadcrumbLabel: BreadcrumbLabel = "Witaj"; export default new (class HelloPagePage extends Page { // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/back/routes/url-tree.ts b/src/back/routes/url-tree.ts index 864bf82..9b5f92c 100644 --- a/src/back/routes/url-tree.ts +++ b/src/back/routes/url-tree.ts @@ -1,12 +1,17 @@ +import * as path from "path"; +import type { Context } from "koa"; import { url_tree } from "./routes.js"; import type { URLTree } from "./routes.js"; +import type { BreadcrumbLabel } from "@sealcode/sealgen"; export function get_breadcrumbs_from_path(url: string) { let position: URLTree = url_tree; const elements = url.split("/").filter((e) => e != ""); - const breadcrumbs: { actionName?: string; url?: string }[] = [ - { actionName: "Home", url: "/" }, - ]; + const breadcrumbs: { + actionName?: string; + url?: string; + breadcrumbLabel?: (ctx: Context) => Promise; + }[] = [{ actionName: "Home", url: "/" }]; let path_so_far = ""; for (const element of elements) { if (position.children[element]) { @@ -18,7 +23,27 @@ export function get_breadcrumbs_from_path(url: string) { break; } path_so_far += "/" + element; - breadcrumbs.push({ actionName: position.actionName, url: path_so_far }); + const actionName = position.actionName; + const modulePath = position.module_path; + + breadcrumbs.push({ + actionName: actionName, + url: path_so_far, + breadcrumbLabel: async (ctx: Context) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions + const module = (await import(path.resolve(modulePath || "") || "")) as { + breadcrumbLabel: BreadcrumbLabel; + }; + + if (!module.breadcrumbLabel) return actionName || ""; + + if (typeof module.breadcrumbLabel === "function") { + return module.breadcrumbLabel(ctx); + } else { + return module.breadcrumbLabel; + } + }, + }); } return breadcrumbs; }