Skip to content

feat: disable start/restart if active version required #10809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions site/src/pages/WorkspacePage/WorkspaceActions/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import { Workspace, WorkspaceBuildParameter } from "api/typesGenerated";
import { BuildParametersPopover } from "./BuildParametersPopover";
import PowerSettingsNewIcon from "@mui/icons-material/PowerSettingsNew";
import LoadingButton from "@mui/lab/LoadingButton";
import Tooltip from "@mui/material/Tooltip";

interface WorkspaceAction {
loading?: boolean;
handleAction: () => void;
disabled?: boolean;
tooltipText?: string;
}

export const UpdateButton: FC<WorkspaceAction> = ({
Expand Down Expand Up @@ -55,8 +58,8 @@ export const StartButton: FC<
workspace: Workspace;
handleAction: (buildParameters?: WorkspaceBuildParameter[]) => void;
}
> = ({ handleAction, workspace, loading }) => {
return (
> = ({ handleAction, workspace, loading, disabled, tooltipText }) => {
const buttonContent = (
<ButtonGroup
variant="outlined"
sx={{
Expand All @@ -65,12 +68,14 @@ export const StartButton: FC<
borderLeft: "1px solid #FFF",
},
}}
disabled={disabled}
>
<LoadingButton
loading={loading}
loadingPosition="start"
startIcon={<PlayCircleOutlineIcon />}
onClick={() => handleAction()}
disabled={disabled}
>
{loading ? <>Starting&hellip;</> : "Start"}
</LoadingButton>
Expand All @@ -81,6 +86,12 @@ export const StartButton: FC<
/>
</ButtonGroup>
);

return tooltipText ? (
<Tooltip title={tooltipText}>{buttonContent}</Tooltip>
) : (
buttonContent
);
};

export const StopButton: FC<WorkspaceAction> = ({ handleAction, loading }) => {
Expand All @@ -102,8 +113,8 @@ export const RestartButton: FC<
workspace: Workspace;
handleAction: (buildParameters?: WorkspaceBuildParameter[]) => void;
}
> = ({ handleAction, loading, workspace }) => {
return (
> = ({ handleAction, loading, workspace, disabled, tooltipText }) => {
const buttonContent = (
<ButtonGroup
variant="outlined"
sx={{
Expand All @@ -112,13 +123,15 @@ export const RestartButton: FC<
borderLeft: "1px solid #FFF",
},
}}
disabled={disabled}
>
<LoadingButton
loading={loading}
loadingPosition="start"
startIcon={<ReplayIcon />}
onClick={() => handleAction()}
data-testid="workspace-restart-button"
disabled={disabled}
>
{loading ? <>Restarting&hellip;</> : <>Restart&hellip;</>}
</LoadingButton>
Expand All @@ -129,6 +142,12 @@ export const RestartButton: FC<
/>
</ButtonGroup>
);

return tooltipText ? (
<Tooltip title={tooltipText}>{buttonContent}</Tooltip>
) : (
buttonContent
);
};

export const CancelButton: FC<WorkspaceAction> = ({ handleAction }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,17 @@ export const RequireActiveVersionStopped: Story = {
canChangeVersions: false,
},
};

export const AlwaysUpdateStarted: Story = {
args: {
workspace: Mocks.MockOutdatedRunningWorkspaceAlwaysUpdate,
canChangeVersions: true,
},
};

export const AlwaysUpdateStopped: Story = {
args: {
workspace: Mocks.MockOutdatedStoppedWorkspaceAlwaysUpdate,
canChangeVersions: true,
},
};
48 changes: 40 additions & 8 deletions site/src/pages/WorkspacePage/WorkspaceActions/WorkspaceActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
MoreMenuTrigger,
ThreeDotsButton,
} from "components/MoreMenu/MoreMenu";
import { workspaceUpdatePolicy } from "utils/workspace";

export interface WorkspaceActionsProps {
workspace: Workspace;
Expand Down Expand Up @@ -67,39 +68,70 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
canCancel,
canAcceptJobs,
actions: actionsByStatus,
} = actionsByWorkspaceStatus(
workspace,
workspace.latest_build.status,
canChangeVersions,
);
} = actionsByWorkspaceStatus(workspace, workspace.latest_build.status);
const canBeUpdated = workspace.outdated && canAcceptJobs;
const { duplicateWorkspace, isDuplicationReady } =
useWorkspaceDuplication(workspace);

const disabled =
workspaceUpdatePolicy(workspace, canChangeVersions) === "always" &&
workspace.outdated;

const tooltipText = ((): string => {
if (!disabled) {
return "";
}
if (workspace.template_require_active_version) {
return "This template requires automatic updates";
}
if (workspace.automatic_updates === "always") {
return "You have enabled automatic updates for this workspace";
}
return "";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just found strange to have two places returning "" 🤔

})();

// A mapping of button type to the corresponding React component
const buttonMapping: ButtonMapping = {
[ButtonTypesEnum.update]: <UpdateButton handleAction={handleUpdate} />,
[ButtonTypesEnum.updating]: (
<UpdateButton loading handleAction={handleUpdate} />
),
[ButtonTypesEnum.start]: (
<StartButton workspace={workspace} handleAction={handleStart} />
<StartButton
workspace={workspace}
handleAction={handleStart}
disabled={disabled}
tooltipText={tooltipText}
/>
),
[ButtonTypesEnum.starting]: (
<StartButton loading workspace={workspace} handleAction={handleStart} />
<StartButton
loading
workspace={workspace}
handleAction={handleStart}
disabled={disabled}
tooltipText={tooltipText}
/>
),
[ButtonTypesEnum.stop]: <StopButton handleAction={handleStop} />,
[ButtonTypesEnum.stopping]: (
<StopButton loading handleAction={handleStop} />
),
[ButtonTypesEnum.restart]: (
<RestartButton workspace={workspace} handleAction={handleRestart} />
<RestartButton
workspace={workspace}
handleAction={handleRestart}
disabled={disabled}
tooltipText={tooltipText}
/>
),
[ButtonTypesEnum.restarting]: (
<RestartButton
loading
workspace={workspace}
handleAction={handleRestart}
disabled={disabled}
tooltipText={tooltipText}
/>
),
[ButtonTypesEnum.deleting]: <ActionLoadingButton label="Deleting" />,
Expand Down
21 changes: 0 additions & 21 deletions site/src/pages/WorkspacePage/WorkspaceActions/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Workspace, WorkspaceStatus } from "api/typesGenerated";
import { ReactNode } from "react";
import { workspaceUpdatePolicy } from "utils/workspace";

// the button types we have
export enum ButtonTypesEnum {
Expand Down Expand Up @@ -34,7 +33,6 @@ interface WorkspaceAbilities {
export const actionsByWorkspaceStatus = (
workspace: Workspace,
status: WorkspaceStatus,
canChangeVersions: boolean,
): WorkspaceAbilities => {
if (workspace.dormant_at) {
return {
Expand All @@ -43,25 +41,6 @@ export const actionsByWorkspaceStatus = (
canAcceptJobs: false,
};
}
if (
workspace.outdated &&
workspaceUpdatePolicy(workspace, canChangeVersions) === "always"
) {
if (status === "running") {
return {
actions: [ButtonTypesEnum.stop],
canCancel: false,
canAcceptJobs: true,
};
}
if (status === "stopped") {
return {
actions: [],
canCancel: false,
canAcceptJobs: true,
};
}
}
return statusToActions[status];
};

Expand Down
19 changes: 19 additions & 0 deletions site/src/testHelpers/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,17 @@ export const MockOutdatedRunningWorkspaceRequireActiveVersion: TypesGen.Workspac
},
};

export const MockOutdatedRunningWorkspaceAlwaysUpdate: TypesGen.Workspace = {
...MockWorkspace,
id: "test-outdated-workspace-always-update",
outdated: true,
automatic_updates: "always",
latest_build: {
...MockWorkspaceBuild,
status: "running",
},
};

export const MockOutdatedStoppedWorkspaceRequireActiveVersion: TypesGen.Workspace =
{
...MockOutdatedRunningWorkspaceRequireActiveVersion,
Expand All @@ -1062,6 +1073,14 @@ export const MockOutdatedStoppedWorkspaceRequireActiveVersion: TypesGen.Workspac
},
};

export const MockOutdatedStoppedWorkspaceAlwaysUpdate: TypesGen.Workspace = {
...MockOutdatedRunningWorkspaceAlwaysUpdate,
latest_build: {
...MockWorkspaceBuild,
status: "stopped",
},
};

export const MockPendingWorkspace: TypesGen.Workspace = {
...MockWorkspace,
id: "test-pending-workspace",
Expand Down