7
7
*/
8
8
import * as Accordion from '@radix-ui/react-accordion'
9
9
import cn from 'classnames'
10
- import { useEffect , useRef , useState } from 'react'
10
+ import { useEffect , useMemo , useRef , useState } from 'react'
11
11
import { useWatch , type Control } from 'react-hook-form'
12
12
import { useNavigate , type LoaderFunctionArgs } from 'react-router-dom'
13
13
import type { SetRequired } from 'type-fest'
@@ -25,19 +25,15 @@ import {
25
25
import {
26
26
DirectionRightIcon ,
27
27
EmptyMessage ,
28
- FieldLabel ,
29
28
FormDivider ,
30
29
Images16Icon ,
31
30
Instances24Icon ,
32
- Key16Icon ,
33
31
Message ,
34
32
RadioCard ,
35
- Table ,
36
33
Tabs ,
37
34
TextInputHint ,
38
- Truncate ,
39
35
} from '@oxide/ui'
40
- import { formatDateTime , GiB , invariant } from '@oxide/util'
36
+ import { GiB , invariant } from '@oxide/util'
41
37
42
38
import {
43
39
CheckboxField ,
@@ -51,6 +47,7 @@ import {
51
47
NameField ,
52
48
NetworkInterfaceField ,
53
49
RadioFieldDyn ,
50
+ SshKeysField ,
54
51
TextField ,
55
52
type DiskTableItem ,
56
53
} from 'app/components/form'
@@ -69,6 +66,8 @@ export type InstanceCreateInput = Assign<
69
66
bootDiskSize : number
70
67
image : string
71
68
userData : File | null
69
+ // ssh keys are always specified. we do not need the undefined case
70
+ sshPublicKeys : NonNullable < InstanceCreate [ 'sshPublicKeys' ] >
72
71
}
73
72
>
74
73
@@ -91,6 +90,8 @@ const baseDefaultValues: InstanceCreateInput = {
91
90
disks : [ ] ,
92
91
networkInterfaces : { type : 'default' } ,
93
92
93
+ sshPublicKeys : [ ] ,
94
+
94
95
start : true ,
95
96
96
97
userData : null ,
@@ -135,9 +136,13 @@ export function CreateInstanceForm() {
135
136
136
137
const defaultImage = allImages [ 0 ]
137
138
139
+ const { data : sshKeys } = usePrefetchedApiQuery ( 'currentUserSshKeyList' , { } )
140
+ const allKeys = useMemo ( ( ) => sshKeys . items . map ( ( key ) => key . id ) , [ sshKeys ] )
141
+
138
142
const defaultValues : InstanceCreateInput = {
139
143
...baseDefaultValues ,
140
144
image : defaultImage ?. id || '' ,
145
+ sshPublicKeys : allKeys ,
141
146
// Use 2x the image size as the default boot disk size
142
147
bootDiskSize : Math . ceil ( defaultImage ?. size / GiB ) * 2 || 10 ,
143
148
}
@@ -210,6 +215,7 @@ export function CreateInstanceForm() {
210
215
externalIps : [ { type : 'ephemeral' } ] ,
211
216
start : values . start ,
212
217
networkInterfaces : values . networkInterfaces ,
218
+ sshPublicKeys : values . sshPublicKeys ,
213
219
userData,
214
220
} ,
215
221
} )
@@ -417,7 +423,7 @@ export function CreateInstanceForm() {
417
423
< FormDivider />
418
424
< Form . Heading id = "authentication" > Authentication</ Form . Heading >
419
425
420
- < SshKeysTable />
426
+ < SshKeysField control = { control } />
421
427
422
428
< FormDivider />
423
429
< Form . Heading id = "advanced" > Advanced</ Form . Heading >
@@ -517,70 +523,6 @@ function AccordionItem({ value, label, children, isOpen }: AccordionItemProps) {
517
523
)
518
524
}
519
525
520
- const SshKeysTable = ( ) => {
521
- const keys = usePrefetchedApiQuery ( 'currentUserSshKeyList' , { } ) . data ?. items || [ ]
522
-
523
- return (
524
- < div className = "max-w-lg" >
525
- < div className = "mb-2" >
526
- < FieldLabel id = "ssh-keys-label" > SSH keys</ FieldLabel >
527
- < TextInputHint id = "ssh-keys-label-help-text" >
528
- SSH keys can be added and removed in your user settings
529
- </ TextInputHint >
530
- </ div >
531
-
532
- { keys . length > 0 ? (
533
- < Table className = "w-full" >
534
- < Table . Header >
535
- < Table . HeaderRow >
536
- < Table . HeadCell > Name</ Table . HeadCell >
537
- < Table . HeadCell > Created</ Table . HeadCell >
538
- </ Table . HeaderRow >
539
- </ Table . Header >
540
- < Table . Body >
541
- { keys . map ( ( key ) => (
542
- < Table . Row key = { key . id } >
543
- < Table . Cell height = "auto" >
544
- < Truncate text = { key . name } maxLength = { 28 } />
545
- </ Table . Cell >
546
- < Table . Cell height = "auto" className = "text-secondary" >
547
- { formatDateTime ( key . timeCreated ) }
548
- </ Table . Cell >
549
- </ Table . Row >
550
- ) ) }
551
- </ Table . Body >
552
- </ Table >
553
- ) : (
554
- < div className = "mb-4 flex max-w-lg items-center justify-center rounded-lg border p-6 border-default" >
555
- < EmptyMessage
556
- icon = { < Key16Icon /> }
557
- title = "No SSH keys"
558
- body = "You need to add a SSH key to be able to see it here"
559
- />
560
- </ div >
561
- ) }
562
-
563
- < Message
564
- variant = "notice"
565
- content = {
566
- < >
567
- If your image supports the cidata volume and{ ' ' }
568
- < a
569
- target = "_blank"
570
- href = "https://cloudinit.readthedocs.io/en/latest/"
571
- rel = "noreferrer"
572
- >
573
- cloud-init
574
- </ a >
575
- , the keys above will be added to your instance. Keys are added when the
576
- instance is created and are not updated after instance launch.
577
- </ >
578
- }
579
- />
580
- </ div >
581
- )
582
- }
583
-
584
526
const renderLargeRadioCards = ( category : string ) => {
585
527
return PRESETS . filter ( ( option ) => option . category === category ) . map ( ( option ) => (
586
528
< RadioCard key = { option . id } value = { option . id } >
0 commit comments