Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 79 additions & 71 deletions app/forms/firewall-rules-common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ import { useVpcSelector } from '~/hooks/use-params'
import { Badge } from '~/ui/lib/Badge'
import { toComboboxItems, type ComboboxItem } from '~/ui/lib/Combobox'
import { FormDivider } from '~/ui/lib/Divider'
import { FieldLabel } from '~/ui/lib/FieldLabel'
import { Message } from '~/ui/lib/Message'
import * as MiniTable from '~/ui/lib/MiniTable'
import { SideModal } from '~/ui/lib/SideModal'
import { TextInputHint } from '~/ui/lib/TextInput'
import { KEYS } from '~/ui/util/keys'
import { ALL_ISH } from '~/util/consts'
Expand Down Expand Up @@ -415,46 +417,50 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =

{/* Really this should be its own <form>, but you can't have a form inside a form,
so we just stick the submit handler in a button onClick */}
<div className="flex flex-col gap-3">
<h3 className="mb-4 text-sans-2xl">Targets</h3>
<Message
variant="info"
content={
<>
<SideModal.Heading>Targets</SideModal.Heading>

<Message
variant="info"
content={
<>
<p>
Targets determine the instances to which this rule applies. You can target
instances directly by name, or specify a VPC, VPC subnet, IP, or IP subnet,
which will apply the rule to traffic going to all matching instances. Targets
are additive: the rule applies to instances matching{' '}
instances directly or specify a VPC, VPC subnet, IP, or IP subnet, which will
apply the rule to traffic going to all matching instances.
</p>
<p className="mt-2">
Targets are additive: the rule applies to instances matching{' '}
<span className="underline">any</span> target.
</>
}
/>
<DynamicTypeAndValueFields
sectionType="target"
control={targetForm.control}
valueType={targetType}
items={toComboboxItems(targetItems[targetType])}
// HACK: reset the whole subform, keeping type (because we just set
// it). most importantly, this resets isSubmitted so the form can go
// back to validating on submit instead of change
onTypeChange={() =>
targetForm.reset({ type: targetForm.getValues('type'), value: '' })
}
onInputChange={(value) => targetForm.setValue('value', value)}
onSubmitTextField={submitTarget}
/>
<MiniTable.ClearAndAddButtons
addButtonCopy="Add target"
disableClear={!targetValue}
onClear={() => targetForm.reset()}
onSubmit={submitTarget}
/>
</div>
</p>
</>
}
/>

<DynamicTypeAndValueFields
sectionType="target"
control={targetForm.control}
valueType={targetType}
items={toComboboxItems(targetItems[targetType])}
// HACK: reset the whole subform, keeping type (because we just set
// it). most importantly, this resets isSubmitted so the form can go
// back to validating on submit instead of change
onTypeChange={() =>
targetForm.reset({ type: targetForm.getValues('type'), value: '' })
}
onInputChange={(value) => targetForm.setValue('value', value)}
onSubmitTextField={submitTarget}
/>
<MiniTable.ClearAndAddButtons
addButtonCopy="Add target"
disableClear={!targetValue}
onClear={() => targetForm.reset()}
onSubmit={submitTarget}
/>
{!!targets.value.length && <TypeAndValueTable sectionType="target" items={targets} />}

<FormDivider />

<h3 className="mb-4 text-sans-2xl">Filters</h3>
<SideModal.Heading>Filters</SideModal.Heading>
<Message
variant="info"
content={
Expand All @@ -468,12 +474,12 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
/>

<div className="flex flex-col gap-3">
{/* We have to blow this up instead of using TextField to get better
{/* We have to blow this up instead of using TextField to get better
text styling on the label */}
<div className="mt-2">
<label id="portRange-label" htmlFor="portRange" className="text-sans-lg">
<FieldLabel id="portRange-label" htmlFor="portRange">
Port filters
</label>
</FieldLabel>
<TextInputHint id="portRange-help-text" className="mb-2">
A single destination port (1234) or a range (1234&ndash;2345)
</TextInputHint>
Expand Down Expand Up @@ -523,45 +529,47 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
)}

<fieldset className="space-y-0.5">
<legend className="mb-2 mt-4 text-sans-lg">Protocol filters</legend>
{/* todo: abstract this label and checkbox pattern */}
<FieldLabel id="portRange-label" htmlFor="portRange" className="mb-2">
Protocol filters
</FieldLabel>
<ProtocolField control={control} protocol="TCP" />
<ProtocolField control={control} protocol="UDP" />
<ProtocolField control={control} protocol="ICMP" />
</fieldset>

<div className="flex flex-col gap-3">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stuff is unnecessary because the overall thing already has the spacing, it also causes a bit of havok since the spacing here is different.

<h3 className="mt-4 text-sans-lg">Host filters</h3>
<Message
variant="info"
content={
<>
Host filters match the &ldquo;other end&rdquo; of traffic from the
target&rsquo;s perspective: for an inbound rule, they match the source of
traffic. For an outbound rule, they match the destination.
</>
}
/>
<DynamicTypeAndValueFields
sectionType="host"
control={hostForm.control}
valueType={hostType}
items={toComboboxItems(hostFilterItems[hostType])}
// HACK: reset the whole subform, keeping type (because we just set
// it). most importantly, this resets isSubmitted so the form can go
// back to validating on submit instead of change
onTypeChange={() =>
hostForm.reset({ type: hostForm.getValues('type'), value: '' })
}
onInputChange={(value) => hostForm.setValue('value', value)}
onSubmitTextField={submitHost}
/>
<MiniTable.ClearAndAddButtons
addButtonCopy="Add host filter"
disableClear={!hostValue}
onClear={() => hostForm.reset()}
onSubmit={submitHost}
/>
</div>
<FormDivider />

<SideModal.Heading>Host filters</SideModal.Heading>

<Message
variant="info"
content={
<>
Host filters match the &ldquo;other end&rdquo; of traffic from the
target&rsquo;s perspective: for an inbound rule, they match the source of
traffic. For an outbound rule, they match the destination.
</>
}
/>
<DynamicTypeAndValueFields
sectionType="host"
control={hostForm.control}
valueType={hostType}
items={toComboboxItems(hostFilterItems[hostType])}
// HACK: reset the whole subform, keeping type (because we just set
// it). most importantly, this resets isSubmitted so the form can go
// back to validating on submit instead of change
onTypeChange={() => hostForm.reset({ type: hostForm.getValues('type'), value: '' })}
onInputChange={(value) => hostForm.setValue('value', value)}
onSubmitTextField={submitHost}
/>
<MiniTable.ClearAndAddButtons
addButtonCopy="Add host filter"
disableClear={!hostValue}
onClear={() => hostForm.reset()}
onSubmit={submitHost}
/>
{!!hosts.value.length && <TypeAndValueTable sectionType="host" items={hosts} />}

{error && (
Expand Down
2 changes: 2 additions & 0 deletions app/ui/lib/SideModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ function SideModalBody({ children }: { children?: ReactNode }) {

SideModal.Body = SideModalBody

SideModal.Heading = classed.div`text-sans-semi-xl`

SideModal.Section = classed.div`p-8 space-y-6 border-secondary`

SideModal.Footer = ({ children, error }: { children: ReactNode; error?: boolean }) => (
Expand Down
Loading