Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release #604

Merged
merged 7 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 22 additions & 4 deletions src/app/pipelines/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ExecutionStatusIcon, getExecutionStatusColor } from "@/components/Execu
import { ExecutionStatus } from "@/types/pipeline-runs";
import { PipelineNamespace, PipelineNamespaceBody } from "@/types/pipelines";
import { ColumnDef } from "@tanstack/react-table";
import { Tag } from "@zenml-io/react-component-library";
import { Tag, TagProps } from "@zenml-io/react-component-library";
import { Link } from "react-router-dom";
import { routes } from "@/router/routes";
import { CopyButton } from "@/components/CopyButton";
Expand Down Expand Up @@ -45,17 +45,19 @@ export function getPipelineColumns(): ColumnDef<PipelineNamespace>[] {
}),
cell: ({ getValue }) => {
const { runId, status } = getValue<{
runId: string;
status: PipelineNamespaceBody["latest_run_status"];
runId?: string;
status?: PipelineNamespaceBody["latest_run_status"];
}>();

if (!runId || !status) return <div>No run</div>;

return (
<Link to={routes.runs.detail(runId)}>
<Tag
emphasis="subtle"
rounded={false}
className="inline-flex items-center gap-0.5"
color={"green"}
color={getTagColor(status)}
>
<RunIcon className={`h-3 w-3 ${getRunIconColor(status)}`} />
{runId?.split("-")[0]}
Expand All @@ -82,3 +84,19 @@ function getRunIconColor(status?: ExecutionStatus) {
return "fill-theme-text-brand";
}
}

function getTagColor(status?: ExecutionStatus): TagProps["color"] {
if (!status) return "purple";
switch (status) {
case "running":
return "orange";
case "cached":
return "grey";
case "completed":
return "green";
case "failed":
return "red";
case "initializing":
return "purple";
}
}
11 changes: 10 additions & 1 deletion src/app/runs/[id]/Dag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ export function DAG() {
fitView(); // Keep an eye on performance here
}, [width, height]);

useEffect(() => {
const timeout = setTimeout(() => {
fitView({ duration: 200 });
}, 100);
return () => {
clearTimeout(timeout);
};
}, [data]);

useLayoutEffect(() => {
onDagreLayout();
}, [data?.nodes, data?.edges, onDagreLayout]);
Expand Down Expand Up @@ -82,7 +91,7 @@ export function DAG() {
onEdgesChange={onEdgesChange}
fitView
>
<DagControls />
<DagControls runId={runId} />
</ReactFlow>
);
}
22 changes: 16 additions & 6 deletions src/app/runs/[id]/_Tabs/Configuration/DockerImageCollapsible.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import Redirect from "@/assets/icons/redirect.svg?react";
import { CopyButton } from "@/components/CopyButton";
import { Codesnippet } from "@/components/CodeSnippet";
import { KeyValue } from "@/components/KeyValue";
import { BuildItem } from "@/types/pipeline-builds";
import { extractDockerImageKey } from "@/lib/strings";

type Props = {
data: any;
data: BuildItem;
};

export function DockerImageCollapsible({ data }: Props) {
Expand All @@ -40,7 +42,7 @@ export function DockerImageCollapsible({ data }: Props) {
<div className="flex justify-between">
<Tag className="inline-flex items-center gap-0.5" rounded={false} emphasis="subtle">
<Docker className="mr-1 h-4 w-4 fill-theme-text-brand" />
{"zenml/my_pipeline:data"}
{extractDockerImageKey(data.image)}
</Tag>
<div className="align-center mr-1 flex">
<a
Expand Down Expand Up @@ -70,10 +72,18 @@ export function DockerImageCollapsible({ data }: Props) {
}
/>
</dl>
<p className="mb-2 mt-5 text-theme-text-secondary">Dockerfile</p>
<Codesnippet fullWidth highlightCode wrap code={data.dockerfile} />
<p className="mb-2 mt-5 text-theme-text-secondary">Requirements</p>
<Codesnippet fullWidth highlightCode wrap code={data.requirements} />
{data.dockerfile && (
<>
<p className="mb-2 mt-5 text-theme-text-secondary">Dockerfile</p>
<Codesnippet fullWidth highlightCode wrap code={data.dockerfile} />
</>
)}
{data.requirements && (
<>
<p className="mb-2 mt-5 text-theme-text-secondary">Requirements</p>
<Codesnippet fullWidth highlightCode wrap code={data.requirements} />
</>
)}
</CollapsibleContent>
</CollapsiblePanel>
);
Expand Down
15 changes: 9 additions & 6 deletions src/app/runs/[id]/_Tabs/Configuration/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { CodeCollapsible } from "./CodeCollapsible";
import { EnvironmentCollapsible } from "./EnvironmentCollapsible";
import { useParams } from "react-router-dom";
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
import { Skeleton } from "@zenml-io/react-component-library";
import { NestedCollapsible } from "@/components/NestedCollapsible";
import { usePipelineBuild } from "@/data/pipeline-builds/all-pipeline-builds-query";
import { usePipelineRun } from "@/data/pipeline-runs/pipeline-run-detail-query";
import { BuildItem, BuildItemMap } from "@/types/pipeline-builds";
import { Skeleton } from "@zenml-io/react-component-library";
import { useParams } from "react-router-dom";
import { CodeCollapsible } from "./CodeCollapsible";
import { DockerImageCollapsible } from "./DockerImageCollapsible";
import { EnvironmentCollapsible } from "./EnvironmentCollapsible";

export function ConfigurationTab() {
const { runId } = useParams() as { runId: string };
Expand All @@ -31,7 +32,9 @@ export function ConfigurationTab() {
return (
<div className="grid grid-cols-1 gap-5">
<NestedCollapsible title="Parameters" data={data.metadata?.config.parameters} />
{buildData && <DockerImageCollapsible data={buildData?.metadata?.images?.orchestrator} />}
{(buildData?.metadata?.images as BuildItemMap)?.orchestrator && (
<DockerImageCollapsible data={buildData?.metadata?.images?.orchestrator as BuildItem} />
)}
<CodeCollapsible runId={runId} />
<EnvironmentCollapsible run={data} />
<NestedCollapsible title="Extra" data={data.metadata?.config.extra} />
Expand Down
57 changes: 14 additions & 43 deletions src/app/runs/[id]/_Tabs/Overview/ComponentCollapsible.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
import ChevronDown from "@/assets/icons/chevron-down.svg?react";
import { Key, Value } from "@/components/KeyValue";
import { NestedCollapsible } from "@/components/NestedCollapsible";
import { snakeCaseToTitleCase } from "@/lib/strings";
import { StackComponent } from "@/types/components";
import { PipelineRun } from "@/types/pipeline-runs";
import {
CollapsibleContent,
CollapsibleHeader,
CollapsiblePanel,
CollapsibleTrigger
} from "@zenml-io/react-component-library";
import { ReactNode, useState } from "react";
import { CollapsibleHeader } from "@zenml-io/react-component-library";

type Props = {
component: StackComponent;
run: PipelineRun;
};

export function StackComponentCollapsible({ component, run }: Props) {
const [open, setOpen] = useState(false);

const keyName = `${component.body?.type}.${component.body?.flavor}`;
const settings =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -37,38 +28,18 @@ export function StackComponentCollapsible({ component, run }: Props) {
}

return (
<CollapsiblePanel className="w-full" open={open} onOpenChange={setOpen}>
<CollapsibleHeader intent="secondary" className="flex items-center justify-between ">
<div className="flex w-full items-center gap-[10px]">
<CollapsibleTrigger>
<ChevronDown
className={` ${
open ? "" : "-rotate-90"
} h-5 w-5 rounded-md fill-neutral-500 transition-transform duration-200 hover:bg-neutral-200`}
/>
</CollapsibleTrigger>
<div className="grid w-full grid-cols-2 gap-2">
<span>{snakeCaseToTitleCase(component.body?.type as string)}</span>
<div>{component.name}</div>
</div>
<NestedCollapsible
intent="secondary"
contentClassName="pl-[60px]"
className="w-full"
isInitialOpen={false}
data={settings}
title={
<div className="grid w-full grid-cols-2 gap-2 text-left">
<span>{snakeCaseToTitleCase(component.body?.type as string)}</span>
<div>{component.name}</div>
</div>
</CollapsibleHeader>
<CollapsibleContent className="border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3">
<dl className="grid grid-cols-1 gap-x-[10px] gap-y-2 pl-[36px] md:grid-cols-2 md:gap-y-4">
{Object.entries(settings).map(([key, value]) => (
<KeyValue key={key} label={key} value={JSON.stringify(value)} />
))}
</dl>
</CollapsibleContent>
</CollapsiblePanel>
);
}

function KeyValue({ label, value }: { label: string; value: string | ReactNode }) {
return (
<>
<Key className="col-span-1 text-theme-text-secondary">{label}</Key>
<Value className="col-span-1 w-full truncate text-neutral-700">{value}</Value>
</>
}
/>
);
}
12 changes: 10 additions & 2 deletions src/app/runs/[id]/_Tabs/Overview/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,19 @@ export function Details() {
</Value>
<Key>Start Time</Key>
<Value>
<DisplayDate dateString={data.metadata?.start_time || ""} />
{data.metadata?.start_time ? (
<DisplayDate dateString={data.metadata?.start_time} />
) : (
"Not available"
)}
</Value>
<Key>End Time</Key>
<Value>
<DisplayDate dateString={data.metadata?.end_time || ""} />
{data.metadata?.end_time ? (
<DisplayDate dateString={data.metadata?.end_time} />
) : (
"Not available"
)}
</Value>
</dl>
</CollapsibleContent>
Expand Down
30 changes: 24 additions & 6 deletions src/app/settings/connectors/Fragments.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import ConnectorsVideo from "@/assets/illustrations/connectors-video.svg";
import { InfoBox as InfoBoxPrimitive } from "@/components/Infobox";
import { Box } from "@zenml-io/react-component-library";
import { ConnectorsSelect } from "./ConnectorsSelect";
import { VideoModal } from "@/components/VideoModal";
import { CommandListItem, generateCommandList } from "@/components/fallback-pages/Commands";
import { HelpBox } from "@/components/fallback-pages/Helpbox";
import {
AWSSection,
AzureSection,
Expand All @@ -9,9 +11,9 @@ import {
GCPSection,
KubernetesSection
} from "@/contents/connectors";
import { Box } from "@zenml-io/react-component-library";
import { Fragment, useState } from "react";
import { CommandListItem, generateCommandList } from "@/components/fallback-pages/Commands";
import { HelpBox } from "@/components/fallback-pages/Helpbox";
import { ConnectorsSelect } from "./ConnectorsSelect";

export function InfoBox() {
return (
Expand All @@ -25,14 +27,30 @@ export function InfoBox() {
}

export function HeaderBox() {
const videoLink =
"https://zenml.portal.trainn.co/share/V6magMJZZvMptz1wdnUmPA/embed?autoplay=false";
return (
<Box className="flex flex-col-reverse items-stretch overflow-hidden md:flex-row">
<div className="w-full p-7 md:w-2/3">
<Box className="flex flex-col-reverse items-stretch overflow-hidden lg:flex-row">
<div className="w-full p-7 lg:w-2/3">
<h2 className="text-display-xs font-semibold">Learn More about Connectors</h2>
<p className="mt-2 text-text-lg text-theme-text-secondary">
Dive into Service Connector Types for a documented approach to secure authentication and
authorization practices.
</p>
<VideoModal videoLink={videoLink} buttonText="Watch the Starter Guide (2 min)" />
</div>
<div className="flex w-full items-center justify-center bg-primary-50 lg:w-1/3">
<VideoModal
fallbackImage={
<img
src={ConnectorsVideo}
alt="Purple squares with text indicating a starter guide for secrets"
className="h-full w-full"
/>
}
videoLink={videoLink}
isButton={false}
/>
</div>
</Box>
);
Expand Down
21 changes: 21 additions & 0 deletions src/assets/illustrations/connectors-video.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion src/components/CollapsibleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CollapsibleHeader,
CollapsibleHeaderProps
} from "@zenml-io/react-component-library";
import { cn } from "@zenml-io/react-component-library/utilities";
import ChevronDown from "@/assets/icons/chevron-down.svg?react";
import { useState } from "react";

Expand All @@ -13,6 +14,7 @@ type CollapsibleCardProps = {
children: React.ReactNode;
title: string | React.ReactNode;
className?: string;
contentClassName?: string;
intent?: CollapsibleHeaderProps["intent"];
};

Expand All @@ -21,6 +23,7 @@ export function CollapsibleCard({
children,
initialOpen = false,
className,
contentClassName,
intent = "primary"
}: CollapsibleCardProps) {
const [open, setOpen] = useState(initialOpen);
Expand All @@ -37,7 +40,12 @@ export function CollapsibleCard({
</CollapsibleTrigger>
</CollapsibleHeader>

<CollapsibleContent className="space-y-3 border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3">
<CollapsibleContent
className={cn(
"space-y-3 border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3",
contentClassName
)}
>
{children}
</CollapsibleContent>
</CollapsiblePanel>
Expand Down
3 changes: 3 additions & 0 deletions src/components/MetadataCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export function UncategorizedCard({ metadata }: Props) {

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

// sort nonDicts alphabetically by index 0
nonDicts.sort((a, b) => a[0].localeCompare(b[0]));

const convertToMBorGB = (number: number) => {
if (number < 1024) {
return number + " bytes";
Expand Down
Loading
Loading