feat(site): show "update and start" button when update is forced (#13334)

This commit is contained in:
Bruno Quaresma
2024-05-21 19:29:54 +00:00
committed by GitHub
parent f27f5c0002
commit 78deaba481
3 changed files with 123 additions and 71 deletions
@@ -117,10 +117,8 @@ export const RestartButton: FC<ActionButtonPropsWithWorkspace> = ({
handleAction,
loading,
workspace,
disabled,
tooltipText,
}) => {
const buttonContent = (
return (
<ButtonGroup
variant="outlined"
css={{
@@ -129,13 +127,12 @@ export const RestartButton: FC<ActionButtonPropsWithWorkspace> = ({
borderLeft: "1px solid #FFF",
},
}}
disabled={disabled}
>
<TopbarButton
startIcon={<ReplayIcon />}
onClick={() => handleAction()}
data-testid="workspace-restart-button"
disabled={disabled || loading}
disabled={loading}
>
{loading ? <>Restarting&hellip;</> : <>Restart&hellip;</>}
</TopbarButton>
@@ -147,11 +144,20 @@ export const RestartButton: FC<ActionButtonPropsWithWorkspace> = ({
/>
</ButtonGroup>
);
};
return tooltipText ? (
<Tooltip title={tooltipText}>{buttonContent}</Tooltip>
) : (
buttonContent
export const UpdateAndStartButton: FC<ActionButtonProps> = ({
handleAction,
}) => {
return (
<Tooltip title="This template requires automatic updates on workspace startup. Contact your administrator if you want to preserve the template version.">
<TopbarButton
startIcon={<PlayCircleOutlineIcon />}
onClick={() => handleAction()}
>
Update and start&hellip;
</TopbarButton>
</Tooltip>
);
};
@@ -24,6 +24,7 @@ import {
UpdateButton,
ActivateButton,
FavoriteButton,
UpdateAndStartButton,
} from "./Buttons";
import { type ActionType, abilitiesByWorkspaceStatus } from "./constants";
import { DebugButton } from "./DebugButton";
@@ -89,6 +90,7 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
// A mapping of button type to the corresponding React component
const buttonMapping: Record<ActionType, ReactNode> = {
update: <UpdateButton handleAction={handleUpdate} />,
updateAndStart: <UpdateAndStartButton handleAction={handleUpdate} />,
updating: <UpdateButton loading handleAction={handleUpdate} />,
start: (
<StartButton
@@ -161,7 +163,13 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
data-testid="workspace-actions"
>
{canBeUpdated && (
<>{isUpdating ? buttonMapping.updating : buttonMapping.update}</>
<>
{isUpdating
? buttonMapping.updating
: workspace.template_require_active_version
? buttonMapping.updateAndStart
: buttonMapping.update}
</>
)}
{isRestarting
@@ -236,10 +244,6 @@ function getTooltipText(
return "This template requires automatic updates on workspace startup, but template administrators can ignore this policy.";
}
if (workspace.template_require_active_version) {
return "This template requires automatic updates on workspace startup. Contact your administrator if you want to preserve the template version.";
}
if (workspace.automatic_updates === "always") {
return "Automatic updates are enabled for this workspace. Modify the update policy in workspace settings if you want to preserve the template version.";
}
@@ -1,4 +1,4 @@
import type { Workspace, WorkspaceStatus } from "api/typesGenerated";
import type { Workspace } from "api/typesGenerated";
/**
* An iterable of all action types supported by the workspace UI
@@ -23,6 +23,10 @@ export const actionTypes = [
"retry",
"debug",
// When a template requires updates, we aim to display a distinct update
// button that clearly indicates a mandatory update.
"updateAndStart",
// These are buttons that should be used with disabled UI elements
"canceling",
"deleted",
@@ -52,67 +56,105 @@ export const abilitiesByWorkspaceStatus = (
const status = workspace.latest_build.status;
if (status === "failed" && canDebug) {
return {
...statusToAbility.failed,
actions: ["retry", "debug"],
canCancel: false,
canAcceptJobs: true,
};
}
return statusToAbility[status];
};
switch (status) {
case "starting": {
return {
actions: ["starting"],
canCancel: true,
canAcceptJobs: false,
};
}
case "running": {
const actions: ActionType[] = ["stop"];
const statusToAbility: Record<WorkspaceStatus, WorkspaceAbilities> = {
starting: {
actions: ["starting"],
canCancel: true,
canAcceptJobs: false,
},
running: {
actions: ["stop", "restart"],
canCancel: false,
canAcceptJobs: true,
},
stopping: {
actions: ["stopping"],
canCancel: true,
canAcceptJobs: false,
},
stopped: {
actions: ["start"],
canCancel: false,
canAcceptJobs: true,
},
canceled: {
actions: ["start", "stop"],
canCancel: false,
canAcceptJobs: true,
},
// If the template requires the latest version, we prevent the user from
// restarting the workspace without updating it first. In the Buttons
// component, we display an UpdateAndStart component to facilitate this.
if (!workspace.template_require_active_version) {
actions.push("restart");
}
// in the case of an error
failed: {
actions: ["retry"],
canCancel: false,
canAcceptJobs: true,
},
return {
actions,
canCancel: false,
canAcceptJobs: true,
};
}
case "stopping": {
return {
actions: ["stopping"],
canCancel: true,
canAcceptJobs: false,
};
}
case "stopped": {
const actions: ActionType[] = [];
// Disabled states
canceling: {
actions: ["canceling"],
canCancel: false,
canAcceptJobs: false,
},
deleting: {
actions: ["deleting"],
canCancel: true,
canAcceptJobs: false,
},
deleted: {
actions: ["deleted"],
canCancel: false,
canAcceptJobs: false,
},
pending: {
actions: ["pending"],
canCancel: false,
canAcceptJobs: false,
},
// If the template requires the latest version, we prevent the user from
// starting the workspace without updating it first. In the Buttons
// component, we display an UpdateAndStart component to facilitate this.
if (!workspace.template_require_active_version) {
actions.push("start");
}
return {
actions,
canCancel: false,
canAcceptJobs: true,
};
}
case "canceled": {
return {
actions: ["start", "stop"],
canCancel: false,
canAcceptJobs: true,
};
}
case "failed": {
return {
actions: ["retry"],
canCancel: false,
canAcceptJobs: true,
};
}
// Disabled states
case "canceling": {
return {
actions: ["canceling"],
canCancel: false,
canAcceptJobs: false,
};
}
case "deleting": {
return {
actions: ["deleting"],
canCancel: true,
canAcceptJobs: false,
};
}
case "deleted": {
return {
actions: ["deleted"],
canCancel: false,
canAcceptJobs: false,
};
}
case "pending": {
return {
actions: ["pending"],
canCancel: false,
canAcceptJobs: false,
};
}
default: {
throw new Error(`Unknown workspace status: ${status}`);
}
}
};