Skip to content

Commit d74cf8e

Browse files
committed
feat: implement basic archive ui to make archiving failed versions easy.
More work is needed... this is just the MVP
1 parent 17132e6 commit d74cf8e

File tree

4 files changed

+87
-6
lines changed

4 files changed

+87
-6
lines changed

site/src/api/api.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,24 @@ export const patchTemplateVersion = async (
387387
return response.data;
388388
};
389389

390+
export const archiveTemplateVersion = async (
391+
templateVersionId: string,
392+
) => {
393+
const response = await axios.post<TypesGen.TemplateVersion>(
394+
`/api/v2/templateversions/${templateVersionId}/archive`,
395+
);
396+
return response.data;
397+
};
398+
399+
export const unarchiveTemplateVersion = async (
400+
templateVersionId: string,
401+
) => {
402+
const response = await axios.post<TypesGen.TemplateVersion>(
403+
`/api/v2/templateversions/${templateVersionId}/unarchive`,
404+
);
405+
return response.data;
406+
};
407+
390408
export const updateTemplateMeta = async (
391409
templateId: string,
392410
data: TypesGen.UpdateTemplateMeta,

site/src/pages/TemplatePage/TemplateVersionsPage/TemplateVersionsPage.tsx

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { useMutation, useQuery } from "react-query";
2-
import { getTemplateVersions, updateActiveTemplateVersion } from "api/api";
2+
import {
3+
archiveTemplateVersion,
4+
getTemplateVersions,
5+
updateActiveTemplateVersion,
6+
} from "api/api";
37
import { getErrorMessage } from "api/errors";
48
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
59
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
@@ -34,9 +38,31 @@ const TemplateVersionsPage = () => {
3438
displayError(getErrorMessage(error, "Failed to promote version"));
3539
},
3640
});
41+
42+
const { mutate: archiveVersion, isLoading: isArchiving } = useMutation({
43+
mutationFn: (templateVersionId: string) => {
44+
return archiveTemplateVersion(templateVersionId);
45+
},
46+
onSuccess: async () => {
47+
// The reload is unfortunate. When a version is archived, we should hide
48+
// the row. I do not know an easy way to do that, so a reload makes the API call
49+
// resend and now the version is omitted.
50+
// TODO: Improve this to not reload the page.
51+
location.reload();
52+
setSelectedVersionIdToArchive(undefined);
53+
displaySuccess("Version archived successfully");
54+
},
55+
onError: (error) => {
56+
displayError(getErrorMessage(error, "Failed to archive version"));
57+
},
58+
});
59+
3760
const [selectedVersionIdToPromote, setSelectedVersionIdToPromote] = useState<
3861
string | undefined
3962
>();
63+
const [selectedVersionIdToArchive, setSelectedVersionIdToArchive] = useState<
64+
string | undefined
65+
>();
4066

4167
return (
4268
<>
@@ -50,8 +76,14 @@ const TemplateVersionsPage = () => {
5076
? setSelectedVersionIdToPromote
5177
: undefined
5278
}
79+
onArchiveClick={
80+
permissions.canUpdateTemplate
81+
? setSelectedVersionIdToArchive
82+
: undefined
83+
}
5384
activeVersionId={latestActiveVersion}
5485
/>
86+
{/* Promote confirm */}
5587
<ConfirmDialog
5688
type="info"
5789
hideCancel={false}
@@ -65,6 +97,20 @@ const TemplateVersionsPage = () => {
6597
confirmText="Promote"
6698
description="Are you sure you want to promote this version? Workspaces will be prompted to “Update” to this version once promoted."
6799
/>
100+
{/* Archive Confirm */}
101+
<ConfirmDialog
102+
type="info"
103+
hideCancel={false}
104+
open={selectedVersionIdToArchive !== undefined}
105+
onConfirm={() => {
106+
archiveVersion(selectedVersionIdToArchive as string);
107+
}}
108+
onClose={() => setSelectedVersionIdToArchive(undefined)}
109+
title="Archive version"
110+
confirmLoading={isArchiving}
111+
confirmText="Archive"
112+
description="Are you sure you want to archive this version? Archived versions cannot be used by workspaces."
113+
/>
68114
</>
69115
);
70116
};

site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ export interface VersionRowProps {
1717
isActive: boolean;
1818
isLatest: boolean;
1919
onPromoteClick?: (templateVersionId: string) => void;
20+
onArchiveClick?: (templateVersionId: string) => void;
2021
}
2122

2223
export const VersionRow: React.FC<VersionRowProps> = ({
2324
version,
2425
isActive,
2526
isLatest,
2627
onPromoteClick,
28+
onArchiveClick,
2729
}) => {
2830
const styles = useStyles();
2931
const navigate = useNavigate();
@@ -33,6 +35,14 @@ export const VersionRow: React.FC<VersionRowProps> = ({
3335
});
3436

3537
const jobStatus = version.job.status;
38+
let buttonVerb = "Promote";
39+
let buttonAction = onPromoteClick;
40+
let buttonDisabled = isActive || jobStatus !== "succeeded";
41+
if (jobStatus === "failed") {
42+
buttonVerb = "Archive";
43+
buttonAction = onArchiveClick;
44+
buttonDisabled = false;
45+
}
3646

3747
return (
3848
<TimelineEntry
@@ -90,17 +100,21 @@ export const VersionRow: React.FC<VersionRowProps> = ({
90100
<Pill text="Canceled" type="neutral" lightBorder />
91101
)}
92102
{jobStatus === "failed" && <Pill text="Failed" type="error" />}
93-
{onPromoteClick && (
103+
{buttonAction && (
94104
<Button
95105
className={styles.promoteButton}
96-
disabled={isActive || jobStatus !== "succeeded"}
106+
disabled={buttonDisabled}
97107
onClick={(e) => {
98108
e.preventDefault();
99109
e.stopPropagation();
100-
onPromoteClick(version.id);
110+
if (buttonAction) {
111+
// Linter was complaining about this unless I threw it
112+
// in an if statement.
113+
buttonAction(version.id);
114+
}
101115
}}
102116
>
103-
Promote&hellip;
117+
{buttonVerb}&hellip;
104118
</Button>
105119
)}
106120
</Stack>

site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ export const Language = {
2121
export interface VersionsTableProps {
2222
activeVersionId: string;
2323
onPromoteClick?: (templateVersionId: string) => void;
24+
onArchiveClick?: (templateVersionId: string) => void;
25+
2426
versions?: TypesGen.TemplateVersion[];
2527
}
2628

2729
export const VersionsTable: FC<VersionsTableProps> = (props) => {
28-
const { versions, onPromoteClick, activeVersionId } = props;
30+
const { versions, onArchiveClick, onPromoteClick, activeVersionId } = props;
2931

3032
const latestVersionId = versions?.reduce(
3133
(latestSoFar, against) => {
@@ -55,6 +57,7 @@ export const VersionsTable: FC<VersionsTableProps> = (props) => {
5557
getDate={(version) => new Date(version.created_at)}
5658
row={(version) => (
5759
<VersionRow
60+
onArchiveClick={onArchiveClick}
5861
onPromoteClick={onPromoteClick}
5962
version={version}
6063
key={version.id}

0 commit comments

Comments
 (0)