Skip to content

Commit

Permalink
frontend: Generate breadcrumbs inside workflow layout (#3149)
Browse files Browse the repository at this point in the history
  • Loading branch information
septum authored Oct 21, 2024
1 parent 45a288d commit f24f53d
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 6 deletions.
5 changes: 2 additions & 3 deletions frontend/packages/core/src/AppProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,9 @@ const ClutchApp = ({

// We define these props in order to avoid UI changes before refactoring
const workflowLayoutProps: LayoutProps = {
variant: "custom",
hideHeader: true,
heading,
...route.layoutProps,
heading: route.layoutProps?.heading || heading,
workflow,
};

const workflowRouteComponent = (
Expand Down
24 changes: 21 additions & 3 deletions frontend/packages/core/src/WorkflowLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import React from "react";
import { matchPath } from "react-router";
import type { Interpolation } from "@emotion/styled";
import type { CSSObject, Theme } from "@mui/material";

import type { Workflow } from "../AppProvider/workflow";
import Breadcrumbs from "../Breadcrumbs";
import { useLocation } from "../navigation";
import styled from "../styled";
import { Typography } from "../typography";
import { generateBreadcrumbsEntries } from "../utils";

export type LayoutVariant = "standard" | "wizard" | "custom";

export type LayoutProps = {
variant: LayoutVariant;
workflow: Workflow;
variant?: LayoutVariant;
heading?: string | React.ReactElement;
hideHeader?: boolean;
};
Expand Down Expand Up @@ -61,15 +67,27 @@ const HeaderTitle = styled(Typography)({
});

const WorkflowLayout = ({
variant,
heading,
workflow,
variant = "standard",
heading = null,
hideHeader = false,
children,
}: React.PropsWithChildren<LayoutProps>) => {
const location = useLocation();
const workflowPaths = workflow.routes.map(({ path }) => `/${workflow.path}/${path}`);
const breadcrumbsEntries = generateBreadcrumbsEntries(
location,
(url: string) =>
`/${workflow.path}` !== url &&
!workflowPaths.includes(url) &&
!workflowPaths.find(path => !!matchPath({ path }, url))
);

return (
<LayoutContainer $variant={variant}>
{!hideHeader && (
<PageHeader $variant={variant}>
<Breadcrumbs entries={breadcrumbsEntries} />
{heading && (
<>
{React.isValidElement(heading) ? (
Expand Down
28 changes: 28 additions & 0 deletions frontend/packages/core/src/utils/generateBreadcrumbsEntries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { Location } from "history";

import type { BreadcrumbEntry } from "../Breadcrumbs";

const generateBreadcrumbsEntries = (location: Location, validateUrl: (url: string) => boolean) => {
const labels = location.pathname
.split("/")
.slice(1, location.pathname.endsWith("/") ? -1 : undefined);

const entries: Array<BreadcrumbEntry> = [{ label: "Home", url: "/" }].concat(
labels.map((label, index) => {
let url = `/${labels.slice(0, index + 1).join("/")}`;

if (validateUrl(url)) {
url = undefined;
}

return {
label,
url,
};
})
);

return entries;
};

export default generateBreadcrumbsEntries;
1 change: 1 addition & 0 deletions frontend/packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as getDisplayName } from "./getDisplayName";
export { default as findPathMatchList } from "./pathMatching";
export { default as generateBreadcrumbsEntries } from "./generateBreadcrumbsEntries";

0 comments on commit f24f53d

Please sign in to comment.