Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitba1dbf3

Browse files
committed
add cancel confirmation dialog for workspace builds and add expect_status for pending builds
1 parentc49c33e commitba1dbf3

File tree

7 files changed

+102
-6
lines changed

7 files changed

+102
-6
lines changed

‎site/src/api/api.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1277,9 +1277,14 @@ class ApiMethods {
12771277

12781278
cancelWorkspaceBuild=async(
12791279
workspaceBuildId:TypesGen.WorkspaceBuild["id"],
1280+
request?:TypesGen.CancelWorkspaceBuildRequest,
12801281
):Promise<TypesGen.Response>=>{
1282+
constparams=request?.expect_status
1283+
?newURLSearchParams({expect_status:request.expect_status}).toString()
1284+
:"";
1285+
12811286
constresponse=awaitthis.axios.patch(
1282-
`/api/v2/workspacebuilds/${workspaceBuildId}/cancel`,
1287+
`/api/v2/workspacebuilds/${workspaceBuildId}/cancel${params ?`?${params}` :""}`,
12831288
);
12841289

12851290
returnresponse.data;

‎site/src/api/queries/workspaces.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,12 @@ export const startWorkspace = (
266266
exportconstcancelBuild=(workspace:Workspace,queryClient:QueryClient)=>{
267267
return{
268268
mutationFn:()=>{
269+
// If workspace status is pending, include expect_status parameter
270+
if(workspace.latest_build.status==="pending"){
271+
returnAPI.cancelWorkspaceBuild(workspace.latest_build.id,{
272+
expect_status:"pending",
273+
});
274+
}
269275
returnAPI.cancelWorkspaceBuild(workspace.latest_build.id);
270276
},
271277
onSuccess:async()=>{

‎site/src/api/typesGenerated.ts‎

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎site/src/modules/workspaces/actions.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export const abilitiesByWorkspaceStatus = (
145145
case"pending":{
146146
return{
147147
actions:["pending"],
148-
canCancel:false,
148+
canCancel:true,
149149
canAcceptJobs:false,
150150
};
151151
}

‎site/src/pages/WorkspacePage/WorkspacePage.test.tsx‎

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
MockFailedWorkspace,
1919
MockOrganization,
2020
MockOutdatedWorkspace,
21+
MockPendingWorkspace,
2122
MockStartingWorkspace,
2223
MockStoppedWorkspace,
2324
MockTemplate,
@@ -223,11 +224,53 @@ describe("WorkspacePage", () => {
223224
}),
224225
);
225226

227+
constuser=userEvent.setup({delay:0});
226228
constcancelWorkspaceMock=jest
227229
.spyOn(API,"cancelWorkspaceBuild")
228230
.mockImplementation(()=>Promise.resolve({message:"job canceled"}));
231+
awaitrenderWorkspacePage(MockStartingWorkspace);
232+
233+
// Click on Cancel
234+
constcancelButton=awaitscreen.findByRole("button",{name:"Cancel"});
235+
awaituser.click(cancelButton);
236+
237+
// Get dialog and confirm
238+
constdialog=awaitscreen.findByTestId("dialog");
239+
constconfirmButton=within(dialog).getByRole("button",{
240+
name:"Confirm",
241+
hidden:false,
242+
});
243+
awaituser.click(confirmButton);
244+
245+
expect(cancelWorkspaceMock).toHaveBeenCalledWith(MockStartingWorkspace.latest_build.id);
246+
});
247+
248+
it("requests cancellation when the user presses Cancel and the workspace is pending",async()=>{
249+
server.use(
250+
http.get("/api/v2/users/:userId/workspace/:workspaceName",()=>{
251+
returnHttpResponse.json(MockPendingWorkspace);
252+
}),
253+
);
254+
255+
constuser=userEvent.setup({delay:0});
256+
constcancelWorkspaceMock=jest
257+
.spyOn(API,"cancelWorkspaceBuild")
258+
.mockImplementation(()=>Promise.resolve({message:"job canceled"}));
259+
awaitrenderWorkspacePage(MockPendingWorkspace);
260+
261+
// Click on Cancel
262+
constcancelButton=awaitscreen.findByRole("button",{name:"Cancel"});
263+
awaituser.click(cancelButton);
264+
265+
// Get dialog and confirm
266+
constdialog=awaitscreen.findByTestId("dialog");
267+
constconfirmButton=within(dialog).getByRole("button",{
268+
name:"Confirm",
269+
hidden:false,
270+
});
271+
awaituser.click(confirmButton);
229272

230-
awaittestButton(MockStartingWorkspace,"Cancel",cancelWorkspaceMock);
273+
expect(cancelWorkspaceMock).toHaveBeenCalledWith(MockPendingWorkspace.latest_build.id,{expect_status:"pending"});
231274
});
232275

233276
it("requests an update when the user presses Update",async()=>{

‎site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
8080
ephemeralParameters:TypesGen.TemplateVersionParameter[];
8181
}>({open:false,action:"start",ephemeralParameters:[]});
8282

83+
const[isCancelConfirmOpen,setIsCancelConfirmOpen]=useState(false);
84+
8385
const{mutate:mutateRestartWorkspace,isPending:isRestarting}=
8486
useMutation({
8587
mutationFn:API.restartWorkspace,
@@ -316,7 +318,7 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
316318
}
317319
}}
318320
handleUpdate={workspaceUpdate.update}
319-
handleCancel={cancelBuildMutation.mutate}
321+
handleCancel={()=>setIsCancelConfirmOpen(true)}
320322
handleRetry={handleRetry}
321323
handleDebug={handleDebug}
322324
handleDormantActivate={async()=>{
@@ -352,6 +354,21 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
352354
}
353355
/>
354356

357+
{/* Cancel confirmation dialog */}
358+
<ConfirmDialog
359+
open={isCancelConfirmOpen}
360+
title="Cancel workspace build"
361+
description={`Are you sure you want to cancel the build for workspace "${workspace.name}"? This will stop the current build process.`}
362+
confirmText="Confirm"
363+
cancelText="Discard"
364+
onClose={()=>setIsCancelConfirmOpen(false)}
365+
onConfirm={()=>{
366+
cancelBuildMutation.mutate();
367+
setIsCancelConfirmOpen(false);
368+
}}
369+
type="delete"
370+
/>
371+
355372
<EphemeralParametersDialog
356373
open={ephemeralParametersDialog.open}
357374
onClose={()=>

‎site/src/pages/WorkspacesPage/WorkspacesTable.tsx‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,8 @@ const WorkspaceActionsCell: FC<WorkspaceActionsCellProps> = ({
497497

498498
// State for stop confirmation dialog
499499
const[isStopConfirmOpen,setIsStopConfirmOpen]=useState(false);
500+
// State for cancel confirmation dialog
501+
const[isCancelConfirmOpen,setIsCancelConfirmOpen]=useState(false);
500502

501503
constisRetrying=
502504
startWorkspaceMutation.isPending||
@@ -606,7 +608,7 @@ const WorkspaceActionsCell: FC<WorkspaceActionsCellProps> = ({
606608

607609
{abilities.canCancel&&(
608610
<PrimaryAction
609-
onClick={cancelBuildMutation.mutate}
611+
onClick={()=>setIsCancelConfirmOpen(true)}
610612
isLoading={cancelBuildMutation.isPending}
611613
label="Cancel build"
612614
>
@@ -643,6 +645,21 @@ const WorkspaceActionsCell: FC<WorkspaceActionsCellProps> = ({
643645
}}
644646
type="delete"
645647
/>
648+
649+
{/* Cancel workspace build confirmation dialog */}
650+
<ConfirmDialog
651+
open={isCancelConfirmOpen}
652+
title="Cancel workspace build"
653+
description={`Are you sure you want to cancel the build for workspace "${workspace.name}"? This will stop the current build process.`}
654+
confirmText="Confirm"
655+
cancelText="Discard"
656+
onClose={()=>setIsCancelConfirmOpen(false)}
657+
onConfirm={()=>{
658+
cancelBuildMutation.mutate();
659+
setIsCancelConfirmOpen(false);
660+
}}
661+
type="delete"
662+
/>
646663
</TableCell>
647664
);
648665
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp