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

Commit18a6810

Browse files
Kira-Pilotkylecarbs
authored andcommitted
feat: show deleted workspace after delete action (#2208)
* added deleted workspace banner* x state pass* added include_deleted param* clean up x state* added teests* cleaning up unneeded xstate service
1 parenta194365 commit18a6810

File tree

9 files changed

+144
-11
lines changed

9 files changed

+144
-11
lines changed

‎site/src/api/api.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,11 @@ export const getTemplateVersionResources = async (versionId: string): Promise<Ty
108108
returnresponse.data
109109
}
110110

111-
exportconstgetWorkspace=async(workspaceId:string):Promise<TypesGen.Workspace>=>{
112-
constresponse=awaitaxios.get<TypesGen.Workspace>(`/api/v2/workspaces/${workspaceId}`)
111+
exportconstgetWorkspace=async(
112+
workspaceId:string,
113+
params?:TypesGen.WorkspaceOptions,
114+
):Promise<TypesGen.Workspace>=>{
115+
constresponse=awaitaxios.get<TypesGen.Workspace>(`/api/v2/workspaces/${workspaceId}`,{ params})
113116
returnresponse.data
114117
}
115118

@@ -141,8 +144,11 @@ export const getWorkspaces = async (filter?: TypesGen.WorkspaceFilter): Promise<
141144
exportconstgetWorkspaceByOwnerAndName=async(
142145
username="me",
143146
workspaceName:string,
147+
params?:TypesGen.WorkspaceByOwnerAndNameParams,
144148
):Promise<TypesGen.Workspace>=>{
145-
constresponse=awaitaxios.get<TypesGen.Workspace>(`/api/v2/users/${username}/workspace/${workspaceName}`)
149+
constresponse=awaitaxios.get<TypesGen.Workspace>(`/api/v2/users/${username}/workspace/${workspaceName}`,{
150+
params,
151+
})
146152
returnresponse.data
147153
}
148154

‎site/src/components/Workspace/Workspace.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import{makeStyles}from"@material-ui/core/styles"
22
import{FC}from"react"
3+
import{useNavigate}from"react-router-dom"
34
import*asTypesGenfrom"../../api/typesGenerated"
45
import{BuildsTable}from"../BuildsTable/BuildsTable"
56
import{Margins}from"../Margins/Margins"
67
import{PageHeader,PageHeaderSubtitle,PageHeaderTitle}from"../PageHeader/PageHeader"
78
import{Resources}from"../Resources/Resources"
89
import{Stack}from"../Stack/Stack"
910
import{WorkspaceActions}from"../WorkspaceActions/WorkspaceActions"
11+
import{WorkspaceDeletedBanner}from"../WorkspaceDeletedBanner/WorkspaceDeletedBanner"
1012
import{WorkspaceSchedule}from"../WorkspaceSchedule/WorkspaceSchedule"
1113
import{WorkspaceScheduleBanner}from"../WorkspaceScheduleBanner/WorkspaceScheduleBanner"
1214
import{WorkspaceSection}from"../WorkspaceSection/WorkspaceSection"
@@ -44,6 +46,7 @@ export const Workspace: FC<WorkspaceProps> = ({
4446
builds,
4547
})=>{
4648
conststyles=useStyles()
49+
constnavigate=useNavigate()
4750

4851
return(
4952
<Margins>
@@ -72,9 +75,13 @@ export const Workspace: FC<WorkspaceProps> = ({
7275
workspace={workspace}
7376
/>
7477

78+
<WorkspaceDeletedBannerworkspace={workspace}handleClick={()=>navigate(`/workspaces/new`)}/>
79+
7580
<WorkspaceStatsworkspace={workspace}/>
7681

77-
<Resourcesresources={resources}getResourcesError={getResourcesError}workspace={workspace}/>
82+
{!!resources&&!!resources.length&&(
83+
<Resourcesresources={resources}getResourcesError={getResourcesError}workspace={workspace}/>
84+
)}
7885

7986
<WorkspaceSectiontitle="Timeline"contentsProps={{className:styles.timelineContents}}>
8087
<BuildsTablebuilds={builds}className={styles.timelineTable}/>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import{action}from"@storybook/addon-actions"
2+
import{Story}from"@storybook/react"
3+
import*asMocksfrom"../../testHelpers/entities"
4+
import{WorkspaceDeletedBanner,WorkspaceDeletedBannerProps}from"./WorkspaceDeletedBanner"
5+
6+
exportdefault{
7+
title:"components/WorkspaceDeletedBanner",
8+
component:WorkspaceDeletedBanner,
9+
}
10+
11+
constTemplate:Story<WorkspaceDeletedBannerProps>=(args)=><WorkspaceDeletedBanner{...args}/>
12+
13+
exportconstExample=Template.bind({})
14+
Example.args={
15+
handleClick:action("extend"),
16+
workspace:{
17+
...Mocks.MockWorkspace,
18+
19+
latest_build:{
20+
...Mocks.MockWorkspaceBuild,
21+
job:{
22+
...Mocks.MockProvisionerJob,
23+
status:"succeeded",
24+
},
25+
transition:"delete",
26+
},
27+
},
28+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
importButtonfrom"@material-ui/core/Button"
2+
import{makeStyles}from"@material-ui/core/styles"
3+
importAlertfrom"@material-ui/lab/Alert"
4+
importAlertTitlefrom"@material-ui/lab/AlertTitle"
5+
import{FC}from"react"
6+
import*asTypesGenfrom"../../api/typesGenerated"
7+
import{isWorkspaceDeleted}from"../../util/workspace"
8+
9+
constLanguage={
10+
bannerTitle:"This workspace has been deleted and cannot be edited.",
11+
createWorkspaceCta:"Create new workspace",
12+
}
13+
14+
exportinterfaceWorkspaceDeletedBannerProps{
15+
workspace:TypesGen.Workspace
16+
handleClick:()=>void
17+
}
18+
19+
exportconstWorkspaceDeletedBanner:FC<WorkspaceDeletedBannerProps>=({ workspace, handleClick})=>{
20+
conststyles=useStyles()
21+
22+
if(!isWorkspaceDeleted(workspace)){
23+
returnnull
24+
}
25+
26+
return(
27+
<Alert
28+
className={styles.root}
29+
action={
30+
<Buttoncolor="inherit"onClick={handleClick}size="small">
31+
{Language.createWorkspaceCta}
32+
</Button>
33+
}
34+
severity="warning"
35+
>
36+
<AlertTitle>{Language.bannerTitle}</AlertTitle>
37+
</Alert>
38+
)
39+
}
40+
41+
exportconstuseStyles=makeStyles(()=>{
42+
return{
43+
root:{
44+
alignItems:"center",
45+
"& .MuiAlertTitle-root":{
46+
marginBottom:"0px",
47+
},
48+
},
49+
}
50+
})

‎site/src/components/WorkspaceScheduleBanner/WorkspaceScheduleBanner.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const shouldDisplay = (workspace: TypesGen.Workspace): boolean => {
2626
if(!isWorkspaceOn(workspace)){
2727
returnfalse
2828
}else{
29-
// amannual shutdown has a deadline of '"0001-01-01T00:00:00Z"'
29+
// amanual shutdown has a deadline of '"0001-01-01T00:00:00Z"'
3030
// SEE: #1834
3131
constdeadline=dayjs(workspace.latest_build.deadline).utc()
3232
consthasDeadline=deadline.year()>1

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import{useMachine}from"@xstate/react"
22
importReact,{useEffect}from"react"
33
import{Helmet}from"react-helmet"
4-
import{useNavigate,useParams}from"react-router-dom"
4+
import{useParams}from"react-router-dom"
55
import{DeleteWorkspaceDialog}from"../../components/DeleteWorkspaceDialog/DeleteWorkspaceDialog"
66
import{ErrorSummary}from"../../components/ErrorSummary/ErrorSummary"
77
import{FullScreenLoader}from"../../components/Loader/FullScreenLoader"
@@ -13,7 +13,6 @@ import { workspaceScheduleBannerMachine } from "../../xServices/workspaceSchedul
1313

1414
exportconstWorkspacePage:React.FC=()=>{
1515
const{username:usernameQueryParam,workspace:workspaceQueryParam}=useParams()
16-
constnavigate=useNavigate()
1716
constusername=firstOrItem(usernameQueryParam,null)
1817
constworkspaceName=firstOrItem(workspaceQueryParam,null)
1918

@@ -63,7 +62,6 @@ export const WorkspacePage: React.FC = () => {
6362
handleCancel={()=>workspaceSend("CANCEL_DELETE")}
6463
handleConfirm={()=>{
6564
workspaceSend("DELETE")
66-
navigate("/workspaces")
6765
}}
6866
/>
6967
</>

‎site/src/util/workspace.test.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
importdayjsfrom"dayjs"
22
import*asTypesGenfrom"../api/typesGenerated"
33
import*asMocksfrom"../testHelpers/entities"
4-
import{defaultWorkspaceExtension,isWorkspaceOn,workspaceQueryToFilter}from"./workspace"
4+
import{defaultWorkspaceExtension,isWorkspaceDeleted,isWorkspaceOn,workspaceQueryToFilter}from"./workspace"
55

66
describe("util > workspace",()=>{
77
describe("isWorkspaceOn",()=>{
@@ -42,6 +42,44 @@ describe("util > workspace", () => {
4242
})
4343
})
4444

45+
describe("isWorkspaceDeleted",()=>{
46+
it.each<[TypesGen.WorkspaceTransition,TypesGen.ProvisionerJobStatus,boolean]>([
47+
["delete","canceled",false],
48+
["delete","canceling",false],
49+
["delete","failed",false],
50+
["delete","pending",false],
51+
["delete","running",false],
52+
["delete","succeeded",true],
53+
54+
["stop","canceled",false],
55+
["stop","canceling",false],
56+
["stop","failed",false],
57+
["stop","pending",false],
58+
["stop","running",false],
59+
["stop","succeeded",false],
60+
61+
["start","canceled",false],
62+
["start","canceling",false],
63+
["start","failed",false],
64+
["start","pending",false],
65+
["start","running",false],
66+
["start","succeeded",false],
67+
])(`transition=%p, status=%p, isWorkspaceDeleted=%p`,(transition,status,isDeleted)=>{
68+
constworkspace:TypesGen.Workspace={
69+
...Mocks.MockWorkspace,
70+
latest_build:{
71+
...Mocks.MockWorkspaceBuild,
72+
job:{
73+
...Mocks.MockProvisionerJob,
74+
status,
75+
},
76+
transition,
77+
},
78+
}
79+
expect(isWorkspaceDeleted(workspace)).toBe(isDeleted)
80+
})
81+
})
82+
4583
describe("defaultWorkspaceExtension",()=>{
4684
it.each<[string,TypesGen.PutExtendWorkspaceRequest]>([
4785
[

‎site/src/util/workspace.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ export const isWorkspaceOn = (workspace: TypesGen.Workspace): boolean => {
249249
returntransition==="start"&&status==="succeeded"
250250
}
251251

252+
exportconstisWorkspaceDeleted=(workspace:TypesGen.Workspace):boolean=>{
253+
returngetWorkspaceStatus(workspace.latest_build)===succeededToStatus["delete"]
254+
}
255+
252256
exportconstdefaultWorkspaceExtension=(__startDate?:dayjs.Dayjs):TypesGen.PutExtendWorkspaceRequest=>{
253257
constnow=__startDate ?dayjs(__startDate) :dayjs()
254258
constfourHoursFromNow=now.add(4,"hours").utc()

‎site/src/xServices/workspace/workspaceXService.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ export const workspaceMachine = createMachine(
431431
},
432432
services:{
433433
getWorkspace:async(_,event)=>{
434-
returnawaitAPI.getWorkspaceByOwnerAndName(event.username,event.workspaceName)
434+
returnawaitAPI.getWorkspaceByOwnerAndName(event.username,event.workspaceName,{include_deleted:true})
435435
},
436436
getTemplate:async(context)=>{
437437
if(context.workspace){
@@ -470,7 +470,9 @@ export const workspaceMachine = createMachine(
470470
},
471471
refreshWorkspace:async(context)=>{
472472
if(context.workspace){
473-
returnawaitAPI.getWorkspaceByOwnerAndName(context.workspace.owner_name,context.workspace.name)
473+
returnawaitAPI.getWorkspaceByOwnerAndName(context.workspace.owner_name,context.workspace.name,{
474+
include_deleted:true,
475+
})
474476
}else{
475477
throwError("Cannot refresh workspace without id")
476478
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp