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

Commit11b7732

Browse files
feat(site): Show confirmation dialog on restart (#7531)
1 parentd9fc94f commit11b7732

File tree

3 files changed

+158
-12
lines changed

3 files changed

+158
-12
lines changed

‎site/src/components/WorkspaceActions/Buttons.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ export const RestartButton: FC<PropsWithChildren<WorkspaceAction>> = ({
5959
const{ t}=useTranslation("workspacePage")
6060

6161
return(
62-
<Buttonsize="small"startIcon={<ReplayIcon/>}onClick={handleAction}>
62+
<Button
63+
size="small"
64+
startIcon={<ReplayIcon/>}
65+
onClick={handleAction}
66+
data-testid="workspace-restart-button"
67+
>
6368
{t("actionButton.restart")}
6469
</Button>
6570
)

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
MockDeletedWorkspace,
2121
MockBuilds,
2222
MockTemplateVersion3,
23+
MockUser,
2324
}from"testHelpers/entities"
2425
import*asapifrom"../../api/api"
2526
import{Workspace}from"../../api/typesGenerated"
@@ -161,10 +162,41 @@ describe("WorkspacePage", () => {
161162
.spyOn(api,"stopWorkspace")
162163
.mockResolvedValueOnce(MockWorkspaceBuild)
163164

164-
awaittestButton("Restart",stopWorkspaceMock)
165+
// Render
166+
awaitrenderWorkspacePage()
167+
168+
// Actions
169+
constuser=userEvent.setup()
170+
awaituser.click(screen.getByTestId("workspace-restart-button"))
171+
constconfirmButton=awaitscreen.findByTestId("confirm-button")
172+
awaituser.click(confirmButton)
173+
174+
// Assertions
175+
awaitwaitFor(()=>{
176+
expect(stopWorkspaceMock).toBeCalled()
177+
})
178+
})
179+
180+
it("requests a stop without confirmation when the user presses Restart",async()=>{
181+
conststopWorkspaceMock=jest
182+
.spyOn(api,"stopWorkspace")
183+
.mockResolvedValueOnce(MockWorkspaceBuild)
184+
window.localStorage.setItem(
185+
`${MockUser.id}_ignoredWarnings`,
186+
JSON.stringify({restart:newDate().toISOString()}),
187+
)
188+
189+
// Render
190+
awaitrenderWorkspacePage()
165191

166-
constbutton=awaitscreen.findByText("Restarting")
167-
expect(button).toBeInTheDocument()
192+
// Actions
193+
constuser=userEvent.setup()
194+
awaituser.click(screen.getByTestId("workspace-restart-button"))
195+
196+
// Assertions
197+
awaitwaitFor(()=>{
198+
expect(stopWorkspaceMock).toBeCalled()
199+
})
168200
})
169201

170202
it("requests cancellation when the user presses Cancel",async()=>{

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

Lines changed: 117 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ProvisionerJobLog } from "api/typesGenerated"
33
import{useDashboard}from"components/Dashboard/DashboardProvider"
44
importdayjsfrom"dayjs"
55
import{useFeatureVisibility}from"hooks/useFeatureVisibility"
6-
import{useEffect,useState}from"react"
6+
import{FC,useEffect,useState}from"react"
77
import{Helmet}from"react-helmet-async"
88
import{useTranslation}from"react-i18next"
99
import{useNavigate}from"react-router-dom"
@@ -31,7 +31,13 @@ import { ChangeVersionDialog } from "./ChangeVersionDialog"
3131
import{useQuery}from"@tanstack/react-query"
3232
import{getTemplateVersions}from"api/api"
3333
import{useRestartWorkspace}from"./hooks"
34-
import{ConfirmDialog}from"components/Dialogs/ConfirmDialog/ConfirmDialog"
34+
import{
35+
ConfirmDialog,
36+
ConfirmDialogProps,
37+
}from"components/Dialogs/ConfirmDialog/ConfirmDialog"
38+
import{useMe}from"hooks/useMe"
39+
importCheckboxfrom"@mui/material/Checkbox"
40+
importFormControlLabelfrom"@mui/material/FormControlLabel"
3541

3642
interfaceWorkspaceReadyPageProps{
3743
workspaceState:StateFrom<typeofworkspaceMachine>
@@ -79,6 +85,9 @@ export const WorkspaceReadyPage = ({
7985
enabled:changeVersionDialogOpen,
8086
})
8187
const[isConfirmingUpdate,setIsConfirmingUpdate]=useState(false)
88+
const[isConfirmingRestart,setIsConfirmingRestart]=useState(false)
89+
constuser=useMe()
90+
const{ isWarningIgnored, ignoreWarning}=useIgnoreWarnings(user.id)
8291

8392
const{
8493
mutate:restartWorkspace,
@@ -133,9 +142,21 @@ export const WorkspaceReadyPage = ({
133142
workspace={workspace}
134143
handleStart={()=>workspaceSend({type:"START"})}
135144
handleStop={()=>workspaceSend({type:"STOP"})}
136-
handleRestart={()=>restartWorkspace(workspace)}
137145
handleDelete={()=>workspaceSend({type:"ASK_DELETE"})}
138-
handleUpdate={()=>setIsConfirmingUpdate(true)}
146+
handleRestart={()=>{
147+
if(isWarningIgnored("restart")){
148+
restartWorkspace(workspace)
149+
}else{
150+
setIsConfirmingRestart(true)
151+
}
152+
}}
153+
handleUpdate={()=>{
154+
if(isWarningIgnored("update")){
155+
workspaceSend({type:"UPDATE"})
156+
}else{
157+
setIsConfirmingUpdate(true)
158+
}
159+
}}
139160
handleCancel={()=>workspaceSend({type:"CANCEL"})}
140161
handleSettings={()=>navigate("settings")}
141162
handleBuildRetry={()=>workspaceSend({type:"RETRY_BUILD"})}
@@ -202,11 +223,12 @@ export const WorkspaceReadyPage = ({
202223
})
203224
}}
204225
/>
205-
<ConfirmDialog
206-
type="info"
207-
hideCancel={false}
226+
<WarningDialog
208227
open={isConfirmingUpdate}
209-
onConfirm={()=>{
228+
onConfirm={(shouldIgnore)=>{
229+
if(shouldIgnore){
230+
ignoreWarning("update")
231+
}
210232
workspaceSend({type:"UPDATE"})
211233
setIsConfirmingUpdate(false)
212234
}}
@@ -215,6 +237,93 @@ export const WorkspaceReadyPage = ({
215237
confirmText="Update"
216238
description="Are you sure you want to update your workspace? Updating your workspace will stop all running processes and delete non-persistent data."
217239
/>
240+
241+
<WarningDialog
242+
open={isConfirmingRestart}
243+
onConfirm={(shouldIgnore)=>{
244+
if(shouldIgnore){
245+
ignoreWarning("restart")
246+
}
247+
restartWorkspace(workspace)
248+
setIsConfirmingRestart(false)
249+
}}
250+
onClose={()=>setIsConfirmingRestart(false)}
251+
title="Confirm restart"
252+
confirmText="Restart"
253+
description="Are you sure you want to restart your workspace? Updating your workspace will stop all running processes and delete non-persistent data."
254+
/>
218255
</>
219256
)
220257
}
258+
259+
typeIgnoredWarnings=Record<string,string>
260+
261+
constuseIgnoreWarnings=(prefix:string)=>{
262+
constignoredWarningsJSON=localStorage.getItem(`${prefix}_ignoredWarnings`)
263+
letignoredWarnings:IgnoredWarnings|undefined
264+
if(ignoredWarningsJSON){
265+
ignoredWarnings=JSON.parse(ignoredWarningsJSON)
266+
}
267+
268+
constisWarningIgnored=(warningId:string)=>{
269+
returnBoolean(ignoredWarnings?.[warningId])
270+
}
271+
272+
constignoreWarning=(warningId:string)=>{
273+
if(!ignoredWarnings){
274+
ignoredWarnings={}
275+
}
276+
ignoredWarnings[warningId]=newDate().toISOString()
277+
localStorage.setItem(
278+
`${prefix}_ignoredWarnings`,
279+
JSON.stringify(ignoredWarnings),
280+
)
281+
}
282+
283+
return{
284+
isWarningIgnored,
285+
ignoreWarning,
286+
}
287+
}
288+
289+
constWarningDialog:FC<
290+
Pick<
291+
ConfirmDialogProps,
292+
"open"|"onClose"|"title"|"confirmText"|"description"
293+
>&{onConfirm:(shouldIgnore:boolean)=>void}
294+
>=({ open, onConfirm, onClose, title, confirmText, description})=>{
295+
const[shouldIgnore,setShouldIgnore]=useState(false)
296+
297+
return(
298+
<ConfirmDialog
299+
type="info"
300+
hideCancel={false}
301+
open={open}
302+
onConfirm={()=>{
303+
onConfirm(shouldIgnore)
304+
}}
305+
onClose={onClose}
306+
title={title}
307+
confirmText={confirmText}
308+
description={
309+
<>
310+
<div>{description}</div>
311+
<FormControlLabel
312+
sx={{
313+
marginTop:2,
314+
}}
315+
control={
316+
<Checkbox
317+
size="small"
318+
onChange={(e)=>{
319+
setShouldIgnore(e.target.checked)
320+
}}
321+
/>
322+
}
323+
label="Don't show me this message again"
324+
/>
325+
</>
326+
}
327+
/>
328+
)
329+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp