Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dashboard): Nv 4476 workflow editor header navigation #6700

Merged
merged 12 commits into from
Oct 17, 2024
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/edit-workflow-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const EditWorkflowLayout = ({
<IntercomProvider appId={INTERCOM_APP_ID}>
<div className="relative flex h-full w-full">
<div className="flex flex-1 flex-col overflow-y-auto overflow-x-hidden">
<HeaderNavigation startItems={headerStartItems} />
<HeaderNavigation startItems={headerStartItems} hideBridgeUrl />

<div className="flex flex-1 flex-col overflow-y-auto overflow-x-hidden">{children}</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import { InboxButton } from '@/components/inbox-button';
import { CustomerSupportButton } from './customer-support-button';
import { EditBridgeUrlButton } from './edit-bridge-url-button';

export const HeaderNavigation = ({ startItems }: { startItems?: ReactNode }) => {
export const HeaderNavigation = ({
startItems,
hideBridgeUrl = false,
}: {
startItems?: ReactNode;
hideBridgeUrl?: boolean;
}) => {
return (
<div className="bg-background flex w-full items-center justify-between border-b px-6 py-3">
<div className="bg-background flex w-full items-center justify-between border-b px-2.5 py-1.5">
{startItems}
<div className="text-foreground-600 ml-auto flex items-center gap-3">
<EditBridgeUrlButton />
{!hideBridgeUrl ? <EditBridgeUrlButton /> : null}
<CustomerSupportButton />
<InboxButton />
<UserProfile />
Expand Down
12 changes: 12 additions & 0 deletions apps/dashboard/src/components/icons/arrow-right.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

export function ArrowRight(props: React.ComponentPropsWithoutRef<'svg'>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="12" viewBox="0 0 8 12" fill="none" {...props}>
<path
d="M3.0452 5.99908L7.5002 10.4541L6.2276 11.7267L0.5 5.99908L6.2276 0.271484L7.5002 1.54408L3.0452 5.99908Z"
fill="currentColor"
/>
</svg>
);
}
2 changes: 2 additions & 0 deletions apps/dashboard/src/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from './logo-circle';
export * from './notification-5-fill';
export * from './mail-3-fill';
export * from './sms';
export * from './route-fill';
export * from './arrow-right';
12 changes: 12 additions & 0 deletions apps/dashboard/src/components/icons/route-fill.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

export function RouteFill(props: React.ComponentPropsWithoutRef<'svg'>) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 20 20" {...props}>
<path
fill="currentColor"
d="M4 12.25V7.375a3.375 3.375 0 016.75 0v5.25a1.875 1.875 0 103.75 0V7.623a2.25 2.25 0 111.5 0v5.002a3.375 3.375 0 01-6.75 0v-5.25a1.875 1.875 0 10-3.75 0v4.875h2.25l-3 3.75-3-3.75H4z"
></path>
</svg>
);
}
96 changes: 96 additions & 0 deletions apps/dashboard/src/components/primitives/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { cn } from '@/utils/ui';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit picky comment: Is breadcrumb a primitive? It's a specific component displayed in one place in the app. Should we remove it from this folder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we will use it in other areas too, like Activity feed, Subscribers list page
< Development / Subscribers / Biswajeet Das

import { Slot } from '@radix-ui/react-slot';
import { MoreHorizontal } from 'lucide-react';
import * as React from 'react';
import { Link, LinkProps } from 'react-router-dom';

const Breadcrumb = React.forwardRef<
HTMLElement,
React.ComponentPropsWithoutRef<'nav'> & {
separator?: React.ReactNode;
}
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />);
Breadcrumb.displayName = 'Breadcrumb';

const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<'ol'>>(
({ className, ...props }, ref) => (
<ol
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

ref={ref}
className={cn(
'flex flex-nowrap items-center gap-1.5 break-words text-sm font-medium text-neutral-600 sm:gap-2.5',
className
)}
{...props}
/>
)
);
BreadcrumbList.displayName = 'BreadcrumbList';

const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<'li'>>(
({ className, ...props }, ref) => (
<li ref={ref} className={cn('inline-flex items-center gap-1.5', className)} {...props} />
)
);
BreadcrumbItem.displayName = 'BreadcrumbItem';

const BreadcrumbLink = React.forwardRef<
HTMLAnchorElement,
LinkProps & {
asChild?: boolean;
}
>(({ asChild, className, ...props }, ref) => {
const Component = asChild ? Slot : Link;

return (
<Component
ref={ref}
className={cn('transition-colors hover:text-neutral-950 hover:underline', className)}
{...props}
/>
);
});
BreadcrumbLink.displayName = 'BreadcrumbLink';

const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<'span'>>(
({ className, ...props }, ref) => (
<span
ref={ref}
role="link"
aria-disabled="true"
aria-current="page"
className={cn('flex gap-1.5 font-medium text-neutral-950', className)}
{...props}
/>
)
);
BreadcrumbPage.displayName = 'BreadcrumbPage';

const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<'li'>) => (
<li role="presentation" aria-hidden="true" className={cn('text-neutral-300', className)} {...props}>
{children ?? '/'}
</li>
);
BreadcrumbSeparator.displayName = 'BreadcrumbSeparator';

const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => (
<span
role="presentation"
aria-hidden="true"
className={cn('flex h-9 w-9 items-center justify-center', className)}
{...props}
>
<MoreHorizontal className="h-4 w-4" />
<span className="sr-only">More</span>
</span>
);
BreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis';

export {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
};
67 changes: 65 additions & 2 deletions apps/dashboard/src/pages/edit-workflow.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,73 @@
import { WorkflowEditor } from '@/components/workflow-editor';
import { EditWorkflowLayout } from '@/components/edit-workflow-layout';
import { ArrowRight, RouteFill } from '@/components/icons';
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/components/primitives/breadcrumb';
import { Button } from '@/components/primitives/button';
import { WorkflowEditor } from '@/components/workflow-editor';
import { useEnvironment } from '@/context/environment/hooks';
import { useFetchWorkflow } from '@/hooks/use-fetch-workflow';
import { buildRoute, ROUTES } from '@/utils/routes';
import React from 'react';
import { useNavigate, useParams } from 'react-router-dom';

export const EditWorkflowPage = () => {
return (
<EditWorkflowLayout headerStartItems={<h1 className="text-foreground-950">Edit Workflow</h1>}>
<EditWorkflowLayout headerStartItems={<StartItems />}>
<WorkflowEditor />
BiswaViraj marked this conversation as resolved.
Show resolved Hide resolved
</EditWorkflowLayout>
);
};

const StartItems = () => {
const { currentEnvironment } = useEnvironment();
const { workflowId } = useParams<{ workflowId?: string }>();
const navigate = useNavigate();
const workflowsRoute = buildRoute(ROUTES.WORKFLOWS, { environmentId: currentEnvironment?._id ?? '' });
const { workflow } = useFetchWorkflow({
workflowId,
});

const breadcrumbs = [
{ label: currentEnvironment?.name, href: '/' },
{
label: 'Workflows',
href: workflowsRoute,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these two will be the same route

];

const handleBackNav = () => {
navigate(workflowsRoute);
};

return (
<div className="flex items-center gap-2">
<Button variant="link" onClick={handleBackNav}>
<ArrowRight className="text-neutral-950" />
</Button>
<Breadcrumb>
<BreadcrumbList>
{breadcrumbs.map(({ label, href }) => (
<React.Fragment key={href}>
BiswaViraj marked this conversation as resolved.
Show resolved Hide resolved
<BreadcrumbItem>
<BreadcrumbLink to={href}>{label}</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
</React.Fragment>
))}
<BreadcrumbItem>
<BreadcrumbPage>
<RouteFill />
{workflow?.name}
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</div>
);
};
Loading