Skip to content

Commit 595d942

Browse files
(feature/PRD-374-dag-missing-info): docker image collapsible (#592)
* (feature/PRD-374-dag-missing-info): docker image collapsible * (feature/PRD-374-dag-missing-info): run id info in overview * (feature/PRD-374-dag-missing-info): clean PR * (feature/PRD-374-dag-missing-info): clean PR * (feature/PRD-374-dag-missing-info): clean PR -type * (feature/PRD-374-dag-missing-info): clean PR -type - status * (feature/PRD-374-dag-missing-info): clean PR -type - status -file icon * (feature/PRD-374-dag-missing-info): clean PR -type - status -file icon * (feature/PRD-374-dag-missing-info): clean PR - deep sacn fixes * (feature/PRD-374-dag-missing-info): clean PR - deep sacn fixes * (feature/PRD-374-dag-missing-info): clean PR - deep sacn fixes * (feature/PRD-374-dag-missing-info): clean PR - deep sacn fixes
1 parent 0759221 commit 595d942

File tree

17 files changed

+346
-28
lines changed

17 files changed

+346
-28
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import ChevronDown from "@/assets/icons/chevron-down.svg?react";
2+
import {
3+
CollapsibleContent,
4+
CollapsibleHeader,
5+
CollapsiblePanel,
6+
CollapsibleTrigger,
7+
Tag
8+
} from "@zenml-io/react-component-library";
9+
import { useState } from "react";
10+
import Docker from "@/assets/icons/services/docker.svg?react";
11+
import Redirect from "@/assets/icons/redirect.svg?react";
12+
import { CopyButton } from "@/components/CopyButton";
13+
import { Codesnippet } from "@/components/CodeSnippet";
14+
import { KeyValue } from "@/components/KeyValue";
15+
16+
type Props = {
17+
data: any;
18+
};
19+
20+
export function DockerImageCollapsible({ data }: Props) {
21+
const [open, setOpen] = useState(true);
22+
23+
return (
24+
<CollapsiblePanel open={open} onOpenChange={setOpen}>
25+
<CollapsibleHeader intent="primary" className="flex items-center gap-[10px]">
26+
<CollapsibleTrigger className="flex w-full items-center gap-[10px]">
27+
<ChevronDown
28+
className={` ${
29+
open ? "" : "-rotate-90"
30+
} h-5 w-5 rounded-md fill-neutral-500 transition-transform duration-200 hover:bg-neutral-200`}
31+
/>
32+
Docker Image
33+
</CollapsibleTrigger>
34+
</CollapsibleHeader>
35+
<CollapsibleContent className="border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3">
36+
<dl className="grid grid-cols-1 gap-x-[10px] gap-y-2 md:grid-cols-3 md:gap-y-4">
37+
<KeyValue
38+
label="Docker Image"
39+
value={
40+
<div className="flex justify-between">
41+
<Tag className="inline-flex items-center gap-0.5" rounded={false} emphasis="subtle">
42+
<Docker className="mr-1 h-4 w-4 fill-theme-text-brand" />
43+
{"zenml/my_pipeline:data"}
44+
</Tag>
45+
<div className="align-center mr-1 flex">
46+
<a
47+
className="cursor-pointer"
48+
rel="noopener noreferrer"
49+
target="_blank"
50+
href={`https://${data.image}`}
51+
>
52+
<Redirect className="mr-1 mt-0.5 h-5 w-5 fill-theme-text-tertiary" />
53+
</a>
54+
<CopyButton copyText={data.image} isVisible copyTitle="Copy url" />
55+
</div>
56+
</div>
57+
}
58+
/>
59+
<KeyValue
60+
label="Contains Code"
61+
value={
62+
<Tag
63+
color={data.contains_code ? "green" : "grey"}
64+
className="inline-flex items-center gap-0.5"
65+
rounded={false}
66+
emphasis="subtle"
67+
>
68+
{data.contains_code ? "Available" : "None"}
69+
</Tag>
70+
}
71+
/>
72+
</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} />
77+
</CollapsibleContent>
78+
</CollapsiblePanel>
79+
);
80+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@ import { useParams } from "react-router-dom";
44
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
55
import { Skeleton } from "@zenml-io/react-component-library";
66
import { NestedCollapsible } from "@/components/NestedCollapsible";
7+
import { usePipelineBuild } from "@/data/pipeline-builds/all-pipeline-builds-query";
8+
import { DockerImageCollapsible } from "./DockerImageCollapsible";
79

810
export function ConfigurationTab() {
911
const { runId } = useParams() as { runId: string };
1012
const { data, isError, isPending } = usePipelineRun({ runId: runId }, { throwOnError: true });
13+
const { data: buildData } = usePipelineBuild(
14+
{
15+
buildId: data?.body?.build?.id as string
16+
},
17+
{ enabled: !!data?.body?.build?.id }
18+
);
19+
1120
if (isError) return null;
1221
if (isPending)
1322
return (
@@ -22,6 +31,7 @@ export function ConfigurationTab() {
2231
return (
2332
<div className="grid grid-cols-1 gap-5">
2433
<NestedCollapsible title="Parameters" data={data.metadata?.config.parameters} />
34+
{buildData && <DockerImageCollapsible data={buildData?.metadata?.images?.orchestrator} />}
2535
<CodeCollapsible runId={runId} />
2636
<EnvironmentCollapsible run={data} />
2737
<NestedCollapsible title="Extra" data={data.metadata?.config.extra} />
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Skeleton } from "@zenml-io/react-component-library";
2+
import { useParams } from "react-router-dom";
3+
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
4+
import { EmptyCards, MetadataCards, UncategorizedCard } from "@/components/MetadataCards";
5+
import { MetadataMap } from "@/types/common";
6+
7+
export function Metadata() {
8+
const { runId } = useParams() as { runId: string };
9+
10+
const { data, isError, isPending } = usePipelineRun({ runId: runId }, { throwOnError: true });
11+
12+
if (isError) return null;
13+
if (isPending) return <Skeleton className="h-[200px] w-full" />;
14+
if (!data.metadata?.run_metadata || Object.keys(data.metadata.run_metadata).length === 0) {
15+
return <EmptyCards />;
16+
}
17+
18+
return (
19+
<div className="flex flex-col gap-5">
20+
<UncategorizedCard metadata={data.metadata?.run_metadata as MetadataMap} />
21+
<MetadataCards metadata={data.metadata?.run_metadata as MetadataMap} />
22+
</div>
23+
);
24+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { Details } from "./Details";
2+
import { Metadata } from "./Metadata";
23
import { StackCollapsible } from "./Stack";
34

45
export function OverviewTab() {
56
return (
67
<div className="grid grid-cols-1 gap-5">
78
<Details />
89
<StackCollapsible />
10+
<Metadata />
911
</div>
1012
);
1113
}

src/assets/icons/code-browser.svg

Lines changed: 1 addition & 1 deletion
Loading

src/assets/icons/github.svg

Lines changed: 3 additions & 0 deletions
Loading

src/assets/icons/logs.svg

Lines changed: 3 additions & 0 deletions
Loading

src/assets/icons/redirect.svg

Lines changed: 3 additions & 0 deletions
Loading

src/components/MetadataCards.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,24 @@ import { KeyValue } from "./KeyValue";
33
import { NestedCollapsible } from "./NestedCollapsible";
44
import { CollapsibleCard } from "./CollapsibleCard";
55
import { Codesnippet } from "./CodeSnippet";
6+
import { EmptyState } from "./EmptyState";
7+
import File from "@/assets/icons/file.svg?react";
68

79
type Props = { metadata: MetadataMap };
810

11+
export function EmptyCards() {
12+
return (
13+
<CollapsibleCard initialOpen title="Metadata">
14+
<EmptyState icon={<File className="h-[120px] w-[120px] fill-neutral-300" />}>
15+
<div className="text-center">
16+
<p className="mb-2 text-display-xs font-semibold">No metadata found</p>
17+
<p className="text-text-lg text-theme-text-secondary">There are no metadata available.</p>
18+
</div>
19+
</EmptyState>
20+
</CollapsibleCard>
21+
);
22+
}
23+
924
export function MetadataCards({ metadata }: Props) {
1025
const dictMetadata = Object.values(metadata || {}).filter((val) => val.body.type === "dict");
1126
return (

src/components/steps/step-sheet/ConfigurationTab.tsx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { Skeleton } from "@zenml-io/react-component-library";
66
import { KeyValue } from "@/components/KeyValue";
77
import { Codesnippet } from "@/components/CodeSnippet";
88
import { renderAnyToString } from "@/lib/strings";
9+
import { DockerImageCollapsible } from "@/app/runs/[id]/_Tabs/Configuration/DockerImageCollapsible";
10+
import { usePipelineBuild } from "@/data/pipeline-builds/all-pipeline-builds-query";
11+
import { useParams } from "react-router-dom";
12+
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
913

1014
type Props = {
1115
stepId: string;
@@ -15,6 +19,44 @@ export function StepConfigTab({ stepId }: Props) {
1519
const { data, isPending, isError, error } = useStepDetail({ stepId });
1620
const extraData = Object.values(data?.metadata?.config?.extra || {});
1721

22+
const { runId } = useParams() as { runId: string };
23+
24+
const { data: pipeline_run } = usePipelineRun(
25+
{ runId: runId },
26+
{ throwOnError: true, enabled: !!runId }
27+
);
28+
29+
const { data: buildData } = usePipelineBuild(
30+
{
31+
buildId: pipeline_run?.body?.build?.id as string
32+
},
33+
{ enabled: !!pipeline_run?.body?.build?.id }
34+
);
35+
36+
const findIndexImage = () => {
37+
const dockerImages = buildData?.metadata?.images;
38+
39+
if (!dockerImages) {
40+
return null;
41+
}
42+
43+
if (Object.keys(dockerImages).length === 1 && Object.keys(dockerImages)[0] !== "orchestrator") {
44+
return Object.keys(dockerImages)[0];
45+
}
46+
47+
for (const key in dockerImages) {
48+
if (key !== "orchestrator" && key.split(".")[1] !== "orchestrator") {
49+
return key;
50+
}
51+
}
52+
53+
return "orchestrator";
54+
};
55+
56+
const indexImage = findIndexImage();
57+
58+
const dataImage = indexImage && buildData?.metadata?.images?.[indexImage];
59+
1860
if (isError) {
1961
return <ErrorFallback err={error} />;
2062
}
@@ -30,8 +72,8 @@ export function StepConfigTab({ stepId }: Props) {
3072
return (
3173
<div className="space-y-5">
3274
<KeyValueCard data={data.metadata?.config?.parameters as AnyDict} title="Parameters" />
75+
{dataImage ? <DockerImageCollapsible data={dataImage} /> : null}
3376
<CodeSnippetCard id={data.id} />
34-
3577
{extraData.length > 0 ? <KeyValueCard data={extraData as AnyDict} title="Extra" /> : null}
3678
</div>
3779
);

0 commit comments

Comments
 (0)