Skip to content

Commit 9b310a4

Browse files
Merge pull request #604 from zenml-io/future
2 parents 2ca7f98 + 2f4e918 commit 9b310a4

File tree

22 files changed

+398
-93
lines changed

22 files changed

+398
-93
lines changed

src/app/pipelines/columns.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ExecutionStatusIcon, getExecutionStatusColor } from "@/components/Execu
44
import { ExecutionStatus } from "@/types/pipeline-runs";
55
import { PipelineNamespace, PipelineNamespaceBody } from "@/types/pipelines";
66
import { ColumnDef } from "@tanstack/react-table";
7-
import { Tag } from "@zenml-io/react-component-library";
7+
import { Tag, TagProps } from "@zenml-io/react-component-library";
88
import { Link } from "react-router-dom";
99
import { routes } from "@/router/routes";
1010
import { CopyButton } from "@/components/CopyButton";
@@ -45,17 +45,19 @@ export function getPipelineColumns(): ColumnDef<PipelineNamespace>[] {
4545
}),
4646
cell: ({ getValue }) => {
4747
const { runId, status } = getValue<{
48-
runId: string;
49-
status: PipelineNamespaceBody["latest_run_status"];
48+
runId?: string;
49+
status?: PipelineNamespaceBody["latest_run_status"];
5050
}>();
5151

52+
if (!runId || !status) return <div>No run</div>;
53+
5254
return (
5355
<Link to={routes.runs.detail(runId)}>
5456
<Tag
5557
emphasis="subtle"
5658
rounded={false}
5759
className="inline-flex items-center gap-0.5"
58-
color={"green"}
60+
color={getTagColor(status)}
5961
>
6062
<RunIcon className={`h-3 w-3 ${getRunIconColor(status)}`} />
6163
{runId?.split("-")[0]}
@@ -82,3 +84,19 @@ function getRunIconColor(status?: ExecutionStatus) {
8284
return "fill-theme-text-brand";
8385
}
8486
}
87+
88+
function getTagColor(status?: ExecutionStatus): TagProps["color"] {
89+
if (!status) return "purple";
90+
switch (status) {
91+
case "running":
92+
return "orange";
93+
case "cached":
94+
return "grey";
95+
case "completed":
96+
return "green";
97+
case "failed":
98+
return "red";
99+
case "initializing":
100+
return "purple";
101+
}
102+
}

src/app/runs/[id]/Dag.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ export function DAG() {
4949
fitView(); // Keep an eye on performance here
5050
}, [width, height]);
5151

52+
useEffect(() => {
53+
const timeout = setTimeout(() => {
54+
fitView({ duration: 200 });
55+
}, 100);
56+
return () => {
57+
clearTimeout(timeout);
58+
};
59+
}, [data]);
60+
5261
useLayoutEffect(() => {
5362
onDagreLayout();
5463
}, [data?.nodes, data?.edges, onDagreLayout]);
@@ -82,7 +91,7 @@ export function DAG() {
8291
onEdgesChange={onEdgesChange}
8392
fitView
8493
>
85-
<DagControls />
94+
<DagControls runId={runId} />
8695
</ReactFlow>
8796
);
8897
}

src/app/runs/[id]/_Tabs/Configuration/DockerImageCollapsible.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ import Redirect from "@/assets/icons/redirect.svg?react";
1212
import { CopyButton } from "@/components/CopyButton";
1313
import { Codesnippet } from "@/components/CodeSnippet";
1414
import { KeyValue } from "@/components/KeyValue";
15+
import { BuildItem } from "@/types/pipeline-builds";
16+
import { extractDockerImageKey } from "@/lib/strings";
1517

1618
type Props = {
17-
data: any;
19+
data: BuildItem;
1820
};
1921

2022
export function DockerImageCollapsible({ data }: Props) {
@@ -40,7 +42,7 @@ export function DockerImageCollapsible({ data }: Props) {
4042
<div className="flex justify-between">
4143
<Tag className="inline-flex items-center gap-0.5" rounded={false} emphasis="subtle">
4244
<Docker className="mr-1 h-4 w-4 fill-theme-text-brand" />
43-
{"zenml/my_pipeline:data"}
45+
{extractDockerImageKey(data.image)}
4446
</Tag>
4547
<div className="align-center mr-1 flex">
4648
<a
@@ -70,10 +72,18 @@ export function DockerImageCollapsible({ data }: Props) {
7072
}
7173
/>
7274
</dl>
73-
<p className="mb-2 mt-5 text-theme-text-secondary">Dockerfile</p>
74-
<Codesnippet fullWidth highlightCode wrap code={data.dockerfile} />
75-
<p className="mb-2 mt-5 text-theme-text-secondary">Requirements</p>
76-
<Codesnippet fullWidth highlightCode wrap code={data.requirements} />
75+
{data.dockerfile && (
76+
<>
77+
<p className="mb-2 mt-5 text-theme-text-secondary">Dockerfile</p>
78+
<Codesnippet fullWidth highlightCode wrap code={data.dockerfile} />
79+
</>
80+
)}
81+
{data.requirements && (
82+
<>
83+
<p className="mb-2 mt-5 text-theme-text-secondary">Requirements</p>
84+
<Codesnippet fullWidth highlightCode wrap code={data.requirements} />
85+
</>
86+
)}
7787
</CollapsibleContent>
7888
</CollapsiblePanel>
7989
);

src/app/runs/[id]/_Tabs/Configuration/index.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { CodeCollapsible } from "./CodeCollapsible";
2-
import { EnvironmentCollapsible } from "./EnvironmentCollapsible";
3-
import { useParams } from "react-router-dom";
4-
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
5-
import { Skeleton } from "@zenml-io/react-component-library";
61
import { NestedCollapsible } from "@/components/NestedCollapsible";
72
import { usePipelineBuild } from "@/data/pipeline-builds/all-pipeline-builds-query";
3+
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
4+
import { BuildItem, BuildItemMap } from "@/types/pipeline-builds";
5+
import { Skeleton } from "@zenml-io/react-component-library";
6+
import { useParams } from "react-router-dom";
7+
import { CodeCollapsible } from "./CodeCollapsible";
88
import { DockerImageCollapsible } from "./DockerImageCollapsible";
9+
import { EnvironmentCollapsible } from "./EnvironmentCollapsible";
910

1011
export function ConfigurationTab() {
1112
const { runId } = useParams() as { runId: string };
@@ -31,7 +32,9 @@ export function ConfigurationTab() {
3132
return (
3233
<div className="grid grid-cols-1 gap-5">
3334
<NestedCollapsible title="Parameters" data={data.metadata?.config.parameters} />
34-
{buildData && <DockerImageCollapsible data={buildData?.metadata?.images?.orchestrator} />}
35+
{(buildData?.metadata?.images as BuildItemMap)?.orchestrator && (
36+
<DockerImageCollapsible data={buildData?.metadata?.images?.orchestrator as BuildItem} />
37+
)}
3538
<CodeCollapsible runId={runId} />
3639
<EnvironmentCollapsible run={data} />
3740
<NestedCollapsible title="Extra" data={data.metadata?.config.extra} />
Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
1-
import ChevronDown from "@/assets/icons/chevron-down.svg?react";
2-
import { Key, Value } from "@/components/KeyValue";
1+
import { NestedCollapsible } from "@/components/NestedCollapsible";
32
import { snakeCaseToTitleCase } from "@/lib/strings";
43
import { StackComponent } from "@/types/components";
54
import { PipelineRun } from "@/types/pipeline-runs";
6-
import {
7-
CollapsibleContent,
8-
CollapsibleHeader,
9-
CollapsiblePanel,
10-
CollapsibleTrigger
11-
} from "@zenml-io/react-component-library";
12-
import { ReactNode, useState } from "react";
5+
import { CollapsibleHeader } from "@zenml-io/react-component-library";
136

147
type Props = {
158
component: StackComponent;
169
run: PipelineRun;
1710
};
1811

1912
export function StackComponentCollapsible({ component, run }: Props) {
20-
const [open, setOpen] = useState(false);
21-
2213
const keyName = `${component.body?.type}.${component.body?.flavor}`;
2314
const settings =
2415
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -37,38 +28,18 @@ export function StackComponentCollapsible({ component, run }: Props) {
3728
}
3829

3930
return (
40-
<CollapsiblePanel className="w-full" open={open} onOpenChange={setOpen}>
41-
<CollapsibleHeader intent="secondary" className="flex items-center justify-between ">
42-
<div className="flex w-full items-center gap-[10px]">
43-
<CollapsibleTrigger>
44-
<ChevronDown
45-
className={` ${
46-
open ? "" : "-rotate-90"
47-
} h-5 w-5 rounded-md fill-neutral-500 transition-transform duration-200 hover:bg-neutral-200`}
48-
/>
49-
</CollapsibleTrigger>
50-
<div className="grid w-full grid-cols-2 gap-2">
51-
<span>{snakeCaseToTitleCase(component.body?.type as string)}</span>
52-
<div>{component.name}</div>
53-
</div>
31+
<NestedCollapsible
32+
intent="secondary"
33+
contentClassName="pl-[60px]"
34+
className="w-full"
35+
isInitialOpen={false}
36+
data={settings}
37+
title={
38+
<div className="grid w-full grid-cols-2 gap-2 text-left">
39+
<span>{snakeCaseToTitleCase(component.body?.type as string)}</span>
40+
<div>{component.name}</div>
5441
</div>
55-
</CollapsibleHeader>
56-
<CollapsibleContent className="border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3">
57-
<dl className="grid grid-cols-1 gap-x-[10px] gap-y-2 pl-[36px] md:grid-cols-2 md:gap-y-4">
58-
{Object.entries(settings).map(([key, value]) => (
59-
<KeyValue key={key} label={key} value={JSON.stringify(value)} />
60-
))}
61-
</dl>
62-
</CollapsibleContent>
63-
</CollapsiblePanel>
64-
);
65-
}
66-
67-
function KeyValue({ label, value }: { label: string; value: string | ReactNode }) {
68-
return (
69-
<>
70-
<Key className="col-span-1 text-theme-text-secondary">{label}</Key>
71-
<Value className="col-span-1 w-full truncate text-neutral-700">{value}</Value>
72-
</>
42+
}
43+
/>
7344
);
7445
}

src/app/runs/[id]/_Tabs/Overview/Details.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,19 @@ export function Details() {
7474
</Value>
7575
<Key>Start Time</Key>
7676
<Value>
77-
<DisplayDate dateString={data.metadata?.start_time || ""} />
77+
{data.metadata?.start_time ? (
78+
<DisplayDate dateString={data.metadata?.start_time} />
79+
) : (
80+
"Not available"
81+
)}
7882
</Value>
7983
<Key>End Time</Key>
8084
<Value>
81-
<DisplayDate dateString={data.metadata?.end_time || ""} />
85+
{data.metadata?.end_time ? (
86+
<DisplayDate dateString={data.metadata?.end_time} />
87+
) : (
88+
"Not available"
89+
)}
8290
</Value>
8391
</dl>
8492
</CollapsibleContent>

src/app/settings/connectors/Fragments.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import ConnectorsVideo from "@/assets/illustrations/connectors-video.svg";
12
import { InfoBox as InfoBoxPrimitive } from "@/components/Infobox";
2-
import { Box } from "@zenml-io/react-component-library";
3-
import { ConnectorsSelect } from "./ConnectorsSelect";
3+
import { VideoModal } from "@/components/VideoModal";
4+
import { CommandListItem, generateCommandList } from "@/components/fallback-pages/Commands";
5+
import { HelpBox } from "@/components/fallback-pages/Helpbox";
46
import {
57
AWSSection,
68
AzureSection,
@@ -9,9 +11,9 @@ import {
911
GCPSection,
1012
KubernetesSection
1113
} from "@/contents/connectors";
14+
import { Box } from "@zenml-io/react-component-library";
1215
import { Fragment, useState } from "react";
13-
import { CommandListItem, generateCommandList } from "@/components/fallback-pages/Commands";
14-
import { HelpBox } from "@/components/fallback-pages/Helpbox";
16+
import { ConnectorsSelect } from "./ConnectorsSelect";
1517

1618
export function InfoBox() {
1719
return (
@@ -25,14 +27,30 @@ export function InfoBox() {
2527
}
2628

2729
export function HeaderBox() {
30+
const videoLink =
31+
"https://zenml.portal.trainn.co/share/V6magMJZZvMptz1wdnUmPA/embed?autoplay=false";
2832
return (
29-
<Box className="flex flex-col-reverse items-stretch overflow-hidden md:flex-row">
30-
<div className="w-full p-7 md:w-2/3">
33+
<Box className="flex flex-col-reverse items-stretch overflow-hidden lg:flex-row">
34+
<div className="w-full p-7 lg:w-2/3">
3135
<h2 className="text-display-xs font-semibold">Learn More about Connectors</h2>
3236
<p className="mt-2 text-text-lg text-theme-text-secondary">
3337
Dive into Service Connector Types for a documented approach to secure authentication and
3438
authorization practices.
3539
</p>
40+
<VideoModal videoLink={videoLink} buttonText="Watch the Starter Guide (2 min)" />
41+
</div>
42+
<div className="flex w-full items-center justify-center bg-primary-50 lg:w-1/3">
43+
<VideoModal
44+
fallbackImage={
45+
<img
46+
src={ConnectorsVideo}
47+
alt="Purple squares with text indicating a starter guide for secrets"
48+
className="h-full w-full"
49+
/>
50+
}
51+
videoLink={videoLink}
52+
isButton={false}
53+
/>
3654
</div>
3755
</Box>
3856
);

src/assets/illustrations/connectors-video.svg

Lines changed: 21 additions & 0 deletions
Loading

src/components/CollapsibleCard.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
CollapsibleHeader,
66
CollapsibleHeaderProps
77
} from "@zenml-io/react-component-library";
8+
import { cn } from "@zenml-io/react-component-library/utilities";
89
import ChevronDown from "@/assets/icons/chevron-down.svg?react";
910
import { useState } from "react";
1011

@@ -13,6 +14,7 @@ type CollapsibleCardProps = {
1314
children: React.ReactNode;
1415
title: string | React.ReactNode;
1516
className?: string;
17+
contentClassName?: string;
1618
intent?: CollapsibleHeaderProps["intent"];
1719
};
1820

@@ -21,6 +23,7 @@ export function CollapsibleCard({
2123
children,
2224
initialOpen = false,
2325
className,
26+
contentClassName,
2427
intent = "primary"
2528
}: CollapsibleCardProps) {
2629
const [open, setOpen] = useState(initialOpen);
@@ -37,7 +40,12 @@ export function CollapsibleCard({
3740
</CollapsibleTrigger>
3841
</CollapsibleHeader>
3942

40-
<CollapsibleContent className="space-y-3 border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3">
43+
<CollapsibleContent
44+
className={cn(
45+
"space-y-3 border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3",
46+
contentClassName
47+
)}
48+
>
4149
{children}
4250
</CollapsibleContent>
4351
</CollapsiblePanel>

src/components/MetadataCards.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export function UncategorizedCard({ metadata }: Props) {
4646

4747
if (nonDicts.length === 0) return null;
4848

49+
// sort nonDicts alphabetically by index 0
50+
nonDicts.sort((a, b) => a[0].localeCompare(b[0]));
51+
4952
const convertToMBorGB = (number: number) => {
5053
if (number < 1024) {
5154
return number + " bytes";

0 commit comments

Comments
 (0)