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 #675

Merged
merged 10 commits into from
Sep 25, 2024
Merged
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
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -68,7 +68,6 @@ jobs:
tar -zcf zenml-dashboard.tar.gz -C dist --transform="s#\.\/##" .
sha256sum -b zenml-dashboard.tar.gz > zenml-dashboard.tar.gz.sha256


- name: Release to GitHub
uses: softprops/action-gh-release@v1
with:
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@ jobs:

- name: Install project dependencies
run: pnpm install --frozen-lockfile

- name: "Run Build"
run: pnpm build

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -38,8 +38,8 @@
"lodash.debounce": "^4.0.8",
"papaparse": "^5.4.1",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.51.5",
"react-joyride": "^2.8.2",
"react-markdown": "^9.0.1",
@@ -64,7 +64,7 @@
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.5",
"eslint-plugin-react-refresh": "^0.4.6",
"husky": "^9.0.11",
"lint-staged": "^15.2.5",
"openapi-typescript": "^6.7.6",
16 changes: 8 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/app/onboarding/Header.tsx
Original file line number Diff line number Diff line change
@@ -6,8 +6,8 @@ export function HeaderOnboardingBox() {
<div className="w-full px-7 py-5 md:w-2/3">
<h2 className="text-display-xs font-semibold">Welcome to ZenML</h2>
<p className="mt-2 text-text-lg text-theme-text-secondary">
You successfully installed the ZenML dashboard. Now you can get started with your new ZenML
server.
You successfully installed the ZenML dashboard. Now you can get started with your new
ZenML server.
</p>
</div>
{/* <div className="flex w-full flex-1 items-center justify-center bg-primary-50 md:w-1/3"></div> */}
9 changes: 7 additions & 2 deletions src/app/pipelines/PipelinesTab/DeletePipelineAlert.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Trash from "@/assets/icons/trash.svg?react";
import { DeleteAlertContent } from "@/components/DeleteAlertDialog";
import { DeleteAlertContent, DeleteAlertContentBody } from "@/components/DeleteAlertDialog";
import { AlertDialog, AlertDialogTrigger, Button } from "@zenml-io/react-component-library";
import { useState } from "react";
import { usePipelinesSelectorContext } from "./PipelineSelectorContext";
@@ -29,7 +29,12 @@ export function DeletePipelineAlert() {
<DeleteAlertContent
title={`Delete Pipeline${selectedPipelines.length >= 2 ? "s" : ""}`}
handleDelete={handleDelete}
/>
>
<DeleteAlertContentBody>
<p>Are you sure?</p>
<p>This action cannot be undone.</p>
</DeleteAlertContentBody>
</DeleteAlertContent>
</AlertDialog>
);
}
9 changes: 7 additions & 2 deletions src/app/pipelines/PipelinesTab/PipelineDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DotsIcon from "@/assets/icons/dots-horizontal.svg?react";
import Trash from "@/assets/icons/trash.svg?react";
import { AlertDialogItem } from "@/components/AlertDialogDropdownItem";
import { DeleteAlertContent } from "@/components/DeleteAlertDialog";
import { DeleteAlertContent, DeleteAlertContentBody } from "@/components/DeleteAlertDialog";
import {
AlertDialogTrigger,
DropdownMenu,
@@ -67,7 +67,12 @@ export function PipelineDropdown({ id }: Props) {
triggerChildren="Delete"
icon={<Trash fill="red" />}
>
<DeleteAlertContent title="Delete Pipeline" handleDelete={handleDelete} />
<DeleteAlertContent title="Delete Pipeline" handleDelete={handleDelete}>
<DeleteAlertContentBody>
<p>Are you sure?</p>
<p>This action cannot be undone.</p>
</DeleteAlertContentBody>
</DeleteAlertContent>
</AlertDialogItem>
</DropdownMenuContent>
</DropdownMenu>
9 changes: 7 additions & 2 deletions src/app/pipelines/RunsTab/DeleteRunAlert.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Trash from "@/assets/icons/trash.svg?react";
import { DeleteAlertContent } from "@/components/DeleteAlertDialog";
import { DeleteAlertContent, DeleteAlertContentBody } from "@/components/DeleteAlertDialog";
import { AlertDialog, AlertDialogTrigger, Button } from "@zenml-io/react-component-library";
import { useState } from "react";
import { useRunsSelectorContext } from "./RunsSelectorContext";
@@ -29,7 +29,12 @@ export function DeleteRunAlert() {
<DeleteAlertContent
title={`Delete Run${selectedRuns.length >= 2 ? "s" : ""}`}
handleDelete={handleDelete}
/>
>
<DeleteAlertContentBody>
<p>Are you sure?</p>
<p>This action cannot be undone.</p>
</DeleteAlertContentBody>
</DeleteAlertContent>
</AlertDialog>
);
}
9 changes: 7 additions & 2 deletions src/app/pipelines/RunsTab/RunDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DotsIcon from "@/assets/icons/dots-horizontal.svg?react";
import Trash from "@/assets/icons/trash.svg?react";
import { AlertDialogItem } from "@/components/AlertDialogDropdownItem";
import { DeleteAlertContent } from "@/components/DeleteAlertDialog";
import { DeleteAlertContent, DeleteAlertContentBody } from "@/components/DeleteAlertDialog";
import {
AlertDialogTrigger,
DropdownMenu,
@@ -68,7 +68,12 @@ export function RunDropdown({ id }: Props) {
triggerChildren="Delete"
icon={<Trash fill="red" />}
>
<DeleteAlertContent title="Delete Run" handleDelete={handleDelete} />
<DeleteAlertContent title="Delete Run" handleDelete={handleDelete}>
<DeleteAlertContentBody>
<p>Are you sure?</p>
<p>This action cannot be undone.</p>
</DeleteAlertContentBody>
</DeleteAlertContent>
</AlertDialogItem>
</DropdownMenuContent>
</DropdownMenu>
80 changes: 27 additions & 53 deletions src/app/runs/[id]/Dag.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,39 @@
import AlertCircle from "@/assets/icons/alert-circle.svg?react";

import { ArtifactNode } from "@/components/dag-visualizer/ArtifactNode";
import { DagControls } from "@/components/dag-visualizer/Controls";
import { PreviewArtifactNode } from "@/components/dag-visualizer/PreviewArtifact";
import { PreviewStepNode } from "@/components/dag-visualizer/PreviewStep";
import { SmoothStepSmart } from "@/components/dag-visualizer/SmartEdge";
import { StepNode } from "@/components/dag-visualizer/StepNode";
import { getLayoutedNodes } from "@/components/dag-visualizer/layout";
import { usePipelineRunGraph } from "@/data/pipeline-runs/pipeline-run-graph-query";
import { Spinner } from "@zenml-io/react-component-library";
import { useCallback, useEffect, useLayoutEffect } from "react";
import { useParams } from "react-router-dom";
import ReactFlow, {
NodeTypes,
useEdgesState,
useNodesState,
useReactFlow,
useStore
} from "reactflow";
import { DagControls } from "@/components/dag-visualizer/Controls";
import { EmptyState } from "@/components/EmptyState";
import { Spinner } from "@zenml-io/react-component-library/components/server";
import ReactFlow, { NodeTypes } from "reactflow";
import { useDag } from "./useDag";

const customNodes: NodeTypes = {
step: StepNode,
artifact: ArtifactNode
artifact: ArtifactNode,
previewStep: PreviewStepNode,
previewArtifact: PreviewArtifactNode
};

const customEdge = {
smart: SmoothStepSmart
};

export function DAG() {
const { runId } = useParams() as { runId: string };
const { data, isPending, isError } = usePipelineRunGraph({ runId });

const { fitView } = useReactFlow();
const { width, height } = useStore((state) => ({ width: state.width, height: state.height }));

const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);

const onDagreLayout = useCallback(() => {
const layouted = getLayoutedNodes(data?.nodes, data?.edges);

setNodes([...layouted.nodes]);
setEdges([...layouted.edges]);
const { pipelineDeployment, pipelineRun, nodes, edges, onEdgesChange, onNodesChange } = useDag();

window.requestAnimationFrame(() => {
fitView();
});
}, [data?.nodes, data?.edges]);

useEffect(() => {
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]);

if (isError) return null;
if (pipelineRun.isError || pipelineDeployment.isError) {
return (
<EmptyState icon={<AlertCircle className="h-[120px] w-[120px] fill-neutral-300" />}>
<p className="text-center">There was an error loading the DAG visualization.</p>
</EmptyState>
);
}

if (isPending) {
if (pipelineRun.isPending || pipelineDeployment.isPending) {
return (
<div className="flex h-full flex-col items-center justify-center">
<Spinner />
@@ -91,7 +60,12 @@ export function DAG() {
onEdgesChange={onEdgesChange}
fitView
>
<DagControls runId={runId} />
<DagControls
refetch={() => {
pipelineRun.refetch();
pipelineDeployment.refetch();
}}
/>
</ReactFlow>
);
}
61 changes: 61 additions & 0 deletions src/app/runs/[id]/DeleteRunAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import AlertCircle from "@/assets/icons/alert-circle.svg?react";
import Tick from "@/assets/icons/tick-circle.svg?react";
import { useQueryClient } from "@tanstack/react-query";
import { AlertDialog, useToast } from "@zenml-io/react-component-library";
import { useNavigate, useParams } from "react-router-dom";
import { DeleteAlertContent, DeleteAlertContentBody } from "../../../components/DeleteAlertDialog";
import { useDeleteRun } from "../../../data/pipeline-runs/delete-run";
import { routes } from "../../../router/routes";

type Props = {
open: boolean;
setOpen: (bool: boolean) => void;
};

export function DeleteRunAlert({ open, setOpen }: Props) {
const { toast } = useToast();
const navigate = useNavigate();
const queryClient = useQueryClient();
const { runId } = useParams() as { runId: string };
const { mutate } = useDeleteRun({
onSuccess: async () => {
queryClient.invalidateQueries({ queryKey: ["runs"] });
toast({
status: "success",
emphasis: "subtle",
icon: <Tick className="h-5 w-5 shrink-0 fill-success-700" />,
description: "Run deleted successfully",
rounded: true
});
setOpen(false);
navigate(routes.pipelines.overview);
},
onError: (e) => {
toast({
status: "error",
emphasis: "subtle",
icon: <AlertCircle className="h-5 w-5 shrink-0 fill-error-700" />,
description: e.message,
rounded: true
});
}
});
async function handleDelete() {
mutate({ runId });
}

return (
<AlertDialog open={open} onOpenChange={setOpen}>
<DeleteAlertContent title={`Delete Run`} handleDelete={() => handleDelete()}>
<DeleteAlertContentBody>
<p>Are you sure?</p>
<p>This action cannot be undone.</p>
<p>
Deleting a run here does not guarantee that this run will get deleted in the underlying
orchestrator.
</p>
</DeleteAlertContentBody>
</DeleteAlertContent>
</AlertDialog>
);
}
6 changes: 4 additions & 2 deletions src/app/runs/[id]/Header.tsx
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import { useBreadcrumbsContext } from "@/layouts/AuthenticatedLayout/Breadcrumbs
import { Skeleton } from "@zenml-io/react-component-library";
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { RunActionsMenu } from "./RunActionMenu";

export function RunsDetailHeader() {
const { runId } = useParams() as { runId: string };
@@ -23,8 +24,8 @@ export function RunsDetailHeader() {
}, [data]);

return (
<PageHeader>
<div className="flex items-center gap-1">
<PageHeader className="flex items-center justify-between">
<div className="flex items-center gap-1 truncate">
{isSuccess ? (
<>
<RunIcon
@@ -41,6 +42,7 @@ export function RunsDetailHeader() {
</>
)}
</div>
<RunActionsMenu />
</PageHeader>
);
}
Loading