1
- import { useMachine } from "@xstate/react" ;
2
1
import { Alert } from "components/Alert/Alert" ;
3
2
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog" ;
4
3
import { Loader } from "components/Loader/Loader" ;
@@ -10,25 +9,38 @@ import {
10
9
} from "pages/WorkspaceSettingsPage/WorkspaceSchedulePage/schedule" ;
11
10
import { ttlMsToAutostop } from "pages/WorkspaceSettingsPage/WorkspaceSchedulePage/ttl" ;
12
11
import { useWorkspaceSettings } from "pages/WorkspaceSettingsPage/WorkspaceSettingsLayout" ;
13
- import { FC } from "react" ;
12
+ import { FC , useState } from "react" ;
14
13
import { Helmet } from "react-helmet-async" ;
15
- import { Navigate , useNavigate , useParams } from "react-router-dom" ;
14
+ import { useNavigate , useParams } from "react-router-dom" ;
16
15
import { pageTitle } from "utils/page" ;
17
16
import * as TypesGen from "api/typesGenerated" ;
18
17
import { workspaceByOwnerAndNameKey } from "api/queries/workspaces" ;
19
18
import { WorkspaceScheduleForm } from "./WorkspaceScheduleForm" ;
20
- import { workspaceSchedule } from "xServices/workspaceSchedule/workspaceScheduleXService" ;
21
19
import {
22
20
formValuesToAutostartRequest ,
23
21
formValuesToTTLRequest ,
24
22
} from "./formToRequest" ;
25
23
import { ErrorAlert } from "components/Alert/ErrorAlert" ;
26
- import { useQueryClient } from "react-query" ;
24
+ import { useMutation , useQuery , useQueryClient } from "react-query" ;
25
+ import { checkAuthorization } from "api/queries/authCheck" ;
26
+ import { templateByName } from "api/queries/templates" ;
27
+ import {
28
+ putWorkspaceAutostart ,
29
+ putWorkspaceAutostop ,
30
+ startWorkspace ,
31
+ } from "api/api" ;
27
32
28
- const getAutostart = ( workspace : TypesGen . Workspace ) =>
29
- scheduleToAutostart ( workspace . autostart_schedule ) ;
30
- const getAutostop = ( workspace : TypesGen . Workspace ) =>
31
- ttlMsToAutostop ( workspace . ttl_ms ) ;
33
+ const permissionsToCheck = ( workspace : TypesGen . Workspace ) =>
34
+ ( {
35
+ updateWorkspace : {
36
+ object : {
37
+ resource_type : "workspace" ,
38
+ resource_id : workspace . id ,
39
+ owner_id : workspace . owner_id ,
40
+ } ,
41
+ action : "update" ,
42
+ } ,
43
+ } ) as const ;
32
44
33
45
export const WorkspaceSchedulePage : FC = ( ) => {
34
46
const params = useParams ( ) as { username : string ; workspace : string } ;
@@ -37,24 +49,28 @@ export const WorkspaceSchedulePage: FC = () => {
37
49
const workspaceName = params . workspace ;
38
50
const queryClient = useQueryClient ( ) ;
39
51
const workspace = useWorkspaceSettings ( ) ;
40
- const [ scheduleState , scheduleSend ] = useMachine ( workspaceSchedule , {
41
- context : { workspace } ,
52
+ const { data : permissions , error : checkPermissionsError } = useQuery (
53
+ checkAuthorization ( { checks : permissionsToCheck ( workspace ) } ) ,
54
+ ) ;
55
+ const { data : template , error : getTemplateError } = useQuery (
56
+ templateByName ( workspace . organization_id , workspace . template_name ) ,
57
+ ) ;
58
+ const submitScheduleMutation = useMutation ( {
59
+ mutationFn : submitSchedule ,
60
+ onSuccess : async ( ) => {
61
+ await queryClient . invalidateQueries (
62
+ workspaceByOwnerAndNameKey ( params . username , params . workspace ) ,
63
+ ) ;
64
+ } ,
42
65
} ) ;
43
- const {
44
- checkPermissionsError,
45
- submitScheduleError,
46
- getTemplateError,
47
- permissions,
48
- template,
49
- } = scheduleState . context ;
50
-
51
- if ( ! username || ! workspaceName ) {
52
- return < Navigate to = "/workspaces" /> ;
53
- }
66
+ const error = checkPermissionsError || getTemplateError ;
67
+ const isLoading = ! template || ! permissions ;
54
68
55
- if ( scheduleState . matches ( "done" ) ) {
56
- return < Navigate to = { `/@${ username } /${ workspaceName } ` } /> ;
57
- }
69
+ const [ isConfirmingApply , setIsConfirmingApply ] = useState ( false ) ;
70
+ const { mutate : updateWorkspace } = useMutation ( {
71
+ mutationFn : ( ) =>
72
+ startWorkspace ( workspace . id , workspace . template_active_version_id ) ,
73
+ } ) ;
58
74
59
75
return (
60
76
< >
@@ -68,70 +84,99 @@ export const WorkspaceSchedulePage: FC = () => {
68
84
>
69
85
< PageHeaderTitle > Workspace Schedule</ PageHeaderTitle >
70
86
</ PageHeader >
71
- { ( scheduleState . hasTag ( "loading" ) || ! template ) && < Loader /> }
72
- { scheduleState . matches ( "error" ) && (
73
- < ErrorAlert error = { checkPermissionsError || getTemplateError } />
74
- ) }
87
+
88
+ { error && < ErrorAlert error = { error } /> }
89
+
90
+ { isLoading && < Loader /> }
91
+
75
92
{ permissions && ! permissions . updateWorkspace && (
76
93
< Alert severity = "error" >
77
94
You don't have permissions to update the schedule for this
78
95
workspace.
79
96
</ Alert >
80
97
) }
81
- { template &&
82
- workspace &&
83
- ( scheduleState . matches ( "presentForm" ) ||
84
- scheduleState . matches ( "submittingSchedule" ) ) && (
85
- < WorkspaceScheduleForm
86
- enableAutoStart = { template . allow_user_autostart }
87
- enableAutoStop = { template . allow_user_autostop }
88
- submitScheduleError = { submitScheduleError }
89
- initialValues = { {
90
- ...getAutostart ( workspace ) ,
91
- ...getAutostop ( workspace ) ,
92
- } }
93
- isLoading = { scheduleState . tags . has ( "loading" ) }
94
- defaultTTL = { dayjs . duration ( template . default_ttl_ms , "ms" ) . asHours ( ) }
95
- onCancel = { ( ) => {
96
- navigate ( `/@${ username } /${ workspaceName } ` ) ;
97
- } }
98
- onSubmit = { async ( values ) => {
99
- scheduleSend ( {
100
- type : "SUBMIT_SCHEDULE" ,
101
- autostart : formValuesToAutostartRequest ( values ) ,
102
- ttl : formValuesToTTLRequest ( values ) ,
103
- autostartChanged : scheduleChanged (
104
- getAutostart ( workspace ) ,
105
- values ,
106
- ) ,
107
- autostopChanged : scheduleChanged (
108
- getAutostop ( workspace ) ,
109
- values ,
110
- ) ,
111
- } ) ;
112
-
113
- await queryClient . invalidateQueries (
114
- workspaceByOwnerAndNameKey ( params . username , params . workspace ) ,
115
- ) ;
116
- } }
117
- />
118
- ) }
98
+
99
+ { template && (
100
+ < WorkspaceScheduleForm
101
+ enableAutoStart = { template . allow_user_autostart }
102
+ enableAutoStop = { template . allow_user_autostop }
103
+ submitScheduleError = { submitScheduleMutation . error }
104
+ initialValues = { {
105
+ ...getAutostart ( workspace ) ,
106
+ ...getAutostop ( workspace ) ,
107
+ } }
108
+ isLoading = { submitScheduleMutation . isLoading }
109
+ defaultTTL = { dayjs . duration ( template . default_ttl_ms , "ms" ) . asHours ( ) }
110
+ onCancel = { ( ) => {
111
+ navigate ( `/@${ username } /${ workspaceName } ` ) ;
112
+ } }
113
+ onSubmit = { async ( values ) => {
114
+ const data = {
115
+ workspace,
116
+ autostart : formValuesToAutostartRequest ( values ) ,
117
+ ttl : formValuesToTTLRequest ( values ) ,
118
+ autostartChanged : scheduleChanged (
119
+ getAutostart ( workspace ) ,
120
+ values ,
121
+ ) ,
122
+ autostopChanged : scheduleChanged ( getAutostop ( workspace ) , values ) ,
123
+ } ;
124
+
125
+ await submitScheduleMutation . mutateAsync ( data ) ;
126
+
127
+ if ( data . autostopChanged ) {
128
+ setIsConfirmingApply ( true ) ;
129
+ }
130
+ } }
131
+ />
132
+ ) }
133
+
119
134
< ConfirmDialog
120
- open = { scheduleState . matches ( "showingRestartDialog" ) }
135
+ open = { isConfirmingApply }
121
136
title = "Restart workspace?"
122
137
description = "Would you like to restart your workspace now to apply your new autostop setting, or let it apply after your next workspace start?"
123
138
confirmText = "Restart"
124
139
cancelText = "Apply later"
125
140
hideCancel = { false }
126
141
onConfirm = { ( ) => {
127
- scheduleSend ( "RESTART_WORKSPACE" ) ;
142
+ updateWorkspace ( ) ;
143
+ navigate ( `/@${ username } /${ workspaceName } ` ) ;
128
144
} }
129
145
onClose = { ( ) => {
130
- scheduleSend ( "APPLY_LATER" ) ;
146
+ navigate ( `/@ ${ username } / ${ workspaceName } ` ) ;
131
147
} }
132
148
/>
133
149
</ >
134
150
) ;
135
151
} ;
136
152
153
+ const getAutostart = ( workspace : TypesGen . Workspace ) =>
154
+ scheduleToAutostart ( workspace . autostart_schedule ) ;
155
+
156
+ const getAutostop = ( workspace : TypesGen . Workspace ) =>
157
+ ttlMsToAutostop ( workspace . ttl_ms ) ;
158
+
159
+ type SubmitScheduleData = {
160
+ workspace : TypesGen . Workspace ;
161
+ autostart : TypesGen . UpdateWorkspaceAutostartRequest ;
162
+ autostartChanged : boolean ;
163
+ ttl : TypesGen . UpdateWorkspaceTTLRequest ;
164
+ autostopChanged : boolean ;
165
+ } ;
166
+
167
+ const submitSchedule = async ( data : SubmitScheduleData ) => {
168
+ const { autostartChanged, workspace, autostart, autostopChanged, ttl } = data ;
169
+ const actions : Promise < void > [ ] = [ ] ;
170
+
171
+ if ( autostartChanged ) {
172
+ actions . push ( putWorkspaceAutostart ( workspace . id , autostart ) ) ;
173
+ }
174
+
175
+ if ( autostopChanged ) {
176
+ actions . push ( putWorkspaceAutostop ( workspace . id , ttl ) ) ;
177
+ }
178
+
179
+ return Promise . all ( actions ) ;
180
+ } ;
181
+
137
182
export default WorkspaceSchedulePage ;
0 commit comments