Files
coder/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx
T
Jake Howell 1fdb8ed9a0 fix: wrap latestVersion?.message with <div /> (#25549)
This pull-request wraps the `latestVersion?.message` in a `<div />` so
that our content is affected by the `flex flex-col` class from the
parent.

| Old | New |
| --- | --- |
| <img width="441" height="363" alt="PREVIEW_1"
src="https://github.com/user-attachments/assets/0693136a-cfcc-4f17-a94d-35c14943c3bd"
/> | <img width="441" height="295" alt="PREVIEW_1_NEW"
src="https://github.com/user-attachments/assets/ce6c1126-6153-4d7f-a4b8-f01a5a98e270"
/> |
| <img width="441" height="396" alt="PREVIEW_2"
src="https://github.com/user-attachments/assets/b26e81b4-09fb-4317-9d25-3ca8b5989c54"
/> | <img width="441" height="294" alt="PREVIEW_2_NEW"
src="https://github.com/user-attachments/assets/241afe85-c278-4593-a985-bcc2400ac52f"
/> |
2026-05-22 00:20:41 +10:00

186 lines
5.0 KiB
TypeScript

import { type FC, useState } from "react";
import { useMutation, useQueryClient } from "react-query";
import { MissingBuildParameters, ParameterValidationError } from "#/api/api";
import { updateWorkspace } from "#/api/queries/workspaces";
import type {
TemplateVersion,
Workspace,
WorkspaceBuild,
WorkspaceBuildParameter,
} from "#/api/typesGenerated";
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
import { MemoizedInlineMarkdown } from "#/components/Markdown/InlineMarkdown";
import { UpdateBuildParametersDialog } from "#/modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialog";
import { UpdateBuildParametersDialogExperimental } from "#/modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental";
type UseWorkspaceUpdateOptions = {
workspace: Workspace;
latestVersion: TemplateVersion | undefined;
onSuccess?: (build: WorkspaceBuild) => void;
onError?: (error: unknown) => void;
};
type UseWorkspaceUpdateResult = {
update: () => void;
isUpdating: boolean;
dialogs: {
updateConfirmation: UpdateConfirmationDialogProps;
missingBuildParameters: MissingBuildParametersDialogProps;
};
};
export const useWorkspaceUpdate = ({
workspace,
latestVersion,
onSuccess,
onError,
}: UseWorkspaceUpdateOptions): UseWorkspaceUpdateResult => {
const queryClient = useQueryClient();
const [isConfirmingUpdate, setIsConfirmingUpdate] = useState(false);
const updateWorkspaceOptions = updateWorkspace(workspace, queryClient);
const updateWorkspaceMutation = useMutation({
...updateWorkspaceOptions,
onSuccess: (build: WorkspaceBuild) => {
updateWorkspaceOptions.onSuccess(build);
onSuccess?.(build);
},
onError,
});
const update = () => {
setIsConfirmingUpdate(true);
};
const confirmUpdate = (buildParameters: WorkspaceBuildParameter[] = []) => {
updateWorkspaceMutation.mutate({
buildParameters,
isDynamicParametersEnabled:
!workspace.template_use_classic_parameter_flow,
});
setIsConfirmingUpdate(false);
};
return {
update,
isUpdating: updateWorkspaceMutation.isPending,
dialogs: {
updateConfirmation: {
open: isConfirmingUpdate,
onClose: () => setIsConfirmingUpdate(false),
onConfirm: () => confirmUpdate(),
latestVersion,
},
missingBuildParameters: {
workspace,
error: updateWorkspaceMutation.error,
onClose: () => {
updateWorkspaceMutation.reset();
},
onUpdate: (buildParameters: WorkspaceBuildParameter[]) => {
if (
updateWorkspaceMutation.error instanceof MissingBuildParameters ||
updateWorkspaceMutation.error instanceof ParameterValidationError
) {
confirmUpdate(buildParameters);
}
},
},
},
};
};
type WorkspaceUpdateDialogsProps = {
updateConfirmation: UpdateConfirmationDialogProps;
missingBuildParameters: MissingBuildParametersDialogProps;
};
export const WorkspaceUpdateDialogs: FC<WorkspaceUpdateDialogsProps> = ({
updateConfirmation,
missingBuildParameters,
}) => {
return (
<>
<UpdateConfirmationDialog {...updateConfirmation} />
<MissingBuildParametersDialog {...missingBuildParameters} />
</>
);
};
type UpdateConfirmationDialogProps = {
open: boolean;
onClose: () => void;
onConfirm: () => void;
latestVersion?: TemplateVersion;
};
const UpdateConfirmationDialog: FC<UpdateConfirmationDialogProps> = ({
latestVersion,
...dialogProps
}) => {
return (
<ConfirmDialog
{...dialogProps}
hideCancel={false}
title="Update workspace?"
confirmText="Update"
description={
<div className="flex flex-col gap-2">
<p>
Updating your workspace will start the workspace on the latest
template version. This can{" "}
<strong>delete non-persistent data</strong>.
</p>
<div>
{latestVersion?.message && (
<MemoizedInlineMarkdown allowedElements={["ol", "ul", "li"]}>
{latestVersion.message}
</MemoizedInlineMarkdown>
)}
</div>
</div>
}
/>
);
};
type MissingBuildParametersDialogProps = {
workspace: Workspace;
error: unknown;
onClose: () => void;
onUpdate: (buildParameters: WorkspaceBuildParameter[]) => void;
};
const MissingBuildParametersDialog: FC<MissingBuildParametersDialogProps> = ({
workspace,
error,
...dialogProps
}) => {
const missedParameters =
error instanceof MissingBuildParameters ? error.parameters : [];
const versionId =
error instanceof ParameterValidationError ? error.versionId : undefined;
const isOpen =
error instanceof MissingBuildParameters ||
error instanceof ParameterValidationError;
return workspace.template_use_classic_parameter_flow ? (
<UpdateBuildParametersDialog
missedParameters={missedParameters}
open={isOpen}
{...dialogProps}
/>
) : (
<UpdateBuildParametersDialogExperimental
validations={
error instanceof ParameterValidationError ? error.validations : []
}
open={isOpen}
onClose={dialogProps.onClose}
workspaceOwnerName={workspace.owner_name}
workspaceName={workspace.name}
templateVersionId={versionId}
/>
);
};