Skip to content

Commit 8438dc1

Browse files
fix: smaller fixes (#602)
* feat: sort dicts alphabetically * feat: allow nesting in component settings
1 parent cbeb41c commit 8438dc1

File tree

5 files changed

+65
-52
lines changed

5 files changed

+65
-52
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+
}
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/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";

src/components/NestedCollapsible.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ type Props = {
1010
intent?: CollapsibleHeaderProps["intent"];
1111
data?: { [key: string]: any };
1212
title: ReactNode;
13+
contentClassName?: string;
14+
className?: string;
1315
isInitialOpen?: boolean;
1416
};
1517

1618
export function NestedCollapsible({
1719
title,
1820
data,
1921
intent = "primary",
20-
isInitialOpen = false
22+
isInitialOpen = false,
23+
contentClassName,
24+
className
2125
}: Props) {
2226
const objects: { [key: string]: any } = {};
2327
const nonObjects: { [key: string]: any } = {};
@@ -36,11 +40,20 @@ export function NestedCollapsible({
3640

3741
if (Object.keys(data || {}).length === 0) return null;
3842

43+
const values = Object.entries(nonObjects);
44+
values.sort((a, b) => a[0].localeCompare(b[0]));
45+
3946
return (
40-
<CollapsibleCard initialOpen={isInitialOpen} intent={intent} title={title}>
47+
<CollapsibleCard
48+
contentClassName={contentClassName}
49+
className={className}
50+
initialOpen={isInitialOpen}
51+
intent={intent}
52+
title={title}
53+
>
4154
<div className="flex flex-col gap-3">
4255
<dl className="grid grid-cols-1 gap-x-[10px] gap-y-2 md:grid-cols-3 md:gap-y-4">
43-
{Object.entries(nonObjects).map(([key, value]) => (
56+
{values.map(([key, value]) => (
4457
<KeyValue
4558
key={key}
4659
label={key}
@@ -51,7 +64,7 @@ export function NestedCollapsible({
5164
) : regex.test(value) ? (
5265
<Codesnippet className="py-1" highlightCode code={value} />
5366
) : (
54-
<div className="py-1">{value}</div>
67+
<div className="overflow-x-auto py-1">{value}</div>
5568
)}
5669
</>
5770
}

0 commit comments

Comments
 (0)