Skip to content
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
16d5013
Added waitpoints/tokens to the sidebar
matt-aitken Mar 20, 2025
ac89e1b
Added indexes to the Waitpoint time for filtering
matt-aitken Mar 20, 2025
e05ee25
Begun work on `WaitpointTokenListPresenter`, the pag is a copy of the…
matt-aitken Mar 20, 2025
964fcf2
MVP of waitpoint token page
matt-aitken Mar 20, 2025
863eb1d
Added status
matt-aitken Mar 20, 2025
11f647f
Expiry of timeout/ttl
matt-aitken Mar 20, 2025
4439880
Improvements to the waitpoint table
matt-aitken Mar 20, 2025
6002c21
Improved columns and icon
matt-aitken Mar 20, 2025
66f1285
Merge remote-tracking branch 'origin/main' into waitpoint-tokens-page
matt-aitken Mar 20, 2025
a41f402
Changes from the RunTag copy on hover branch
matt-aitken Mar 20, 2025
725291f
Fix for nested button error
matt-aitken Mar 20, 2025
f55b059
Added waitpoint tags to the DB/table
matt-aitken Mar 20, 2025
3f6442d
Applied Eric’s task run tag fix (it’s live on prod in the legacy run …
matt-aitken Mar 20, 2025
370c76f
Added tags to waitpoints
matt-aitken Mar 20, 2025
c66d2b2
Removed todos that have been done
matt-aitken Mar 20, 2025
98283fc
Added token support for releaseConcurrency. Also added a ton of JSDocs
matt-aitken Mar 20, 2025
3abad43
Added releaseConcurrency to the API token endpoint…
matt-aitken Mar 20, 2025
35028c2
WIP on waitpoint page filters
matt-aitken Mar 23, 2025
2336a2c
Fix for tags filtering
matt-aitken Mar 23, 2025
bf03eb4
Waitpoint filters working
matt-aitken Mar 23, 2025
0770e5f
Fix for badly named function
matt-aitken Mar 24, 2025
d96924e
WaitpointPresenter used from SpanPresenter
matt-aitken Mar 24, 2025
7825872
Waitpoint detail panel WIP
matt-aitken Mar 24, 2025
86eda3c
Fix for server client hydration issue with CodeBlock
matt-aitken Mar 24, 2025
21f8071
Selected waitpoint panel
matt-aitken Mar 24, 2025
960bd01
Merge remote-tracking branch 'origin/main' into waitpoint-tokens-page
matt-aitken Mar 24, 2025
5bf0cc5
Added a blank state
matt-aitken Mar 24, 2025
9241633
Added waitpoint docs link
matt-aitken Mar 25, 2025
f7c2aa1
Fix for animated number going past the target
matt-aitken Mar 25, 2025
8d4b842
Fix for the queue list pagination and upgrade status
matt-aitken Mar 25, 2025
0819ae7
Engine version error for waitpoint token list
matt-aitken Mar 25, 2025
ca47383
RunTag component doesn’t get squished and hover behaviour is nicer
matt-aitken Mar 25, 2025
4832469
Associating runs with waitpoints
matt-aitken Mar 25, 2025
64d8bbd
Added triggered icon
matt-aitken Mar 25, 2025
6890cce
Link directly to the waitpoint
matt-aitken Mar 25, 2025
d24e976
Fix for TS error on waitpoint retrieve
matt-aitken Mar 25, 2025
e3fffe2
Added CopyableText component, used for waitpoint id in the table
matt-aitken Mar 25, 2025
004ef18
Removed the confetti 🎊
matt-aitken Mar 25, 2025
f8b7141
Deleted some old images
matt-aitken Mar 25, 2025
461e987
Moved some schemas/types to core. Use `id` instead of `friendlyId`
matt-aitken Mar 26, 2025
0efc415
Added wait.listTokens() function. Made some changes to the types to m…
matt-aitken Mar 26, 2025
e17d25c
WIP wait.retrieveToken()
matt-aitken Mar 26, 2025
59011f3
wait.retrieveToken working
matt-aitken Mar 26, 2025
ada673b
Added data to retrieve token
matt-aitken Mar 26, 2025
bf5ec07
Separate ApiWaitpointPresenter completely
matt-aitken Mar 26, 2025
7bc307a
Added completed time to the waitpoint detail panel
matt-aitken Mar 26, 2025
9ad0508
Merge remote-tracking branch 'origin/main' into waitpoint-tokens-page
matt-aitken Mar 26, 2025
fe040df
Fix for the Avatar component having SSR issues. Specify the size in r…
matt-aitken Mar 26, 2025
721558b
Fix for applied idempotency key filter dropdown showing the id field
matt-aitken Mar 26, 2025
0f293a7
Use parentheses to make sure the token list query respects idempotenc…
matt-aitken Mar 26, 2025
bf2fead
Use the proper logger, and have a decent message with info to track t…
matt-aitken Mar 26, 2025
aeb4a58
Pass the org title into the Avatar
matt-aitken Mar 26, 2025
0e4a759
Better error when failing to creating a manual waitpoint after X atte…
matt-aitken Mar 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,6 @@ apps/**/public/build
/packages/cli-v3/src/package.json
.husky
/packages/react-hooks/src/package.json
/packages/core/src/package.json
/packages/trigger-sdk/src/package.json
/packages/python/src/package.json
9 changes: 9 additions & 0 deletions apps/webapp/app/assets/icons/StatusIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { cn } from "~/utils/cn";

export function StatusIcon({ className }: { className?: string }) {
return (
<div className={cn("grid place-items-center", className)}>
<div className="size-[75%] rounded-full border-2 border-text-dimmed" />
</div>
);
}
5 changes: 5 additions & 0 deletions apps/webapp/app/assets/icons/TriggerIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { BoltIcon } from "@heroicons/react/20/solid";

export function TriggerIcon({ className }: { className?: string }) {
return <BoltIcon className={className} />;
}
12 changes: 12 additions & 0 deletions apps/webapp/app/assets/icons/WaitpointTokenIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function WaitpointTokenIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.71193 3.50338C6.89005 3.1921 7.22123 3.00004 7.57987 3.00003L16.4201 3C16.7787 3 17.1099 3.19206 17.288 3.50334L21.8658 11.5034C22.0419 11.8111 22.0419 12.189 21.8658 12.4967L17.288 20.4967C17.1099 20.8079 16.7787 21 16.4201 21H7.57987C7.22123 21 6.89005 20.8079 6.71193 20.4967L2.1342 12.4967C1.95813 12.189 1.95813 11.8111 2.1342 11.5034L6.71193 3.50338ZM8.5 9.00011C8.5 8.44783 8.94771 8.00011 9.5 8.00011H10C10.5523 8.00011 11 8.44783 11 9.00011V15.0001C11 15.5524 10.5523 16.0001 10 16.0001H9.5C8.94771 16.0001 8.5 15.5524 8.5 15.0001V9.00011ZM14 8.00006C13.4477 8.00006 13 8.44777 13 9.00006V15.0001C13 15.5523 13.4477 16.0001 14 16.0001H14.5C15.0523 16.0001 15.5 15.5523 15.5 15.0001V9.00006C15.5 8.44777 15.0523 8.00006 14.5 8.00006H14Z"
fill="currentColor"
/>
</svg>
);
}
25 changes: 25 additions & 0 deletions apps/webapp/app/components/BlankStatePanels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { StepNumber } from "./primitives/StepNumber";
import { TextLink } from "./primitives/TextLink";
import { InitCommandV3, PackageManagerProvider, TriggerDevStepV3 } from "./SetupCommands";
import { StepContentContainer } from "./StepContentContainer";
import { WaitpointTokenIcon } from "~/assets/icons/WaitpointTokenIcon";

export function HasNoTasksDev() {
return (
Expand Down Expand Up @@ -412,6 +413,30 @@ export function QueuesHasNoTasks() {
);
}

export function NoWaitpointTokens() {
return (
<InfoPanel
title="You don't have any waitpoint tokens"
icon={WaitpointTokenIcon}
iconClassName="text-sky-500"
panelClassName="max-w-md"
accessory={
<LinkButton to={docsPath("wait")} variant="docs/small" LeadingIcon={BookOpenIcon}>
Waitpoint docs
</LinkButton>
}
>
<Paragraph spacing variant="small">
Waitpoint tokens are used to pause runs until you complete the token so the run can
continue.
</Paragraph>
<Paragraph spacing variant="small">
You can build approval workflows using them, as well as other use cases.
</Paragraph>
</InfoPanel>
);
}

function SwitcherPanel() {
const organization = useOrganization();
const project = useProject();
Expand Down
28 changes: 27 additions & 1 deletion apps/webapp/app/components/code/CodeBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ArrowsPointingOutIcon } from "@heroicons/react/20/solid";
import { Clipboard, ClipboardCheck } from "lucide-react";
import type { Language, PrismTheme } from "prism-react-renderer";
import { Highlight, Prism } from "prism-react-renderer";
import { forwardRef, ReactNode, useCallback, useState } from "react";
import { forwardRef, ReactNode, useCallback, useEffect, useState } from "react";
import { cn } from "~/utils/cn";
import { Button } from "../primitives/Buttons";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../primitives/Dialog";
Expand Down Expand Up @@ -422,6 +422,32 @@ function HighlightCode({
className,
preClassName,
}: HighlightCodeProps) {
const [isLoaded, setIsLoaded] = useState(false);

useEffect(() => {
// This ensures the language definitions are loaded
Promise.all([
//@ts-ignore
import("prismjs/components/prism-json"),
//@ts-ignore
import("prismjs/components/prism-typescript"),
]).then(() => setIsLoaded(true));
}, []);

if (!isLoaded) {
return (
<div
dir="ltr"
className={cn(
"overflow-auto px-3 py-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600",
className
)}
>
<pre className={cn("relative mr-2 font-mono leading-relaxed", preClassName)}>{code}</pre>
</div>
);
}

return (
<Highlight theme={theme} code={code} language={language}>
{({
Expand Down
11 changes: 11 additions & 0 deletions apps/webapp/app/components/navigation/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
v3SchedulesPath,
v3TestPath,
v3UsagePath,
v3WaitpointTokensPath,
} from "~/utils/pathBuilder";
import connectedImage from "../../assets/images/cli-connected.png";
import disconnectedImage from "../../assets/images/cli-disconnected.png";
Expand All @@ -80,6 +81,7 @@ import { HelpAndFeedback } from "./HelpAndFeedbackPopover";
import { SideMenuHeader } from "./SideMenuHeader";
import { SideMenuItem } from "./SideMenuItem";
import { SideMenuSection } from "./SideMenuSection";
import { WaitpointTokenIcon } from "~/assets/icons/WaitpointTokenIcon";

type SideMenuUser = Pick<User, "email" | "admin"> & { isImpersonating: boolean };
export type SideMenuProject = Pick<
Expand Down Expand Up @@ -211,6 +213,15 @@ export function SideMenu({
/>
</div>

<SideMenuSection title="Waitpoints">
<SideMenuItem
name="Tokens"
icon={WaitpointTokenIcon}
activeIconColor="text-sky-500"
to={v3WaitpointTokensPath(organization, project, environment)}
/>
</SideMenuSection>

<SideMenuSection title="Manage">
<SideMenuItem
name="API keys"
Expand Down
13 changes: 8 additions & 5 deletions apps/webapp/app/components/primitives/AnimatedNumber.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { motion, useSpring, useTransform } from "framer-motion";
import { motion, useSpring, useTransform, useMotionValue, animate } from "framer-motion";
import { useEffect } from "react";

export function AnimatedNumber({ value }: { value: number }) {
let spring = useSpring(value, { mass: 0.8, stiffness: 75, damping: 15 });
let display = useTransform(spring, (current) => Math.round(current).toLocaleString());
const motionValue = useMotionValue(value);
let display = useTransform(motionValue, (current) => Math.round(current).toLocaleString());

useEffect(() => {
spring.set(value);
}, [spring, value]);
animate(motionValue, value, {
duration: 0.5,
ease: "easeInOut",
});
}, [value]);

return <motion.span>{display}</motion.span>;
}
61 changes: 61 additions & 0 deletions apps/webapp/app/components/primitives/CopyableText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useCallback, useState } from "react";
import { SimpleTooltip } from "~/components/primitives/Tooltip";
import { ClipboardCheckIcon, ClipboardIcon } from "lucide-react";
import { cn } from "~/utils/cn";

export function CopyableText({ value, className }: { value: string; className?: string }) {
const [isHovered, setIsHovered] = useState(false);
const [copied, setCopied] = useState(false);

const copy = useCallback(
(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
navigator.clipboard.writeText(value);
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 1500);
},
[value]
);

return (
<span
className={cn("group relative inline-flex h-6 items-center", className)}
onMouseLeave={() => setIsHovered(false)}
>
<span onMouseEnter={() => setIsHovered(true)}>{value}</span>
<span
onClick={copy}
onMouseDown={(e) => e.stopPropagation()}
className={cn(
"absolute -right-6 top-0 z-10 size-6 font-sans",
isHovered ? "flex" : "hidden"
)}
>
<SimpleTooltip
button={
<span
className={cn(
"ml-1 flex size-6 items-center justify-center rounded border border-charcoal-650 bg-charcoal-750",
copied
? "text-green-500"
: "text-text-dimmed hover:border-charcoal-600 hover:bg-charcoal-700 hover:text-text-bright"
)}
>
{copied ? (
<ClipboardCheckIcon className="size-3.5" />
) : (
<ClipboardIcon className="size-3.5" />
)}
</span>
}
content={copied ? "Copied!" : "Copy text"}
className="font-sans"
disableHoverableContent
/>
</span>
</span>
);
}
51 changes: 51 additions & 0 deletions apps/webapp/app/components/runs/v3/PacketDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { CloudArrowDownIcon } from "@heroicons/react/20/solid";
import { CodeBlock } from "~/components/code/CodeBlock";
import { LinkButton } from "~/components/primitives/Buttons";
import { Paragraph } from "~/components/primitives/Paragraph";

export function PacketDisplay({
data,
dataType,
title,
}: {
data: string;
dataType: string;
title: string;
}) {
switch (dataType) {
case "application/store": {
return (
<div className="flex flex-col">
<Paragraph variant="base/bright" className="w-full border-b border-grid-dimmed py-2.5">
{title}
</Paragraph>
<LinkButton LeadingIcon={CloudArrowDownIcon} to={data} variant="tertiary/medium" download>
Download
</LinkButton>
</div>
);
}
case "text/plain": {
return (
<CodeBlock
language="markdown"
rowTitle={title}
code={data}
maxLines={20}
showLineNumbers={false}
/>
);
}
default: {
return (
<CodeBlock
language="json"
rowTitle={title}
code={data}
maxLines={20}
showLineNumbers={false}
/>
);
}
}
}
7 changes: 2 additions & 5 deletions apps/webapp/app/components/runs/v3/RunFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import {
TaskRunStatusCombo,
} from "./TaskRunStatus";
import { TaskTriggerSourceIcon } from "./TaskTriggerSource";
import { StatusIcon } from "~/assets/icons/StatusIcon";

export const TaskAttemptStatus = z.enum(allTaskRunStatuses);

Expand Down Expand Up @@ -148,11 +149,7 @@ const filterTypes = [
{
name: "statuses",
title: "Status",
icon: (
<div className="flex size-4 items-center justify-center">
<div className="size-3 rounded-full border-2 border-text-dimmed" />
</div>
),
icon: <StatusIcon className="size-4" />,
},
{ name: "tasks", title: "Tasks", icon: <TaskIcon className="size-4" /> },
{ name: "tags", title: "Tags", icon: <TagIcon className="size-4" /> },
Expand Down
3 changes: 3 additions & 0 deletions apps/webapp/app/components/runs/v3/RunIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { tablerIcons } from "~/utils/tablerIcons";
import tablerSpritePath from "~/components/primitives/tabler-sprite.svg";
import { TaskCachedIcon } from "~/assets/icons/TaskCachedIcon";
import { PauseIcon } from "~/assets/icons/PauseIcon";
import { TriggerIcon } from "~/assets/icons/TriggerIcon";

type TaskIconProps = {
name: string | undefined;
Expand Down Expand Up @@ -65,6 +66,8 @@ export function RunIcon({ name, className, spanName }: TaskIconProps) {
return <TagIcon className={cn(className, "text-text-dimmed")} />;
case "queue":
return <RectangleStackIcon className={cn(className, "text-purple-500")} />;
case "trigger":
return <TriggerIcon className={cn(className, "text-orange-500")} />;
//log levels
case "debug":
case "log":
Expand Down
Loading
Loading