|
7 | 7 | */ |
8 | 8 | import { createColumnHelper } from '@tanstack/react-table' |
9 | 9 | import { useCallback, useMemo, useState } from 'react' |
10 | | -import { useForm, type FieldValues } from 'react-hook-form' |
| 10 | +import { useForm } from 'react-hook-form' |
11 | 11 | import { Outlet } from 'react-router' |
12 | 12 |
|
13 | 13 | import { |
@@ -36,7 +36,6 @@ import { Button } from '~/ui/lib/Button' |
36 | 36 | import { toComboboxItems } from '~/ui/lib/Combobox' |
37 | 37 | import { EmptyMessage } from '~/ui/lib/EmptyMessage' |
38 | 38 | import { Message } from '~/ui/lib/Message' |
39 | | -import { Modal } from '~/ui/lib/Modal' |
40 | 39 | import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' |
41 | 40 | import { TableActions } from '~/ui/lib/Table' |
42 | 41 | import { docLinks } from '~/util/links' |
@@ -202,16 +201,21 @@ const PromoteImageModal = ({ onDismiss }: { onDismiss: () => void }) => { |
202 | 201 | ) |
203 | 202 | } |
204 | 203 |
|
| 204 | +type DemoteFormValues = { |
| 205 | + project: string | undefined |
| 206 | +} |
| 207 | + |
205 | 208 | const DemoteImageModal = ({ |
206 | 209 | onDismiss, |
207 | 210 | image, |
208 | 211 | }: { |
209 | 212 | onDismiss: () => void |
210 | 213 | image: Image |
211 | 214 | }) => { |
212 | | - const { control, handleSubmit, watch } = useForm() |
| 215 | + const defaultValues: DemoteFormValues = { project: undefined } |
| 216 | + const form = useForm({ defaultValues }) |
213 | 217 |
|
214 | | - const selectedProject: string | undefined = watch('project') |
| 218 | + const selectedProject: string | undefined = form.watch('project') |
215 | 219 |
|
216 | 220 | const queryClient = useApiQueryClient() |
217 | 221 |
|
@@ -239,51 +243,40 @@ const DemoteImageModal = ({ |
239 | 243 | onSettled: onDismiss, |
240 | 244 | }) |
241 | 245 |
|
242 | | - const onSubmit = (data: FieldValues) => { |
243 | | - demoteImage.mutate({ path: { image: image.id }, query: { project: data.project } }) |
244 | | - } |
245 | | - |
246 | 246 | const projects = useApiQuery('projectList', {}) |
247 | 247 | const projectItems = useMemo(() => toComboboxItems(projects.data?.items), [projects.data]) |
248 | 248 |
|
249 | 249 | return ( |
250 | | - <Modal isOpen onDismiss={onDismiss} title="Demote image"> |
251 | | - <Modal.Body> |
252 | | - <Modal.Section> |
253 | | - <form |
254 | | - autoComplete="off" |
255 | | - onSubmit={(e) => { |
256 | | - e.stopPropagation() |
257 | | - handleSubmit(onSubmit)(e) |
258 | | - }} |
259 | | - className="space-y-4" |
260 | | - > |
261 | | - <p> |
262 | | - Demoting: <span className="text-sans-semi-md text-raise">{image.name}</span> |
263 | | - </p> |
| 250 | + <ModalForm |
| 251 | + title="Demote image" |
| 252 | + form={form} |
| 253 | + loading={demoteImage.isPending} |
| 254 | + submitError={demoteImage.error} |
| 255 | + onSubmit={({ project }) => { |
| 256 | + if (!project) return // shouldn't happen because of validation |
| 257 | + demoteImage.mutate({ path: { image: image.id }, query: { project } }) |
| 258 | + }} |
| 259 | + onDismiss={onDismiss} |
| 260 | + submitLabel="Demote" |
| 261 | + > |
| 262 | + <p> |
| 263 | + Demoting: <span className="text-sans-semi-md text-raise">{image.name}</span> |
| 264 | + </p> |
264 | 265 |
|
265 | | - <Message |
266 | | - variant="info" |
267 | | - content="Once an image has been demoted it is only visible to the project that it is demoted into. This will not affect disks already created with the image." |
268 | | - /> |
| 266 | + <Message |
| 267 | + variant="info" |
| 268 | + content="Once an image has been demoted it is only visible to the project that it is demoted into. This will not affect disks already created with the image." |
| 269 | + /> |
269 | 270 |
|
270 | | - <ComboboxField |
271 | | - placeholder="Select project for image" |
272 | | - name="project" |
273 | | - label="Project" |
274 | | - items={projectItems} |
275 | | - isLoading={projects.isPending} |
276 | | - required |
277 | | - control={control} |
278 | | - /> |
279 | | - </form> |
280 | | - </Modal.Section> |
281 | | - </Modal.Body> |
282 | | - <Modal.Footer |
283 | | - onDismiss={onDismiss} |
284 | | - onAction={handleSubmit(onSubmit)} |
285 | | - actionText="Demote" |
| 271 | + <ComboboxField |
| 272 | + placeholder="Select project for image" |
| 273 | + name="project" |
| 274 | + label="Project" |
| 275 | + items={projectItems} |
| 276 | + isLoading={projects.isPending} |
| 277 | + required |
| 278 | + control={form.control} |
286 | 279 | /> |
287 | | - </Modal> |
| 280 | + </ModalForm> |
288 | 281 | ) |
289 | 282 | } |
0 commit comments