Files
Matt Aitken 2a1273b683 Major v3 web app update (#924)
* Added the new colours to the Tailwind config

* Fixed Tsailwind compile errors

* WIP Geist working in the app

* WIP Storybook

* Storybook is working again… ouch

* Use Geist mono for CodeMirror

* Some find/replace class changes

* Resizable colours improved

* WIP on primary button

* Minor style improvements

* Improve the side menu header styling

* Improved v2 breadcrumbs

* Account side menu tweaks

* The page now works with the NavBar and UpgradePrompt

* Removed unused import

* Refactored the buttons to be dry-er

* Removed the breadcrumbs

* WIP on nav bar

* WIP updating the button styles

* Fix for the old test page

* Fix for type errors

* Removed console.log

* Colour change in the resizable handle

* New loading bar divider

* Removed the design plugin

* Creating our own storybook pages

* Added some “storybook” pages

* Added DetailCell storybook

* WIP new animation for the loading page

* Added the new loading divider

* Fix for the time frame filter having a green border

* Style improvements to the new test page

* Small style improvements

* Improvements to the list pagination components

* Nav bar back button improved

* Improvements to the run page

* Lots of v2 style improvements

* Help looks better

* Improvements to the regenerate API key modal

* More general improvements

* Added section titles to our storybook

* Added form stories

* Fix for missing key prop

* Loading bar is working

* Fixed button submitting state

* Fix for the test button icon

* Code bg improved

* Improved oauth buttons

* Integration page header fix

* Various improvements, mainly changing button variants

* Segmented control style updates

* Added an outline of 3px for the segment control

* Fixes for the billing pages

* More pricing improvements

* Added dialog to storybook

* Typography now in storybook

* Free usage bar added to storybook

* Added inline clode to storybook

* Separated menu types into a sub section in storybook

* NamedIcon now in storybook

* Added page header to storybook

* Added pricing callout to storybook

* Added radio groups to storybook

* Added segmented controllers to storybook

* Added shortcuts to storybook

* Added switches to storybook

* Added toast to storybook

* Added tooltips to storybook

* Added tree view to storybook

* Added usage charts to storybook

* Tarted up the environment variables page

* Fix for the FreePlanUsage panel bg colours

* Added new badge variants

* Added the <TaskPath /> to the tasks table

* Span header improvements

* Started work on the timeline

* Started work on the timeline

* Fix for the run page header

* Timeline tick marks are working

* Timeline working

* Got the durations showing on hover

* Button improvements

* Experimenting with how the duration should be shown

* Lots of refinements to the timeline

* Much nicer API for the Timeline

* The switch is now purple to match the design, with inverted thumb when on

* Removed old stuff

* Export the props

* Added the span with duration back in

* Simplified more and fixed the span durations

* Put in some decent dummy data

* Rendering defaults

* Wip with the mouse cursor

* Improvements to the story

* Added Slider primitive

* Integrated the icons into the slider

* Lots of layout improvements

* Cleaned up imports

* “Root” indicator

* Animated background on partials

* Pull the styles through to the spans and log dots

* Fixed some bugs in the TreeView when nodes get created or destroyed

* Fix for incorrect parentTask reference

* Added run streaming endpoint for live refreshing

* Added the tabs to Storybook

* Fix for status font size mismatch

* Fix for the misaligned run filter status

* Set a minimum duration on the timeline

* The TreeView now re-calculates if the number of nodes has changed

* Partials now render to the end

* Improved the durations gutter

* The duration is calculated using the current time if there are partial events

* Added the environment label to storybook

* Improved the environment label style

* Removed bottom margin from badge

* Button style improvements

* Callouts style fits the new design better

* Got the scrollbars to appear on the tree/timeline

* Added scroll support

* Synced scrolling working

* Close button and exit icon for the detail panel

* secure field shows start of env

* Clipboard improvements

* Latest lockfile

* Fix for the durations wrapping

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2024-03-04 17:33:53 +00:00

159 lines
5.1 KiB
TypeScript

import { ChevronDownIcon, Square2StackIcon } from "@heroicons/react/24/solid";
import { AnimatePresence, motion } from "framer-motion";
import { Fragment, useState } from "react";
import simplur from "simplur";
import { Paragraph } from "~/components/primitives/Paragraph";
import { ViewTask } from "~/presenters/RunPresenter.server";
import { cn } from "~/utils/cn";
import {
RunPanel,
RunPanelBody,
RunPanelDescription,
RunPanelError,
RunPanelHeader,
RunPanelIconProperty,
RunPanelIconSection,
RunPanelIconTitle,
RunPanelProperties,
TaskSeparator,
UpdatingDelay,
UpdatingDuration,
} from "./RunCard";
import { TaskStatusIcon } from "./TaskStatus";
import { formatDuration } from "@trigger.dev/core/v3";
type TaskCardProps = ViewTask & {
selectedId?: string;
selectedTask: (id: string) => void;
isLast: boolean;
depth: number;
};
export function TaskCard({
selectedId,
selectedTask,
isLast,
depth,
id,
style,
status,
icon,
name,
startedAt,
completedAt,
description,
displayKey,
connection,
properties,
subtasks,
error,
delayUntil,
}: TaskCardProps) {
const [expanded, setExpanded] = useState(false);
const isSelected = id === selectedId;
return (
<Fragment>
<div style={{ marginLeft: `${depth}rem` }}>
<RunPanel selected={isSelected} onClick={() => selectedTask(id)} styleName={style?.style}>
<RunPanelHeader
icon={
status === "COMPLETED" ? (
icon
) : (
<TaskStatusIcon
status={status}
minimal={true}
className={cn("h-5 w-5", !isSelected && "text-charcoal-400")}
/>
)
}
title={status === "COMPLETED" ? name : <RunPanelIconTitle icon={icon} title={name} />}
accessory={
<Paragraph variant="extra-small">
<UpdatingDuration start={startedAt ?? undefined} end={completedAt ?? undefined} />
</Paragraph>
}
styleName={style?.style}
/>
<RunPanelBody>
{error && <RunPanelError text={error.message} stackTrace={error.stack} />}
{description && <RunPanelDescription text={description} variant={style?.variant} />}
<RunPanelIconSection>
{displayKey && <RunPanelIconProperty icon="key" label="Key" value={displayKey} />}
{delayUntil && !completedAt && (
<>
<UpdatingDelay delayUntil={delayUntil} />
</>
)}
{delayUntil && completedAt && (
<RunPanelIconProperty
icon="clock"
label="Delay duration"
value={formatDuration(startedAt, delayUntil, {
style: "long",
maxDecimalPoints: 0,
})}
/>
)}
{connection && (
<RunPanelIconProperty
icon={
connection.integration.definition.icon ?? connection.integration.definitionId
}
label="Connection"
value={connection.integration.slug}
/>
)}
</RunPanelIconSection>
{properties.length > 0 && (
<RunPanelProperties properties={properties} className="mt-4" />
)}
</RunPanelBody>
{subtasks && subtasks.length > 0 && (
<button
className="mt-4 flex h-10 w-full items-center justify-between gap-2 bg-charcoal-800 px-2"
onClick={() => setExpanded((c) => !c)}
>
<div className="flex items-center gap-2">
<Square2StackIcon className="h-5 w-5 text-charcoal-400" />
<Paragraph variant="small">
{simplur`${expanded ? "Hide" : "Show"} ${subtasks.length} subtask[|s]`}
</Paragraph>
</div>
<motion.span
initial={expanded ? "expanded" : "collapsed"}
animate={expanded ? "expanded" : "collapsed"}
variants={{
collapsed: { rotate: 0, transition: { ease: "anticipate" } },
expanded: { rotate: 180, transition: { ease: "anticipate" } },
}}
>
<ChevronDownIcon className={"h-5 w-5 text-charcoal-400 transition"} />
</motion.span>
</button>
)}
</RunPanel>
</div>
{(!isLast || expanded) && <TaskSeparator depth={depth + (expanded ? 1 : 0)} />}
{subtasks &&
subtasks.length > 0 &&
expanded &&
subtasks.map((subtask, index) => (
<AnimatePresence key={subtask.id}>
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 100 }}>
<TaskCard
selectedId={selectedId}
selectedTask={selectedTask}
isLast={false}
depth={depth + 1}
{...subtask}
/>
</motion.div>
</AnimatePresence>
))}
</Fragment>
);
}