Skip to content

Commit e386f46

Browse files
Merge pull request #740 from zenml-io/staging
Release
2 parents 3bc2631 + 36636a7 commit e386f46

File tree

43 files changed

+598
-236
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+598
-236
lines changed

src/app/components/columns.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { ComponentSheet } from "@/components/stack-components/component-sheet";
55
import { ComponentBadge } from "@/components/stack-components/ComponentBadge";
66
import { snakeCaseToTitleCase } from "@/lib/strings";
77
import { sanitizeUrl } from "@/lib/url";
8-
import { getUsername } from "@/lib/user";
98
import { StackComponent } from "@/types/components";
109
import { ColumnDef } from "@tanstack/react-table";
1110
import { Tag } from "@zenml-io/react-component-library/components/server";
@@ -88,9 +87,9 @@ export function getComponentList(): ColumnDef<StackComponent>[] {
8887
header: "Author",
8988
accessorFn: (row) => row.body?.user?.name,
9089
cell: ({ row }) => {
91-
const author = row.original.body?.user;
90+
const author = row.original.body?.user?.name;
9291
if (!author) return null;
93-
return <InlineAvatar username={getUsername(author)} />;
92+
return <InlineAvatar username={author} />;
9493
}
9594
},
9695
{

src/app/pipelines/PipelinesTab/DeletePipelineAlert.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ export function DeletePipelineAlert() {
1515

1616
return (
1717
<AlertDialog open={isOpen} onOpenChange={setIsOpen}>
18-
<AlertDialogTrigger>
18+
<AlertDialogTrigger asChild>
1919
<Button
20-
className="rounded-sharp border-none bg-white"
20+
className="rounded-sharp border-y-0 bg-white"
2121
size="md"
2222
emphasis="subtle"
2323
intent="secondary"

src/app/pipelines/RunsTab/DeleteRunAlert.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ export function DeleteRunAlert() {
1515

1616
return (
1717
<AlertDialog open={isOpen} onOpenChange={setIsOpen}>
18-
<AlertDialogTrigger>
18+
<AlertDialogTrigger asChild>
1919
<Button
20-
className="rounded-sharp border-none bg-white"
20+
className="rounded-sharp border-y-0 bg-white"
2121
size="md"
2222
emphasis="subtle"
2323
intent="secondary"

src/app/pipelines/RunsTab/columns.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,15 @@ export const runsColumns: ColumnDef<PipelineRun>[] = [
137137
id: "author",
138138
header: "Author",
139139
accessorFn: (row) => ({
140-
name: row.body?.user?.body?.full_name || row.body?.user?.name
140+
name: row.body?.user?.name
141141
}),
142142
cell: ({ getValue }) => {
143143
const { name } = getValue<{
144-
name: string;
144+
name?: string;
145145
}>();
146146

147+
if (!name) return null;
148+
147149
return <InlineAvatar username={name} />;
148150
}
149151
},

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Skeleton } from "@zenml-io/react-component-library";
77
import { useEffect } from "react";
88
import { useParams } from "react-router-dom";
99
import { RunActionsMenu } from "./RunActionMenu";
10+
import { RunRefreshGroup } from "@/components/runs/refresh-group";
1011

1112
export function RunsDetailHeader() {
1213
const { runId } = useParams() as { runId: string };
@@ -42,7 +43,10 @@ export function RunsDetailHeader() {
4243
</>
4344
)}
4445
</div>
45-
<RunActionsMenu />
46+
<div className="flex items-center gap-1">
47+
<RunRefreshGroup runId={runId} />
48+
<RunActionsMenu />
49+
</div>
4650
</PageHeader>
4751
);
4852
}

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import HorizontalDots from "@/assets/icons/dots-horizontal.svg?react";
22
import Trash from "@/assets/icons/trash.svg?react";
33
import {
4+
Button,
45
DropdownMenu,
56
DropdownMenuContent,
67
DropdownMenuItem,
@@ -19,9 +20,16 @@ export function RunActionsMenu() {
1920
<DeleteRunAlert setOpen={setDeleteOpen} open={deleteOpen} />
2021
<DropdownMenu modal={dropdownOpen} open={dropdownOpen} onOpenChange={setDropdownOpen}>
2122
<DropdownMenu>
22-
<DropdownMenuTrigger className="z-10">
23-
<HorizontalDots className="h-5 w-5 shrink-0 fill-theme-text-secondary" />
24-
<p className="sr-only">Run Actions</p>
23+
<DropdownMenuTrigger asChild>
24+
<Button
25+
intent="secondary"
26+
className="flex aspect-square items-center justify-center p-0"
27+
emphasis="minimal"
28+
size="md"
29+
>
30+
<HorizontalDots className="h-5 w-5 shrink-0 fill-theme-text-secondary" />
31+
<p className="sr-only">Run Actions</p>
32+
</Button>
2533
</DropdownMenuTrigger>
2634
<DropdownMenuContent className="z-10" align="end" sideOffset={1}>
2735
<DropdownMenuItem onClick={() => setDeleteOpen(true)} className="space-x-2">

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

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,29 @@ import {
55
CollapsibleContent,
66
CollapsibleHeader,
77
CollapsiblePanel,
8-
CollapsibleTrigger
8+
CollapsibleTrigger,
9+
Tooltip,
10+
TooltipContent,
11+
TooltipProvider,
12+
TooltipTrigger
913
} from "@zenml-io/react-component-library";
1014
import { useState } from "react";
1115

1216
type Props = {
1317
run: PipelineRun;
1418
};
1519

20+
const PYTHON_PACKAGES_KEY = "python_packages";
21+
1622
export function EnvironmentCollapsible({ run }: Props) {
1723
const [open, setOpen] = useState(true);
1824

25+
const executionEnvironment = run.metadata?.orchestrator_environment;
26+
const clientEnvironment = run.metadata?.client_environment;
27+
28+
const normalizedExecutionEnvironment = normalizePythonPackages(executionEnvironment ?? {});
29+
const normalizedClientEnvironment = normalizePythonPackages(clientEnvironment ?? {});
30+
1931
return (
2032
<CollapsiblePanel open={open} onOpenChange={setOpen}>
2133
<CollapsibleHeader intent="primary" className="flex items-center gap-[10px]">
@@ -32,16 +44,65 @@ export function EnvironmentCollapsible({ run }: Props) {
3244
<NestedCollapsible
3345
isInitialOpen
3446
intent="secondary"
35-
title="Client Environment"
36-
data={run.metadata?.client_environment}
47+
title={
48+
<TooltipProvider>
49+
<Tooltip>
50+
<TooltipTrigger asChild>
51+
<span>Client Environment</span>
52+
</TooltipTrigger>
53+
<TooltipContent className="max-w-[200px] whitespace-normal xl:max-w-[300px]">
54+
Environment where you start your pipeline run by calling the pipeline function.{" "}
55+
<a
56+
rel="noopener noreferrer"
57+
className="link"
58+
href="https://docs.zenml.io/user-guides/best-practices/configure-python-environments#client-environment-or-the-runner-environment"
59+
target="_blank"
60+
>
61+
Learn more about client environments
62+
</a>
63+
</TooltipContent>
64+
</Tooltip>
65+
</TooltipProvider>
66+
}
67+
data={normalizedClientEnvironment}
3768
/>
3869
<NestedCollapsible
3970
isInitialOpen
4071
intent="secondary"
41-
title="Orchestrator Environment"
42-
data={run.metadata?.orchestrator_environment}
72+
title={
73+
<TooltipProvider>
74+
<Tooltip>
75+
<TooltipTrigger asChild>
76+
<span>Execution Environment</span>
77+
</TooltipTrigger>
78+
<TooltipContent className="max-w-[200px] whitespace-normal xl:max-w-[300px]">
79+
Environment where your ZenML steps get executed.{" "}
80+
<a
81+
rel="noopener noreferrer"
82+
className="link"
83+
href="https://docs.zenml.io/user-guides/best-practices/configure-python-environments#execution-environments"
84+
target="_blank"
85+
>
86+
Learn more about exectuion environments
87+
</a>
88+
</TooltipContent>
89+
</Tooltip>
90+
</TooltipProvider>
91+
}
92+
data={normalizedExecutionEnvironment}
4393
/>
4494
</CollapsibleContent>
4595
</CollapsiblePanel>
4696
);
4797
}
98+
99+
function normalizePythonPackages(env: Record<string, unknown>) {
100+
const pythonPackages = env[PYTHON_PACKAGES_KEY];
101+
if (typeof pythonPackages === "string") {
102+
return {
103+
...env,
104+
[PYTHON_PACKAGES_KEY]: pythonPackages.split("\n").map((pkg) => pkg.trim())
105+
};
106+
}
107+
return env;
108+
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ChevronDown from "@/assets/icons/chevron-down.svg?react";
22
import { NestedCollapsible } from "@/components/NestedCollapsible";
3+
import { NotAvailable } from "@/components/not-available";
34
import { pipelineDeploymentQueries } from "@/data/pipeline-deployments";
45
import { useQuery } from "@tanstack/react-query";
56
import {
@@ -37,7 +38,7 @@ export function PipelineParamsCollapsible({ deploymentId }: Props) {
3738
Pipeline Parameters
3839
</CollapsibleHeader>
3940
<CollapsibleContent className="border-t border-theme-border-moderate bg-theme-surface-primary px-5 py-3">
40-
Not available
41+
<NotAvailable />
4142
</CollapsibleContent>
4243
</CollapsiblePanel>
4344
);

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import { PipelineParamsCollapsible } from "./ParameterCollapsible";
1111

1212
export function ConfigurationTab() {
1313
const { runId } = useParams() as { runId: string };
14-
const { data, isError, isPending } = usePipelineRun({ runId: runId }, { throwOnError: true });
14+
const { data, isError, isPending } = usePipelineRun(
15+
{ runId: runId, queryParams: { include_python_packages: true } },
16+
{ throwOnError: true }
17+
);
1518
const { data: buildData } = usePipelineBuild(
1619
{
1720
buildId: data?.body?.build?.id as string

src/app/settings/members/columns.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { DisplayDate } from "@/components/DisplayDate";
22
import { InlineAvatar } from "@/components/InlineAvatar";
3-
import { getUsername } from "@/lib/user";
43
import { User, UserBody } from "@/types/user";
54
import { ColumnDef } from "@tanstack/react-table";
65
import { Badge } from "@zenml-io/react-component-library";
@@ -71,7 +70,7 @@ export function columns({ isAdmin }: Props): ColumnDef<User>[] {
7170
header: "",
7271
accessorFn: (row) => ({
7372
id: row.id,
74-
name: getUsername(row)
73+
name: row.name
7574
}),
7675
meta: {
7776
width: "5%"

src/app/settings/page.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1+
import { InlineAvatar } from "@/components/InlineAvatar";
12
import { useCurrentUser } from "@/data/users/current-user-query";
3+
import { Skeleton } from "@zenml-io/react-component-library";
24
import { Outlet } from "react-router-dom";
35
import { DisplayServer, ProfileSettingsMenu, ServerSettingsMenu } from "./LayoutSidebar";
4-
import { InlineAvatar } from "@/components/InlineAvatar";
56
import { VersionDisplay } from "./VersionDisplay";
6-
import { getUsername } from "@/lib/user";
7-
import { Skeleton } from "@zenml-io/react-component-library";
87

98
export default function SettingsPage() {
109
const { data } = useCurrentUser();
@@ -20,7 +19,7 @@ export default function SettingsPage() {
2019
{data ? (
2120
<div className="flex flex-col gap-4">
2221
<p className="text-text-xs font-semibold uppercase text-theme-text-tertiary">Account</p>
23-
<InlineAvatar username={getUsername(data)} />
22+
<InlineAvatar username={data.name} />
2423
</div>
2524
) : (
2625
<Skeleton className="h-[70px] w-full" />

src/app/settings/profile/page.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Avatar, AvatarFallback, Box, Skeleton } from "@zenml-io/react-component-library";
22
import { UpdateProfileForm } from "./UpdateProfileForm";
33
import { useCurrentUser } from "@/data/users/current-user-query";
4-
import { getUsername } from "@/lib/user";
54

65
export default function ProfilePage() {
76
const { data: user } = useCurrentUser();
@@ -15,7 +14,7 @@ export default function ProfilePage() {
1514
{user ? (
1615
<Avatar size="xxl" className="ml-5 h-[140px] w-[140px]" type="rounded">
1716
<AvatarFallback className="text-display-lg" size="xxl">
18-
{getUsername(user)[0]}
17+
{user.name[0]}
1918
</AvatarFallback>
2019
</Avatar>
2120
) : (

src/app/settings/secrets/columns.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ import { CopyButton } from "@/components/CopyButton";
33
import { DisplayDate } from "@/components/DisplayDate";
44
import { InlineAvatar } from "@/components/InlineAvatar";
55
import { getSecretSnippet } from "@/lib/code-snippets";
6-
import { getUsername } from "@/lib/user";
76
import { routes } from "@/router/routes";
87
import { SecretNamespace } from "@/types/secret";
9-
import { User } from "@/types/user";
108
import { ColumnDef } from "@tanstack/react-table";
119
import { Link } from "react-router-dom";
1210
import SecretsDropdown from "./SecretsDropdown";
@@ -54,14 +52,11 @@ export const secretsColumns: ColumnDef<SecretNamespace>[] = [
5452
{
5553
id: "author",
5654
header: "Author",
57-
accessorFn: (row) => row.body?.user,
55+
accessorFn: (row) => row.body?.user?.name,
5856
cell: ({ getValue }) => {
59-
const user = getValue<User>();
60-
return (
61-
<>
62-
<InlineAvatar username={getUsername(user)} />
63-
</>
64-
);
57+
const name = getValue<string>();
58+
if (!name) return null;
59+
return <InlineAvatar username={name} />;
6560
}
6661
},
6762
{

src/app/settings/service-accounts/DeleteAlert.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function DeleteServiceAccountAlert() {
2121
<AlertDialog open={isOpen} onOpenChange={setIsOpen}>
2222
<AlertDialogTrigger asChild>
2323
<Button
24-
className="rounded-sharp border-none bg-white"
24+
className="rounded-sharp border-y-0 bg-white"
2525
size="md"
2626
emphasis="subtle"
2727
intent="secondary"

src/app/settings/service-accounts/[service-account-id]/DeleteApiKeyDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function DeleteApiKey({ serviceAccountId }: { serviceAccountId: string })
2121
<AlertDialog open={isOpen} onOpenChange={setIsOpen}>
2222
<AlertDialogTrigger asChild>
2323
<Button
24-
className="rounded-sharp border-none bg-white"
24+
className="rounded-sharp border-y-0 bg-white"
2525
size="md"
2626
emphasis="subtle"
2727
intent="secondary"

src/app/stacks/columns.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ import { CopyButton } from "@/components/CopyButton";
22
import { DisplayDate } from "@/components/DisplayDate";
33
import { InlineAvatar } from "@/components/InlineAvatar";
44
import { StackSheet } from "@/components/stacks/Sheet";
5-
import { getUsername } from "@/lib/user";
65
import { Stack } from "@/types/stack";
7-
import { User } from "@/types/user";
86
import { ColumnDef } from "@tanstack/react-table";
97
import { Avatar, AvatarFallback } from "@zenml-io/react-component-library";
108
import { useMemo } from "react";
@@ -52,11 +50,11 @@ export function useStackColumns(): ColumnDef<Stack>[] {
5250
{
5351
id: "author",
5452
header: "Author",
55-
accessorFn: (row) => ({ author: row.body?.user }),
53+
accessorFn: (row) => ({ author: row.body?.user?.name }),
5654
cell: ({ getValue }) => {
57-
const { author } = getValue<{ author?: User }>();
55+
const { author } = getValue<{ author?: string }>();
5856
if (!author) return null;
59-
return <InlineAvatar username={getUsername(author)} />;
57+
return <InlineAvatar username={author} />;
6058
}
6159
},
6260
{

src/app/stacks/create/components/sharedSchema.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@ export const stackNameSchema = z
55
.string()
66
.trim()
77
.min(1, "Stack name is required")
8-
.max(32, "Stack name must be less than 32 characters")
9-
.regex(/^[a-zA-Z0-9-]+$/, "Stack name can only contain alphanumeric characters and hyphens")
8+
.max(255, "Stack name must be less than 255 characters")
109
.refine((name) => validateStackName(name), "Stack name is already in use");

0 commit comments

Comments
 (0)