Skip to content

Commit 7f68453

Browse files
committed
Move logic into common file
1 parent 62844ae commit 7f68453

File tree

3 files changed

+50
-28
lines changed

3 files changed

+50
-28
lines changed

app/forms/firewall-rules-common.tsx

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Copyright Oxide Computer Company
77
*/
88

9-
import { useEffect, type ReactNode } from 'react'
9+
import { useEffect, useState, type ReactNode } from 'react'
1010
import { useController, useForm, type Control } from 'react-hook-form'
1111

1212
import {
@@ -40,9 +40,8 @@ import { KEYS } from '~/ui/util/keys'
4040
import { ALL_ISH } from '~/util/consts'
4141
import { validateIp, validateIpNet } from '~/util/ip'
4242
import { links } from '~/util/links'
43-
import { capitalize } from '~/util/str'
43+
import { capitalize, commaSeries } from '~/util/str'
4444

45-
import { type ActiveSubforms } from './firewall-rules-create'
4645
import { type FirewallRuleValues } from './firewall-rules-util'
4746

4847
/**
@@ -539,3 +538,33 @@ export const CommonFields = ({
539538
</>
540539
)
541540
}
541+
542+
export type ActiveSubforms = { target: boolean; port: boolean; host: boolean }
543+
export const defaultActiveSubforms: ActiveSubforms = {
544+
target: false,
545+
port: false,
546+
host: false,
547+
}
548+
549+
export function useSubformStates(defaultActiveSubforms: ActiveSubforms) {
550+
const [subformStates, setSubformStates] = useState(defaultActiveSubforms)
551+
const updateSubformStates = (subform: keyof ActiveSubforms, value: boolean) => {
552+
setSubformStates((prev) => ({ ...prev, [subform]: value }))
553+
}
554+
return { subformStates, updateSubformStates }
555+
}
556+
557+
export const getActiveSubformList = (subformStates: ActiveSubforms) =>
558+
commaSeries(
559+
Object.keys(subformStates).filter((key) => subformStates[key as keyof ActiveSubforms]),
560+
'and'
561+
)
562+
.replace('port', 'port filter')
563+
.replace('host', 'host filter')
564+
565+
export const submitDisabledMessage = (subformStates: ActiveSubforms) => {
566+
const activeSubformList = getActiveSubformList(subformStates)
567+
return activeSubformList.length > 0
568+
? `You have an unsaved ${activeSubformList} entry; save or clear ${activeSubformList.includes('and') ? 'them' : 'it'} to create this firewall rule`
569+
: undefined
570+
}

app/forms/firewall-rules-create.tsx

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { useState } from 'react'
98
import { useForm } from 'react-hook-form'
109
import { useNavigate, useParams, type LoaderFunctionArgs } from 'react-router'
1110

@@ -24,9 +23,13 @@ import { getVpcSelector, useVpcSelector } from '~/hooks/use-params'
2423
import { addToast } from '~/stores/toast'
2524
import { ALL_ISH } from '~/util/consts'
2625
import { pb } from '~/util/path-builder'
27-
import { commaSeries } from '~/util/str'
2826

29-
import { CommonFields } from './firewall-rules-common'
27+
import {
28+
CommonFields,
29+
defaultActiveSubforms,
30+
submitDisabledMessage,
31+
useSubformStates,
32+
} from './firewall-rules-common'
3033
import { valuesToRuleUpdate, type FirewallRuleValues } from './firewall-rules-util'
3134

3235
/** Empty form for when we're not creating from an existing rule */
@@ -71,23 +74,8 @@ CreateFirewallRuleForm.loader = async ({ params }: LoaderFunctionArgs) => {
7174
return null
7275
}
7376

74-
export type ActiveSubforms = { target: boolean; port: boolean; host: boolean }
75-
const defaultActiveSubforms: ActiveSubforms = { target: false, port: false, host: false }
76-
7777
export function CreateFirewallRuleForm() {
78-
const [subformStates, setSubformStates] = useState(defaultActiveSubforms)
79-
const updateSubformStates = (subform: keyof ActiveSubforms, value: boolean) => {
80-
setSubformStates({
81-
...subformStates,
82-
[subform]: value,
83-
})
84-
}
85-
const activeSubformList = commaSeries(
86-
Object.keys(subformStates).filter((key) => subformStates[key as keyof ActiveSubforms]),
87-
'and'
88-
)
89-
.replace('port', 'port filter')
90-
.replace('host', 'host filter')
78+
const { subformStates, updateSubformStates } = useSubformStates(defaultActiveSubforms)
9179

9280
const vpcSelector = useVpcSelector()
9381
const queryClient = useApiQueryClient()
@@ -139,11 +127,7 @@ export function CreateFirewallRuleForm() {
139127
loading={updateRules.isPending}
140128
submitError={updateRules.error}
141129
submitLabel="Add rule"
142-
submitDisabled={
143-
activeSubformList.length
144-
? `You have an unsaved ${activeSubformList} entry; save or clear ${activeSubformList.includes('and') ? 'them' : 'it'} to create this firewall rule`
145-
: undefined
146-
}
130+
submitDisabled={submitDisabledMessage(subformStates)}
147131
>
148132
<CommonFields
149133
control={form.control}

app/forms/firewall-rules-edit.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ import { ALL_ISH } from '~/util/consts'
2929
import { invariant } from '~/util/invariant'
3030
import { pb } from '~/util/path-builder'
3131

32-
import { CommonFields } from './firewall-rules-common'
32+
import {
33+
CommonFields,
34+
defaultActiveSubforms,
35+
submitDisabledMessage,
36+
useSubformStates,
37+
} from './firewall-rules-common'
3338
import { valuesToRuleUpdate, type FirewallRuleValues } from './firewall-rules-util'
3439

3540
EditFirewallRuleForm.loader = async ({ params }: LoaderFunctionArgs) => {
@@ -55,6 +60,8 @@ export function EditFirewallRuleForm() {
5560
const vpcSelector = useVpcSelector()
5661
const queryClient = useApiQueryClient()
5762

63+
const { subformStates, updateSubformStates } = useSubformStates(defaultActiveSubforms)
64+
5865
const { data: firewallRules } = usePrefetchedApiQuery('vpcFirewallRulesView', {
5966
query: { project, vpc },
6067
})
@@ -122,13 +129,15 @@ export function EditFirewallRuleForm() {
122129
// validationSchema={validationSchema}
123130
// validateOnBlur
124131
loading={updateRules.isPending}
132+
submitDisabled={submitDisabledMessage(subformStates)}
125133
submitError={updateRules.error}
126134
>
127135
<CommonFields
128136
control={form.control}
129137
// error if name is being changed to something that conflicts with some other rule
130138
nameTaken={(name) => !!otherRules.find((r) => r.name === name)}
131139
error={updateRules.error}
140+
updateSubformStates={updateSubformStates}
132141
/>
133142
</SideModalForm>
134143
)

0 commit comments

Comments
 (0)