Skip to content

Commit 1f8ebf2

Browse files
authored
Revert all app changes since v6 except two small fixes (#1958)
Revert all app changes since v6 (e5a1f80)
1 parent b454cef commit 1f8ebf2

File tree

29 files changed

+5727
-5052
lines changed

29 files changed

+5727
-5052
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"rules": {
6767
"playwright/expect-expect": [
6868
"warn",
69-
{ "assertFunctionNames": ["expectVisible", "expectRowVisible"] }
69+
{ "additionalAssertFunctionNames": ["expectVisible", "expectRowVisible"] }
7070
]
7171
}
7272
}

app/components/NoLicense2.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
5+
*
6+
* Copyright Oxide Computer Company
7+
*/
8+
9+
export function NoLicenseHere() {
10+
return null
11+
}

app/components/ThemeIcons.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
5+
*
6+
* Copyright Oxide Computer Company
7+
*/
8+
9+
// TODO: Figure out a better place to put this?
10+
11+
export const LightTheme = () => (
12+
<svg
13+
width="237"
14+
height="137"
15+
viewBox="0 0 237 137"
16+
fill="none"
17+
xmlns="http://www.w3.org/2000/svg"
18+
>
19+
<rect width="237" height="137" rx="1" fill="#DBDBDC" />
20+
<rect x="60" y="16" width="59" height="6" rx="1" fill="#141A1C" />
21+
<rect opacity="0.6" x="60" y="37" width="161" height="12" rx="1" fill="#48D597" />
22+
<rect x="108" y="77" width="113" height="12" rx="1" fill="#AEB0B2" />
23+
<rect x="108" y="61" width="113" height="12" rx="1" fill="#AEB0B2" />
24+
<rect x="108" y="93" width="113" height="12" rx="1" fill="#AEB0B2" />
25+
<rect x="60" y="61" width="32" height="32" rx="1" fill="#AEB0B2" />
26+
<line x1="45.5" y1="2.18557e-08" x2="45.5" y2="137" stroke="#AEB0B2" />
27+
</svg>
28+
)
29+
30+
export const DarkTheme = () => (
31+
<svg
32+
width="237"
33+
height="137"
34+
viewBox="0 0 237 137"
35+
fill="none"
36+
xmlns="http://www.w3.org/2000/svg"
37+
>
38+
<rect width="237" height="137" rx="1" fill="#080F11" />
39+
<line x1="45.5" y1="-2.18557e-08" x2="45.5" y2="138" stroke="#1C2325" />
40+
<rect x="60" y="16" width="59" height="6" rx="1" fill="#2E8160" />
41+
<rect x="60" y="37" width="161" height="12" rx="1" fill="#102422" />
42+
<rect x="108" y="77" width="113" height="12" rx="1" fill="#1C2325" />
43+
<rect x="108" y="61" width="113" height="12" rx="1" fill="#1C2325" />
44+
<rect x="108" y="93" width="113" height="12" rx="1" fill="#1C2325" />
45+
</svg>
46+
)

app/components/form/FullPageForm.tsx

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
import { cloneElement, useEffect, type ReactElement, type ReactNode } from 'react'
99
import type { FieldValues, UseFormReturn } from 'react-hook-form'
10-
import { useBlocker, type Blocker } from 'react-router-dom'
10+
import { useBlocker, type unstable_Blocker as Blocker } from 'react-router-dom'
1111

1212
import type { ApiError } from '@oxide/api'
1313
import { Modal, PageHeader, PageTitle } from '@oxide/ui'
@@ -25,11 +25,7 @@ interface FullPageFormProps<TFieldValues extends FieldValues> {
2525
error?: Error
2626
form: UseFormReturn<TFieldValues>
2727
loading?: boolean
28-
/**
29-
* Use await mutateAsync(), otherwise you'll break the logic below that relies
30-
* on knowing when the submit is done.
31-
*/
32-
onSubmit: (values: TFieldValues) => Promise<void>
28+
onSubmit: (values: TFieldValues) => void
3329
/** Error from the API call */
3430
submitError: ApiError | null
3531
/**
@@ -57,25 +53,22 @@ export function FullPageForm<TFieldValues extends FieldValues>({
5753
onSubmit,
5854
submitError,
5955
}: FullPageFormProps<TFieldValues>) {
60-
const { isSubmitting, isDirty, isSubmitSuccessful } = form.formState
56+
const { isSubmitting, isDirty } = form.formState
6157

62-
// Confirms with the user if they want to navigate away if the form is
63-
// dirty. Does not intercept everything e.g. refreshes or closing the tab
64-
// but serves to reduce the possibility of a user accidentally losing their
65-
// progress.
66-
const blocker = useBlocker(isDirty && !isSubmitSuccessful)
58+
/*
59+
Confirms with the user if they want to navigate away
60+
if the form is dirty. Does not intercept everything e.g.
61+
refreshes or closing the tab but serves to reduce
62+
the possibility of a user accidentally losing their progress
63+
*/
64+
const blocker = useBlocker(isDirty)
6765

68-
// Gating on !isSubmitSuccessful above makes the blocker stop blocking nav
69-
// after a successful submit. However, this can take a little time (there is a
70-
// render in between when isSubmitSuccessful is true but the blocker is still
71-
// ready to block), so we also have this useEffect that lets blocked requests
72-
// through if submit is succesful but the blocker hasn't gotten a chance to
73-
// stop blocking yet.
66+
// Reset blocker if form is no longer dirty
7467
useEffect(() => {
75-
if (blocker.state === 'blocked' && isSubmitSuccessful) {
76-
blocker.proceed()
68+
if (blocker.state === 'blocked' && !isDirty) {
69+
blocker.reset()
7770
}
78-
}, [blocker, isSubmitSuccessful])
71+
}, [blocker, isDirty])
7972

8073
const childArray = flattenChildren(children)
8174
const actions = pluckFirstOfType(childArray, Form.Actions)
@@ -88,27 +81,24 @@ export function FullPageForm<TFieldValues extends FieldValues>({
8881
<form
8982
className="ox-form pb-20"
9083
id={id}
91-
onSubmit={async (e) => {
84+
onSubmit={(e) => {
9285
// This modal being in a portal doesn't prevent the submit event
9386
// from bubbling up out of the portal. Normally that's not a
9487
// problem, but sometimes (e.g., instance create) we render the
9588
// SideModalForm from inside another form, in which case submitting
9689
// the inner form submits the outer form unless we stop propagation
9790
e.stopPropagation()
98-
// Important to await here so isSubmitSuccessful doesn't become true
99-
// until the submit is actually successful. Note you must use await
100-
// mutateAsync() inside onSubmit in order to make this wait
101-
await form.handleSubmit(onSubmit)(e)
91+
// This resets `isDirty` whilst keeping the values meaning
92+
// we are not prevented from navigating away by the blocker
93+
form.reset({} as TFieldValues, { keepValues: true })
94+
form.handleSubmit(onSubmit)(e)
10295
}}
10396
autoComplete="off"
10497
>
10598
{childArray}
10699
</form>
107100

108-
{/* rendering of the modal must be gated on isSubmitSuccessful because
109-
there is a brief moment where isSubmitSuccessful is true but the proceed()
110-
hasn't fired yet, which means we get a brief flash of this modal */}
111-
{!isSubmitSuccessful && <ConfirmNavigation blocker={blocker} />}
101+
{blocker ? <ConfirmNavigation blocker={blocker} /> : null}
112102

113103
{actions && (
114104
<PageActions>

app/forms/image-from-snapshot.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { filesize } from 'filesize'
8+
import fileSize from 'filesize'
99
import { useNavigate, type LoaderFunctionArgs } from 'react-router-dom'
1010

1111
import {
@@ -83,7 +83,7 @@ export function CreateImageFromSnapshotSideModalForm() {
8383
<PropertiesTable.Row label="Snapshot">{data.name}</PropertiesTable.Row>
8484
<PropertiesTable.Row label="Project">{project}</PropertiesTable.Row>
8585
<PropertiesTable.Row label="Size">
86-
{filesize(data.size, { base: 2 })}
86+
{fileSize(data.size, { base: 2 })}
8787
</PropertiesTable.Row>
8888
</PropertiesTable>
8989

app/forms/image-upload.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Copyright Oxide Computer Company
77
*/
88
import cn from 'classnames'
9-
import { filesize } from 'filesize'
9+
import filesize from 'filesize'
1010
import pMap from 'p-map'
1111
import pRetry from 'p-retry'
1212
import { useRef, useState } from 'react'

app/forms/instance-create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export function CreateInstanceForm() {
188188
? await readBlobAsBase64(values.userData)
189189
: undefined
190190

191-
await createInstance.mutateAsync({
191+
createInstance.mutate({
192192
query: projectSelector,
193193
body: {
194194
name: values.name,

app/forms/ip-pool-range-add.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useNavigate } from 'react-router-dom'
99

1010
import { useApiMutation, useApiQueryClient, type IpRange } from '@oxide/api'
1111
import { Message } from '@oxide/ui'
12-
import { validateIp } from '@oxide/util'
12+
import { IPV4_REGEX, IPV6_REGEX } from '@oxide/util'
1313

1414
import { SideModalForm, TextField } from 'app/components/form'
1515
import { useForm, useIpPoolSelector } from 'app/hooks'
@@ -21,6 +21,12 @@ const defaultValues: IpRange = {
2121
last: '',
2222
}
2323

24+
function validateIp(s: string) {
25+
const isv4 = IPV4_REGEX.test(s)
26+
const isv6 = !isv4 && IPV6_REGEX.test(s)
27+
return { isv4, isv6, valid: isv4 || isv6 }
28+
}
29+
2430
const invalidAddressError = { type: 'pattern', message: 'Not a valid IP address' }
2531

2632
const diffVersionError = {

app/pages/project/access/ProjectAccessPage.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,8 @@ export function ProjectAccessPage() {
9696
return groupBy(siloRows.concat(projectRows), (u) => u.id)
9797
.map(([userId, userAssignments]) => {
9898
const siloRole = userAssignments.find((a) => a.roleSource === 'silo')?.roleName
99-
const projectRole = userAssignments.find(
100-
(a) => a.roleSource === 'project'
101-
)?.roleName
99+
const projectRole = userAssignments.find((a) => a.roleSource === 'project')
100+
?.roleName
102101

103102
const roles = [siloRole, projectRole].filter(isTruthy)
104103

app/pages/project/instances/instance/InstancePage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Copyright Oxide Computer Company
77
*/
88
import { format } from 'date-fns'
9-
import { filesize } from 'filesize'
9+
import filesize from 'filesize'
1010
import { useMemo } from 'react'
1111
import { Link, useNavigate, type LoaderFunctionArgs } from 'react-router-dom'
1212

0 commit comments

Comments
 (0)