1
1
import { type Interpolation , type Theme } from "@emotion/react" ;
2
2
import Link , { type LinkProps } from "@mui/material/Link" ;
3
3
import IconButton from "@mui/material/IconButton" ;
4
- import RemoveIcon from "@mui/icons-material/RemoveOutlined" ;
5
4
import AddIcon from "@mui/icons-material/AddOutlined" ;
5
+ import RemoveIcon from "@mui/icons-material/RemoveOutlined" ;
6
+ import ScheduleOutlined from "@mui/icons-material/ScheduleOutlined" ;
6
7
import Tooltip from "@mui/material/Tooltip" ;
7
8
import { visuallyHidden } from "@mui/utils" ;
8
9
import { type Dayjs } from "dayjs" ;
@@ -25,16 +26,54 @@ import {
25
26
updateDeadline ,
26
27
workspaceByOwnerAndNameKey ,
27
28
} from "api/queries/workspaces" ;
29
+ import { TopbarData , TopbarIcon } from "components/FullPageLayout/Topbar" ;
28
30
import { displayError , displaySuccess } from "components/GlobalSnackbar/utils" ;
31
+ import type { WorkspaceActivityStatus } from "modules/workspaces/activity" ;
32
+
33
+ export interface WorkspaceScheduleProps {
34
+ status : WorkspaceActivityStatus ;
35
+ workspace : Workspace ;
36
+ template : Template ;
37
+ canUpdateWorkspace : boolean ;
38
+ }
39
+
40
+ export const WorkspaceSchedule : FC < WorkspaceScheduleProps > = ( {
41
+ status,
42
+ workspace,
43
+ template,
44
+ canUpdateWorkspace,
45
+ } ) => {
46
+ if ( ! shouldDisplayScheduleControls ( workspace , status ) ) {
47
+ return null ;
48
+ }
49
+
50
+ return (
51
+ < TopbarData >
52
+ < TopbarIcon >
53
+ < Tooltip title = "Schedule" >
54
+ < ScheduleOutlined aria-label = "Schedule" />
55
+ </ Tooltip >
56
+ </ TopbarIcon >
57
+ < WorkspaceScheduleControls
58
+ workspace = { workspace }
59
+ status = { status }
60
+ template = { template }
61
+ canUpdateSchedule = { canUpdateWorkspace }
62
+ />
63
+ </ TopbarData >
64
+ ) ;
65
+ } ;
29
66
30
67
export interface WorkspaceScheduleControlsProps {
31
68
workspace : Workspace ;
69
+ status : WorkspaceActivityStatus ;
32
70
template : Template ;
33
71
canUpdateSchedule : boolean ;
34
72
}
35
73
36
74
export const WorkspaceScheduleControls : FC < WorkspaceScheduleControlsProps > = ( {
37
75
workspace,
76
+ status,
38
77
template,
39
78
canUpdateSchedule,
40
79
} ) => {
@@ -92,7 +131,11 @@ export const WorkspaceScheduleControls: FC<WorkspaceScheduleControlsProps> = ({
92
131
return (
93
132
< div css = { styles . scheduleValue } data-testid = "schedule-controls" >
94
133
{ isWorkspaceOn ( workspace ) ? (
95
- < AutoStopDisplay workspace = { workspace } template = { template } />
134
+ < AutoStopDisplay
135
+ workspace = { workspace }
136
+ status = { status }
137
+ template = { template }
138
+ />
96
139
) : (
97
140
< ScheduleSettingsLink >
98
141
Starts at { autostartDisplay ( workspace . autostart_schedule ) }
@@ -135,18 +178,27 @@ export const WorkspaceScheduleControls: FC<WorkspaceScheduleControlsProps> = ({
135
178
136
179
interface AutoStopDisplayProps {
137
180
workspace : Workspace ;
181
+ status : WorkspaceActivityStatus ;
138
182
template : Template ;
139
183
}
140
184
141
- const AutoStopDisplay : FC < AutoStopDisplayProps > = ( { workspace, template } ) => {
185
+ const AutoStopDisplay : FC < AutoStopDisplayProps > = ( {
186
+ workspace,
187
+ status,
188
+ template,
189
+ } ) => {
142
190
useTime ( ) ;
143
- const { message, tooltip } = autostopDisplay ( workspace , template ) ;
191
+ const { message, tooltip, danger } = autostopDisplay (
192
+ workspace ,
193
+ status ,
194
+ template ,
195
+ ) ;
144
196
145
197
const display = (
146
198
< ScheduleSettingsLink
147
199
data-testid = "schedule-controls-autostop"
148
200
css = {
149
- isShutdownSoon ( workspace ) &&
201
+ danger &&
150
202
( ( theme ) => ( {
151
203
color : `${ theme . roles . danger . fill . outline } !important` ,
152
204
} ) )
@@ -196,22 +248,13 @@ export const canEditDeadline = (workspace: Workspace): boolean => {
196
248
197
249
export const shouldDisplayScheduleControls = (
198
250
workspace : Workspace ,
251
+ status : WorkspaceActivityStatus ,
199
252
) : boolean => {
200
253
const willAutoStop = isWorkspaceOn ( workspace ) && hasDeadline ( workspace ) ;
201
254
const willAutoStart = ! isWorkspaceOn ( workspace ) && hasAutoStart ( workspace ) ;
202
- return willAutoStop || willAutoStart ;
203
- } ;
204
-
205
- const isShutdownSoon = ( workspace : Workspace ) : boolean => {
206
- const deadline = workspace . latest_build . deadline ;
207
- if ( ! deadline ) {
208
- return false ;
209
- }
210
- const deadlineDate = new Date ( deadline ) ;
211
- const now = new Date ( ) ;
212
- const diff = deadlineDate . getTime ( ) - now . getTime ( ) ;
213
- const oneHour = 1000 * 60 * 60 ;
214
- return diff < oneHour ;
255
+ const hasActivity =
256
+ status === "connected" && ! workspace . latest_build . max_deadline ;
257
+ return ( willAutoStop || willAutoStart ) && ! hasActivity ;
215
258
} ;
216
259
217
260
const styles = {
0 commit comments