fix: display error message on delete workspace error (#18654)

resolves coder/preview#155

When deleting a workspace, show an error dialog if deleting the
workspace is not possible.

![Screenshot 2025-06-28 at 10 06
47](https://github.com/user-attachments/assets/650bfb54-6ed9-4f41-a410-1333afeee0a4)
This commit is contained in:
Jaayden Halko
2025-06-30 15:09:51 -04:00
committed by GitHub
parent 22c5e84a7e
commit ad6773360c
3 changed files with 43 additions and 4 deletions
@@ -19,6 +19,7 @@ interface WorkspaceErrorDialogProps {
workspaceOwner: string;
workspaceName: string;
templateVersionId: string;
isDeleting: boolean;
}
export const WorkspaceErrorDialog: FC<WorkspaceErrorDialogProps> = ({
@@ -29,6 +30,7 @@ export const WorkspaceErrorDialog: FC<WorkspaceErrorDialogProps> = ({
workspaceOwner,
workspaceName,
templateVersionId,
isDeleting,
}) => {
const navigate = useNavigate();
@@ -52,7 +54,9 @@ export const WorkspaceErrorDialog: FC<WorkspaceErrorDialogProps> = ({
<Dialog open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
<DialogContent variant="destructive">
<DialogHeader>
<DialogTitle>Error building workspace</DialogTitle>
<DialogTitle>
Error {isDeleting ? "deleting" : "building"} workspace
</DialogTitle>
<DialogDescription className="flex flex-row gap-4">
<strong className="text-content-primary">Message</strong>{" "}
<span>{getErrorMessage(error, "Failed to build workspace.")}</span>
@@ -1,4 +1,6 @@
import { MissingBuildParameters } from "api/api";
import { isApiError } from "api/errors";
import { type ApiError, getErrorMessage } from "api/errors";
import {
changeVersion,
deleteWorkspace,
@@ -13,6 +15,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "components/DropdownMenu/DropdownMenu";
import { displayError } from "components/GlobalSnackbar/utils";
import {
CopyIcon,
DownloadIcon,
@@ -24,6 +27,7 @@ import {
import { type FC, useEffect, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { Link as RouterLink } from "react-router-dom";
import { WorkspaceErrorDialog } from "../ErrorDialog/WorkspaceErrorDialog";
import { ChangeWorkspaceVersionDialog } from "./ChangeWorkspaceVersionDialog";
import { DownloadLogsDialog } from "./DownloadLogsDialog";
import { UpdateBuildParametersDialog } from "./UpdateBuildParametersDialog";
@@ -42,6 +46,11 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
}) => {
const queryClient = useQueryClient();
const [workspaceErrorDialog, setWorkspaceErrorDialog] = useState<{
open: boolean;
error?: ApiError;
}>({ open: false });
// Permissions
const { data: permissions } = useQuery(workspacePermissions(workspace));
@@ -58,11 +67,25 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
),
);
const handleError = (error: unknown) => {
if (isApiError(error) && error.code === "ERR_BAD_REQUEST") {
setWorkspaceErrorDialog({
open: true,
error: error,
});
} else {
displayError(getErrorMessage(error, "Failed to delete workspace."));
}
};
// Delete
const [isConfirmingDelete, setIsConfirmingDelete] = useState(false);
const deleteWorkspaceMutation = useMutation(
deleteWorkspace(workspace, queryClient),
);
const deleteWorkspaceMutation = useMutation({
...deleteWorkspace(workspace, queryClient),
onError: (error: unknown) => {
handleError(error);
},
});
// Duplicate
const { duplicateWorkspace, isDuplicationReady } =
@@ -212,6 +235,17 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
setIsConfirmingDelete(false);
}}
/>
<WorkspaceErrorDialog
open={workspaceErrorDialog.open}
error={workspaceErrorDialog.error}
onClose={() => setWorkspaceErrorDialog({ open: false })}
showDetail={workspace.template_use_classic_parameter_flow}
workspaceOwner={workspace.owner_name}
workspaceName={workspace.name}
templateVersionId={workspace.latest_build.template_version_id}
isDeleting={true}
/>
</>
);
};
@@ -392,6 +392,7 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
workspaceOwner={workspace.owner_name}
workspaceName={workspace.name}
templateVersionId={workspace.latest_build.template_version_id}
isDeleting={false}
/>
</>
);