Skip to content

Commit 22759e3

Browse files
committed
Refactor change workspace version
1 parent 496473f commit 22759e3

File tree

9 files changed

+177
-163
lines changed

9 files changed

+177
-163
lines changed

site/src/api/queries/templates.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,14 @@ export const templateVersionByName = (
139139
};
140140
};
141141

142+
export const templateVersionsQueryKey = (templateId: string) => [
143+
"templateVersions",
144+
templateId,
145+
];
146+
142147
export const templateVersions = (templateId: string) => {
143148
return {
144-
queryKey: ["templateVersions", templateId],
149+
queryKey: templateVersionsQueryKey(templateId),
145150
queryFn: () => API.getTemplateVersions(templateId),
146151
};
147152
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { Meta, StoryObj } from "@storybook/react";
2+
import {
3+
MockTemplate,
4+
MockTemplateVersion,
5+
MockTemplateVersionWithMarkdownMessage,
6+
MockWorkspace,
7+
} from "testHelpers/entities";
8+
import { ChangeWorkspaceVersionDialog } from "./ChangeWorkspaceVersionDialog";
9+
import { templateVersionsQueryKey } from "api/queries/templates";
10+
11+
const noMessage = {
12+
...MockTemplateVersion,
13+
id: "no-message",
14+
message: "",
15+
};
16+
17+
const meta: Meta<typeof ChangeWorkspaceVersionDialog> = {
18+
title: "modules/workspaces/ChangeWorkspaceVersionDialog",
19+
component: ChangeWorkspaceVersionDialog,
20+
args: {
21+
open: true,
22+
workspace: MockWorkspace,
23+
},
24+
parameters: {
25+
queries: [
26+
{
27+
key: templateVersionsQueryKey(MockWorkspace.template_id),
28+
data: [
29+
MockTemplateVersion,
30+
MockTemplateVersionWithMarkdownMessage,
31+
noMessage,
32+
],
33+
},
34+
],
35+
},
36+
};
37+
38+
export default meta;
39+
type Story = StoryObj<typeof ChangeWorkspaceVersionDialog>;
40+
41+
export const NoVersionSelected: Story = {};
42+
43+
export const NoMessage: Story = {
44+
args: {
45+
workspace: {
46+
...MockWorkspace,
47+
template_active_version_id: noMessage.id,
48+
},
49+
},
50+
};
51+
52+
export const ShortMessage: Story = {
53+
args: {
54+
workspace: {
55+
...MockWorkspace,
56+
template_active_version_id: MockTemplateVersion.id,
57+
},
58+
},
59+
};
60+
61+
export const LongMessage: Story = {
62+
args: {
63+
workspace: {
64+
...MockWorkspace,
65+
template_active_version_id: MockTemplateVersionWithMarkdownMessage.id,
66+
},
67+
},
68+
};

site/src/pages/WorkspacePage/ChangeVersionDialog.tsx renamed to site/src/modules/workspaces/WorkspaceMoreActions/ChangeWorkspaceVersionDialog.tsx

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import AlertTitle from "@mui/material/AlertTitle";
33
import Autocomplete from "@mui/material/Autocomplete";
44
import CircularProgress from "@mui/material/CircularProgress";
55
import TextField from "@mui/material/TextField";
6-
import type { Template, TemplateVersion } from "api/typesGenerated";
6+
import { templateVersions } from "api/queries/templates";
7+
import type { TemplateVersion, Workspace } from "api/typesGenerated";
78
import { Alert } from "components/Alert/Alert";
89
import { Avatar } from "components/Avatar/Avatar";
910
import { AvatarData } from "components/Avatar/AvatarData";
@@ -15,41 +16,40 @@ import { Pill } from "components/Pill/Pill";
1516
import { Stack } from "components/Stack/Stack";
1617
import { InfoIcon } from "lucide-react";
1718
import { TemplateUpdateMessage } from "modules/templates/TemplateUpdateMessage";
18-
import { type FC, useRef, useState } from "react";
19+
import { type FC, useEffect, useState } from "react";
20+
import { useQuery } from "react-query";
1921
import { createDayString } from "utils/createDayString";
2022

21-
export type ChangeVersionDialogProps = DialogProps & {
22-
template: Template | undefined;
23-
templateVersions: TemplateVersion[] | undefined;
24-
defaultTemplateVersion: TemplateVersion | undefined;
23+
export type ChangeWorkspaceVersionDialogProps = DialogProps & {
24+
workspace: Workspace;
2525
onClose: () => void;
26-
onConfirm: (templateVersion: TemplateVersion) => void;
26+
onConfirm: (version: TemplateVersion) => void;
2727
};
2828

29-
export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
30-
onConfirm,
31-
onClose,
32-
template,
33-
templateVersions,
34-
defaultTemplateVersion,
35-
...dialogProps
36-
}) => {
29+
export const ChangeWorkspaceVersionDialog: FC<
30+
ChangeWorkspaceVersionDialogProps
31+
> = ({ workspace, onClose, onConfirm, ...dialogProps }) => {
32+
const { data: versions } = useQuery(templateVersions(workspace.template_id));
3733
const [isAutocompleteOpen, setIsAutocompleteOpen] = useState(false);
38-
const selectedTemplateVersion = useRef<TemplateVersion | undefined>(
39-
defaultTemplateVersion,
34+
const activeVersion = versions?.find(
35+
(v) => workspace.template_active_version_id === v.id,
4036
);
41-
const version = selectedTemplateVersion.current;
42-
const validTemplateVersions = templateVersions?.filter((version) => {
43-
return version.job.status === "succeeded";
44-
});
37+
const [selectedVersion, setSelectedVersion] = useState<TemplateVersion>();
38+
const validVersions = versions?.filter((v) => v.job.status === "succeeded");
39+
40+
useEffect(() => {
41+
if (activeVersion) {
42+
setSelectedVersion(activeVersion);
43+
}
44+
}, [activeVersion]);
4545

4646
return (
4747
<ConfirmDialog
4848
{...dialogProps}
4949
onClose={onClose}
5050
onConfirm={() => {
51-
if (selectedTemplateVersion.current) {
52-
onConfirm(selectedTemplateVersion.current);
51+
if (selectedVersion) {
52+
onConfirm(selectedVersion);
5353
}
5454
}}
5555
hideCancel={false}
@@ -60,18 +60,17 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
6060
description={
6161
<Stack>
6262
<p>You are about to change the version of this workspace.</p>
63-
{validTemplateVersions ? (
63+
{validVersions ? (
6464
<>
6565
<FormFields>
6666
<Autocomplete
6767
disableClearable
68-
options={validTemplateVersions}
69-
defaultValue={defaultTemplateVersion}
68+
options={validVersions}
69+
defaultValue={activeVersion}
7070
id="template-version-autocomplete"
7171
open={isAutocompleteOpen}
7272
onChange={(_, newTemplateVersion) => {
73-
selectedTemplateVersion.current =
74-
newTemplateVersion ?? undefined;
73+
setSelectedVersion(newTemplateVersion);
7574
}}
7675
onOpen={() => {
7776
setIsAutocompleteOpen(true);
@@ -112,9 +111,8 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
112111
/>
113112
)}
114113
</Stack>
115-
{template?.active_version_id === option.id && (
116-
<Pill type="success">Active</Pill>
117-
)}
114+
{workspace.template_active_version_id ===
115+
option.id && <Pill type="success">Active</Pill>}
118116
</Stack>
119117
}
120118
subtitle={createDayString(option.created_at)}
@@ -131,9 +129,7 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
131129
...params.InputProps,
132130
endAdornment: (
133131
<>
134-
{!templateVersions ? (
135-
<CircularProgress size={16} />
136-
) : null}
132+
{!versions && <CircularProgress size={16} />}
137133
{params.InputProps.endAdornment}
138134
</>
139135
),
@@ -144,16 +140,16 @@ export const ChangeVersionDialog: FC<ChangeVersionDialogProps> = ({
144140
)}
145141
/>
146142
</FormFields>
147-
{version && (
143+
{selectedVersion && (
148144
<>
149-
{version.message && (
145+
{selectedVersion.message && (
150146
<TemplateUpdateMessage>
151-
{version.message}
147+
{selectedVersion.message}
152148
</TemplateUpdateMessage>
153149
)}
154150
<Alert severity="info">
155151
<AlertTitle>
156-
Published by {version.created_by.username}
152+
Published by {selectedVersion.created_by.username}
157153
</AlertTitle>
158154
</Alert>
159155
</>

site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { MissingBuildParameters } from "api/api";
2+
import { changeVersion } from "api/queries/workspaces";
3+
import type { Workspace } from "api/typesGenerated";
14
import { Button } from "components/Button/Button";
25
import {
36
DropdownMenu,
@@ -14,31 +17,42 @@ import {
1417
CopyIcon,
1518
DownloadIcon,
1619
} from "lucide-react";
20+
import { UpdateBuildParametersDialog } from "pages/WorkspacePage/UpdateBuildParametersDialog";
21+
import { DownloadLogsDialog } from "pages/WorkspacePage/WorkspaceActions/DownloadLogsDialog";
1722
import { useState, type FC } from "react";
23+
import { useMutation, useQueryClient } from "react-query";
1824
import { Link as RouterLink } from "react-router-dom";
25+
import { ChangeWorkspaceVersionDialog } from "./ChangeWorkspaceVersionDialog";
1926

2027
type WorkspaceMoreActionsProps = {
28+
workspace: Workspace;
2129
isDuplicationReady: boolean;
2230
disabled?: boolean;
23-
onDuplicate: () => void;
24-
onDelete: () => void;
25-
onChangeVersion?: () => void;
2631
permissions?: {
2732
changeWorkspaceVersion?: boolean;
2833
};
34+
onDuplicate: () => void;
35+
onDelete: () => void;
2936
};
3037

3138
export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
39+
workspace,
3240
disabled,
41+
permissions,
3342
isDuplicationReady,
3443
onDuplicate,
3544
onDelete,
36-
onChangeVersion,
37-
permissions,
3845
}) => {
46+
const queryClient = useQueryClient();
47+
3948
// Download logs
4049
const [isDownloadDialogOpen, setIsDownloadDialogOpen] = useState(false);
41-
const canChangeVersion = permissions?.changeWorkspaceVersion !== false;
50+
51+
// Change version
52+
const [changeVersionDialogOpen, setChangeVersionDialogOpen] = useState(false);
53+
const changeVersionMutation = useMutation(
54+
changeVersion(workspace, queryClient),
55+
);
4256

4357
return (
4458
<>
@@ -64,8 +78,12 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
6478
</RouterLink>
6579
</DropdownMenuItem>
6680

67-
{onChangeVersion && canChangeVersion && (
68-
<DropdownMenuItem onClick={onChangeVersion}>
81+
{permissions?.changeWorkspaceVersion && (
82+
<DropdownMenuItem
83+
onClick={() => {
84+
setChangeVersionDialogOpen(true);
85+
}}
86+
>
6987
<HistoryIcon />
7088
Change version&hellip;
7189
</DropdownMenuItem>
@@ -96,6 +114,48 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
96114
</DropdownMenuItem>
97115
</DropdownMenuContent>
98116
</DropdownMenu>
117+
118+
<DownloadLogsDialog
119+
workspace={workspace}
120+
open={isDownloadDialogOpen}
121+
onClose={() => setIsDownloadDialogOpen(false)}
122+
/>
123+
124+
<UpdateBuildParametersDialog
125+
missedParameters={
126+
isMissingBuildParameters(changeVersionMutation.error)
127+
? changeVersionMutation.error.parameters
128+
: []
129+
}
130+
open={isMissingBuildParameters(changeVersionMutation.error)}
131+
onClose={() => {
132+
changeVersionMutation.reset();
133+
}}
134+
onUpdate={(buildParameters) => {
135+
if (isMissingBuildParameters(changeVersionMutation.error)) {
136+
changeVersionMutation.mutate({
137+
versionId: changeVersionMutation.error.versionId,
138+
buildParameters,
139+
});
140+
}
141+
}}
142+
/>
143+
144+
<ChangeWorkspaceVersionDialog
145+
workspace={workspace}
146+
open={changeVersionDialogOpen}
147+
onClose={() => {
148+
setChangeVersionDialogOpen(false);
149+
}}
150+
onConfirm={(version) => {
151+
setChangeVersionDialogOpen(false);
152+
changeVersionMutation.mutate({ versionId: version.id });
153+
}}
154+
/>
99155
</>
100156
);
101157
};
158+
159+
const isMissingBuildParameters = (e: unknown): e is MissingBuildParameters => {
160+
return Boolean(e && e instanceof MissingBuildParameters);
161+
};

site/src/pages/WorkspacePage/ChangeVersionDialog.stories.tsx

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)