@@ -47,6 +47,11 @@ const MS_DAY_CONVERSION = 86400000;
47
47
const FAILURE_CLEANUP_DEFAULT = 7 ;
48
48
const INACTIVITY_CLEANUP_DEFAULT = 180 ;
49
49
const DORMANT_AUTODELETION_DEFAULT = 30 ;
50
+ /**
51
+ * The default form field space is 4 but since this form is quite heavy I think
52
+ * increase the space can make it feels lighter.
53
+ */
54
+ const FORM_FIELDS_SPACING = 6 ;
50
55
51
56
export interface TemplateScheduleForm {
52
57
template :Template ;
@@ -318,10 +323,10 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
318
323
aria-label = "Template settings form"
319
324
>
320
325
< FormSection
321
- title = "Schedule "
326
+ title = "Autostop "
322
327
description = "Define when workspaces created from this template are stopped."
323
328
>
324
- < Stack direction = "row" css = { styles . ttlFields } >
329
+ < FormFields spacing = { FORM_FIELDS_SPACING } >
325
330
< TextField
326
331
{ ...getFieldHelpers ( "default_ttl_ms" , {
327
332
helperText :(
@@ -347,11 +352,91 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
347
352
label = "Activity bump (hours)"
348
353
type = "number"
349
354
/>
350
- </ Stack >
355
+
356
+ < Stack direction = "row" css = { styles . ttlFields } >
357
+ < TextField
358
+ { ...getFieldHelpers ( "autostop_requirement_days_of_week" , {
359
+ helperText :(
360
+ < AutostopRequirementDaysHelperText
361
+ days = { form . values . autostop_requirement_days_of_week }
362
+ />
363
+ ) ,
364
+ } ) }
365
+ disabled = { isSubmitting }
366
+ fullWidth
367
+ select
368
+ value = { form . values . autostop_requirement_days_of_week }
369
+ label = "Days with required stop"
370
+ >
371
+ < MenuItem key = "off" value = "off" >
372
+ Off
373
+ </ MenuItem >
374
+ < MenuItem key = "daily" value = "daily" >
375
+ Daily
376
+ </ MenuItem >
377
+ < MenuItem key = "saturday" value = "saturday" >
378
+ Saturday
379
+ </ MenuItem >
380
+ < MenuItem key = "sunday" value = "sunday" >
381
+ Sunday
382
+ </ MenuItem >
383
+ </ TextField >
384
+
385
+ < TextField
386
+ { ...getFieldHelpers ( "autostop_requirement_weeks" , {
387
+ helperText :(
388
+ < AutostopRequirementWeeksHelperText
389
+ days = { form . values . autostop_requirement_days_of_week }
390
+ weeks = { form . values . autostop_requirement_weeks }
391
+ />
392
+ ) ,
393
+ } ) }
394
+ disabled = {
395
+ isSubmitting ||
396
+ ! [ "saturday" , "sunday" ] . includes (
397
+ form . values . autostop_requirement_days_of_week || "" ,
398
+ )
399
+ }
400
+ fullWidth
401
+ inputProps = { { min :1 , max :16 , step :1 } }
402
+ label = "Weeks between required stops"
403
+ type = "number"
404
+ />
405
+ </ Stack >
406
+
407
+ < Stack direction = "row" alignItems = "center" >
408
+ < Checkbox
409
+ id = "allow-user-autostop"
410
+ size = "small"
411
+ disabled = { isSubmitting || ! allowAdvancedScheduling }
412
+ onChange = { async ( ) => {
413
+ await form . setFieldValue (
414
+ "allow_user_autostop" ,
415
+ ! form . values . allow_user_autostop ,
416
+ ) ;
417
+ } }
418
+ name = "allow_user_autostop"
419
+ checked = { form . values . allow_user_autostop }
420
+ />
421
+ < Stack spacing = { 0.5 } >
422
+ < strong > Enforce these settings across all workspaces</ strong >
423
+ < span
424
+ css = { {
425
+ fontSize :12 ,
426
+ color :theme . palette . text . secondary ,
427
+ } }
428
+ >
429
+ Workspaces by default allow users to set custom autostop timers.
430
+ Use this to apply the template settings to all workspaces under
431
+ this template.
432
+ </ span >
433
+ </ Stack >
434
+ </ Stack >
435
+ </ FormFields >
351
436
</ FormSection >
352
437
353
438
< FormSection
354
- title = "Allow users scheduling "
439
+ title = "Autostart "
355
440
description = "Allow users to set custom autostart and autostop scheduling options for workspaces created from this template."
356
441
>
357
442
< Stack direction = "column" >
@@ -390,190 +475,101 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
390
475
} }
391
476
/>
392
477
) }
393
-
394
- < Stack direction = "row" alignItems = "center" >
395
- < Checkbox
396
- id = "allow-user-autostop"
397
- size = "small"
398
- disabled = { isSubmitting || ! allowAdvancedScheduling }
399
- onChange = { async ( ) => {
400
- await form . setFieldValue (
401
- "allow_user_autostop" ,
402
- ! form . values . allow_user_autostop ,
403
- ) ;
404
- } }
405
- name = "allow_user_autostop"
406
- checked = { form . values . allow_user_autostop }
407
- />
408
- < Stack spacing = { 0.5 } >
409
- < strong >
410
- Allow users to customize autostop duration for workspaces.
411
- </ strong >
412
- < span
413
- css = { {
414
- fontSize :12 ,
415
- color :theme . palette . text . secondary ,
416
- } }
417
- >
418
- Workspaces will always use the default TTL if this is set.
419
- </ span >
420
- </ Stack >
421
- </ Stack >
422
- </ Stack >
423
- </ FormSection >
424
-
425
- < FormSection
426
- title = "Autostop Requirement"
427
- description = "Define when workspaces created from this template are stopped periodically to enforce template updates and ensure idle workspaces are stopped."
428
- >
429
- < Stack direction = "row" css = { styles . ttlFields } >
430
- < TextField
431
- { ...getFieldHelpers ( "autostop_requirement_days_of_week" , {
432
- helperText :(
433
- < AutostopRequirementDaysHelperText
434
- days = { form . values . autostop_requirement_days_of_week }
435
- />
436
- ) ,
437
- } ) }
438
- disabled = { isSubmitting }
439
- fullWidth
440
- select
441
- value = { form . values . autostop_requirement_days_of_week }
442
- label = "Days with required stop"
443
- >
444
- < MenuItem key = "off" value = "off" >
445
- Off
446
- </ MenuItem >
447
- < MenuItem key = "daily" value = "daily" >
448
- Daily
449
- </ MenuItem >
450
- < MenuItem key = "saturday" value = "saturday" >
451
- Saturday
452
- </ MenuItem >
453
- < MenuItem key = "sunday" value = "sunday" >
454
- Sunday
455
- </ MenuItem >
456
- </ TextField >
457
-
458
- < TextField
459
- { ...getFieldHelpers ( "autostop_requirement_weeks" , {
460
- helperText :(
461
- < AutostopRequirementWeeksHelperText
462
- days = { form . values . autostop_requirement_days_of_week }
463
- weeks = { form . values . autostop_requirement_weeks }
464
- />
465
- ) ,
466
- } ) }
467
- disabled = {
468
- isSubmitting ||
469
- ! [ "saturday" , "sunday" ] . includes (
470
- form . values . autostop_requirement_days_of_week || "" ,
471
- )
472
- }
473
- fullWidth
474
- inputProps = { { min :1 , max :16 , step :1 } }
475
- label = "Weeks between required stops"
476
- type = "number"
477
- />
478
478
</ Stack >
479
479
</ FormSection >
480
480
481
481
{ allowAdvancedScheduling && (
482
482
< >
483
483
< FormSection
484
- title = "Failure Cleanup "
485
- description = "When enabled, Coder will attempt to stop workspacesthat are in a failed state after a specified number of days ."
484
+ title = "Dormancy "
485
+ description = "Coder's Dormancy Threshold determines when workspacesbecome dormant due to inactivity, requiring manual activation for access ."
486
486
>
487
- < FormFields >
488
- < FormControlLabel
489
- control = {
490
- < Switch
491
- name = "failureCleanupEnabled"
492
- checked = { form . values . failure_cleanup_enabled }
493
- onChange = { handleToggleFailureCleanup }
494
- />
495
- }
496
- label = "Enable Failure Cleanup"
497
- />
498
- < TextField
499
- { ...getFieldHelpers ( "failure_ttl_ms" , {
500
- helperText :(
501
- < FailureTTLHelperText ttl = { form . values . failure_ttl_ms } />
502
- ) ,
503
- } ) }
504
- disabled = { isSubmitting || ! form . values . failure_cleanup_enabled }
505
- fullWidth
506
- inputProps = { { min :0 , step :"any" } }
507
- label = "Time until cleanup (days)"
508
- type = "number"
509
- />
510
- </ FormFields >
511
- </ FormSection >
512
- < FormSection
513
- title = "Dormancy Threshold"
514
- description = "When enabled, Coder will mark workspaces as dormant after a period of time with no connections. Dormant workspaces can be auto-deleted (see below) or manually reviewed by the workspace owner or admins."
515
- >
516
- < FormFields >
517
- < FormControlLabel
518
- control = {
519
- < Switch
520
- name = "dormancyThreshold"
521
- checked = { form . values . inactivity_cleanup_enabled }
522
- onChange = { handleToggleInactivityCleanup }
523
- />
524
- }
525
- label = "Enable Dormancy Threshold"
526
- />
527
- < TextField
528
- { ...getFieldHelpers ( "time_til_dormant_ms" , {
529
- helperText :(
530
- < DormancyTTLHelperText
531
- ttl = { form . values . time_til_dormant_ms }
487
+ < FormFields spacing = { FORM_FIELDS_SPACING } >
488
+ < Stack >
489
+ < FormControlLabel
490
+ control = {
491
+ < Switch
492
+ name = "dormancyThreshold"
493
+ checked = { form . values . inactivity_cleanup_enabled }
494
+ onChange = { handleToggleInactivityCleanup }
532
495
/>
533
- ) ,
534
- } ) }
535
- disabled = {
536
- isSubmitting || ! form . values . inactivity_cleanup_enabled
537
- }
538
- fullWidth
539
- inputProps = { { min :0 , step :"any" } }
540
- label = "Time until dormant (days)"
541
- type = "number"
542
- />
543
- </ FormFields >
544
- </ FormSection >
545
- < FormSection
546
- title = "Dormancy Auto-Deletion"
547
- description = "When enabled, Coder will permanently delete dormant workspaces after a period of time. Once a workspace is deleted it cannot be recovered."
548
- >
549
- < FormFields >
550
- < FormControlLabel
551
- control = {
552
- < Switch
553
- name = "dormancyAutoDeletion"
554
- checked = { form . values . dormant_autodeletion_cleanup_enabled }
555
- onChange = { handleToggleDormantAutoDeletion }
556
- />
557
- }
558
- label = "Enable Dormancy Auto-Deletion"
559
- />
560
- < TextField
561
- { ...getFieldHelpers ( "time_til_dormant_autodelete_ms" , {
562
- helperText :(
563
- < DormancyAutoDeletionTTLHelperText
564
- ttl = { form . values . time_til_dormant_autodelete_ms }
496
+ }
497
+ label = "Enable Dormancy Threshold"
498
+ />
499
+ < TextField
500
+ { ...getFieldHelpers ( "time_til_dormant_ms" , {
501
+ helperText :(
502
+ < DormancyTTLHelperText
503
+ ttl = { form . values . time_til_dormant_ms }
504
+ />
505
+ ) ,
506
+ } ) }
507
+ disabled = {
508
+ isSubmitting || ! form . values . inactivity_cleanup_enabled
509
+ }
510
+ fullWidth
511
+ inputProps = { { min :0 , step :"any" } }
512
+ label = "Time until dormant (days)"
513
+ type = "number"
514
+ />
515
+ </ Stack >
516
+
517
+ < Stack >
518
+ < FormControlLabel
519
+ control = {
520
+ < Switch
521
+ name = "dormancyAutoDeletion"
522
+ checked = { form . values . dormant_autodeletion_cleanup_enabled }
523
+ onChange = { handleToggleDormantAutoDeletion }
524
+ />
525
+ }
526
+ label = "Enable Dormancy Auto-Deletion"
527
+ />
528
+ < TextField
529
+ { ...getFieldHelpers ( "time_til_dormant_autodelete_ms" , {
530
+ helperText :(
531
+ < DormancyAutoDeletionTTLHelperText
532
+ ttl = { form . values . time_til_dormant_autodelete_ms }
533
+ />
534
+ ) ,
535
+ } ) }
536
+ disabled = {
537
+ isSubmitting ||
538
+ ! form . values . dormant_autodeletion_cleanup_enabled
539
+ }
540
+ fullWidth
541
+ inputProps = { { min :0 , step :"any" } }
542
+ label = "Time until deletion (days)"
543
+ type = "number"
544
+ />
545
+ </ Stack >
546
+
547
+ < Stack >
548
+ < FormControlLabel
549
+ control = {
550
+ < Switch
551
+ name = "failureCleanupEnabled"
552
+ checked = { form . values . failure_cleanup_enabled }
553
+ onChange = { handleToggleFailureCleanup }
565
554
/>
566
- ) ,
567
- } ) }
568
- disabled = {
569
- isSubmitting ||
570
- ! form . values . dormant_autodeletion_cleanup_enabled
571
- }
572
- fullWidth
573
- inputProps = { { min :0 , step :"any" } }
574
- label = "Time until deletion (days)"
575
- type = "number"
576
- />
555
+ }
556
+ label = "Enable Failure Cleanup"
557
+ />
558
+ < TextField
559
+ { ...getFieldHelpers ( "failure_ttl_ms" , {
560
+ helperText :(
561
+ < FailureTTLHelperText ttl = { form . values . failure_ttl_ms } />
562
+ ) ,
563
+ } ) }
564
+ disabled = {
565
+ isSubmitting || ! form . values . failure_cleanup_enabled
566
+ }
567
+ fullWidth
568
+ inputProps = { { min :0 , step :"any" } }
569
+ label = "Time until cleanup (days)"
570
+ type = "number"
571
+ />
572
+ </ Stack >
577
573
</ FormFields >
578
574
</ FormSection >
579
575
</ >