Skip to content

Commit 7dcd41c

Browse files
charlieparkbenjaminleonarddavid-crespo
authored
Reorder IDP form elements (#2511)
* Reorder IDP create form elements * Update edit form order * Add docs link for Identity Providers * Remove checkbox for Signed Requests * Add side modal heading (#2533) * Add side modal heading * Remove commented input legend * very important mt-2 * cut one word to cut a whole line out of the targets info box --------- Co-authored-by: David Crespo <[email protected]> * change form section headings to SideModal.Heading, remove "General" --------- Co-authored-by: Benjamin Leonard <[email protected]> Co-authored-by: David Crespo <[email protected]>
1 parent b01ca85 commit 7dcd41c

File tree

6 files changed

+148
-109
lines changed

6 files changed

+148
-109
lines changed

app/forms/firewall-rules-common.tsx

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ import { useVpcSelector } from '~/hooks/use-params'
3636
import { Badge } from '~/ui/lib/Badge'
3737
import { toComboboxItems, type ComboboxItem } from '~/ui/lib/Combobox'
3838
import { FormDivider } from '~/ui/lib/Divider'
39+
import { FieldLabel } from '~/ui/lib/FieldLabel'
3940
import { Message } from '~/ui/lib/Message'
4041
import * as MiniTable from '~/ui/lib/MiniTable'
42+
import { SideModal } from '~/ui/lib/SideModal'
4143
import { TextInputHint } from '~/ui/lib/TextInput'
4244
import { KEYS } from '~/ui/util/keys'
4345
import { ALL_ISH } from '~/util/consts'
@@ -415,46 +417,50 @@ export const CommonFields = ({ control, nameTaken, error }: CommonFieldsProps) =
415417

416418
{/* Really this should be its own <form>, but you can't have a form inside a form,
417419
so we just stick the submit handler in a button onClick */}
418-
<div className="flex flex-col gap-3">
419-
<h3 className="mb-4 text-sans-2xl">Targets</h3>
420-
<Message
421-
variant="info"
422-
content={
423-
<>
420+
<SideModal.Heading>Targets</SideModal.Heading>
421+
422+
<Message
423+
variant="info"
424+
content={
425+
<>
426+
<p>
424427
Targets determine the instances to which this rule applies. You can target
425-
instances directly by name, or specify a VPC, VPC subnet, IP, or IP subnet,
426-
which will apply the rule to traffic going to all matching instances. Targets
427-
are additive: the rule applies to instances matching{' '}
428+
instances directly or specify a VPC, VPC subnet, IP, or IP subnet, which will
429+
apply the rule to traffic going to all matching instances.
430+
</p>
431+
<p className="mt-2">
432+
Targets are additive: the rule applies to instances matching{' '}
428433
<span className="underline">any</span> target.
429-
</>
430-
}
431-
/>
432-
<DynamicTypeAndValueFields
433-
sectionType="target"
434-
control={targetForm.control}
435-
valueType={targetType}
436-
items={toComboboxItems(targetItems[targetType])}
437-
// HACK: reset the whole subform, keeping type (because we just set
438-
// it). most importantly, this resets isSubmitted so the form can go
439-
// back to validating on submit instead of change
440-
onTypeChange={() =>
441-
targetForm.reset({ type: targetForm.getValues('type'), value: '' })
442-
}
443-
onInputChange={(value) => targetForm.setValue('value', value)}
444-
onSubmitTextField={submitTarget}
445-
/>
446-
<MiniTable.ClearAndAddButtons
447-
addButtonCopy="Add target"
448-
disableClear={!targetValue}
449-
onClear={() => targetForm.reset()}
450-
onSubmit={submitTarget}
451-
/>
452-
</div>
434+
</p>
435+
</>
436+
}
437+
/>
438+
439+
<DynamicTypeAndValueFields
440+
sectionType="target"
441+
control={targetForm.control}
442+
valueType={targetType}
443+
items={toComboboxItems(targetItems[targetType])}
444+
// HACK: reset the whole subform, keeping type (because we just set
445+
// it). most importantly, this resets isSubmitted so the form can go
446+
// back to validating on submit instead of change
447+
onTypeChange={() =>
448+
targetForm.reset({ type: targetForm.getValues('type'), value: '' })
449+
}
450+
onInputChange={(value) => targetForm.setValue('value', value)}
451+
onSubmitTextField={submitTarget}
452+
/>
453+
<MiniTable.ClearAndAddButtons
454+
addButtonCopy="Add target"
455+
disableClear={!targetValue}
456+
onClear={() => targetForm.reset()}
457+
onSubmit={submitTarget}
458+
/>
453459
{!!targets.value.length && <TypeAndValueTable sectionType="target" items={targets} />}
454460

455461
<FormDivider />
456462

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

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

525531
<fieldset className="space-y-0.5">
526-
<legend className="mb-2 mt-4 text-sans-lg">Protocol filters</legend>
532+
{/* todo: abstract this label and checkbox pattern */}
533+
<FieldLabel id="portRange-label" htmlFor="portRange" className="mb-2">
534+
Protocol filters
535+
</FieldLabel>
527536
<ProtocolField control={control} protocol="TCP" />
528537
<ProtocolField control={control} protocol="UDP" />
529538
<ProtocolField control={control} protocol="ICMP" />
530539
</fieldset>
531540

532-
<div className="flex flex-col gap-3">
533-
<h3 className="mt-4 text-sans-lg">Host filters</h3>
534-
<Message
535-
variant="info"
536-
content={
537-
<>
538-
Host filters match the &ldquo;other end&rdquo; of traffic from the
539-
target&rsquo;s perspective: for an inbound rule, they match the source of
540-
traffic. For an outbound rule, they match the destination.
541-
</>
542-
}
543-
/>
544-
<DynamicTypeAndValueFields
545-
sectionType="host"
546-
control={hostForm.control}
547-
valueType={hostType}
548-
items={toComboboxItems(hostFilterItems[hostType])}
549-
// HACK: reset the whole subform, keeping type (because we just set
550-
// it). most importantly, this resets isSubmitted so the form can go
551-
// back to validating on submit instead of change
552-
onTypeChange={() =>
553-
hostForm.reset({ type: hostForm.getValues('type'), value: '' })
554-
}
555-
onInputChange={(value) => hostForm.setValue('value', value)}
556-
onSubmitTextField={submitHost}
557-
/>
558-
<MiniTable.ClearAndAddButtons
559-
addButtonCopy="Add host filter"
560-
disableClear={!hostValue}
561-
onClear={() => hostForm.reset()}
562-
onSubmit={submitHost}
563-
/>
564-
</div>
541+
<FormDivider />
542+
543+
<SideModal.Heading>Host filters</SideModal.Heading>
544+
545+
<Message
546+
variant="info"
547+
content={
548+
<>
549+
Host filters match the &ldquo;other end&rdquo; of traffic from the
550+
target&rsquo;s perspective: for an inbound rule, they match the source of
551+
traffic. For an outbound rule, they match the destination.
552+
</>
553+
}
554+
/>
555+
<DynamicTypeAndValueFields
556+
sectionType="host"
557+
control={hostForm.control}
558+
valueType={hostType}
559+
items={toComboboxItems(hostFilterItems[hostType])}
560+
// HACK: reset the whole subform, keeping type (because we just set
561+
// it). most importantly, this resets isSubmitted so the form can go
562+
// back to validating on submit instead of change
563+
onTypeChange={() => hostForm.reset({ type: hostForm.getValues('type'), value: '' })}
564+
onInputChange={(value) => hostForm.setValue('value', value)}
565+
onSubmitTextField={submitHost}
566+
/>
567+
<MiniTable.ClearAndAddButtons
568+
addButtonCopy="Add host filter"
569+
disableClear={!hostValue}
570+
onClear={() => hostForm.reset()}
571+
onSubmit={submitHost}
572+
/>
565573
{!!hosts.value.length && <TypeAndValueTable sectionType="host" items={hosts} />}
566574

567575
{error && (

app/forms/idp/create.tsx

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { SideModalForm } from '~/components/form/SideModalForm'
1818
import { HL } from '~/components/HL'
1919
import { useSiloSelector } from '~/hooks/use-params'
2020
import { addToast } from '~/stores/toast'
21+
import { FormDivider } from '~/ui/lib/Divider'
22+
import { SideModal } from '~/ui/lib/SideModal'
2123
import { readBlobAsBase64 } from '~/util/file'
2224
import { pb } from '~/util/path-builder'
2325

@@ -109,21 +111,15 @@ export function CreateIdpSideModalForm() {
109111
<NameField name="name" control={form.control} />
110112
<DescriptionField name="description" control={form.control} required />
111113
<TextField
112-
name="acsUrl"
113-
label="ACS URL"
114-
description="Service provider endpoint for the IdP to send the SAML response"
115-
required
116-
control={form.control}
117-
/>
118-
{/* TODO: help text */}
119-
<TextField name="idpEntityId" label="Entity ID" required control={form.control} />
120-
<TextField
121-
name="sloUrl"
122-
label="Single Logout (SLO) URL"
123-
description="Service provider endpoint for log out requests"
114+
name="technicalContactEmail"
115+
label="Technical contact email"
124116
required
125117
control={form.control}
126118
/>
119+
120+
<FormDivider />
121+
122+
<SideModal.Heading>Service provider</SideModal.Heading>
127123
{/* TODO: help text */}
128124
<TextField
129125
name="spClientId"
@@ -132,22 +128,23 @@ export function CreateIdpSideModalForm() {
132128
control={form.control}
133129
/>
134130
<TextField
135-
name="groupAttributeName"
136-
label="Group attribute name"
137-
description="Name of the SAML attribute in the IdP response listing the user’s groups"
131+
name="acsUrl"
132+
label="ACS URL"
133+
description="Service provider endpoint for the IdP to send the SAML response"
134+
required
138135
control={form.control}
139136
/>
140-
{/* TODO: Email field, probably */}
141137
<TextField
142-
name="technicalContactEmail"
143-
label="Technical contact email"
138+
name="sloUrl"
139+
label="Single Logout (SLO) URL"
140+
description="Service provider endpoint for log out requests"
144141
required
145142
control={form.control}
146143
/>
147-
<MetadataSourceField control={form.control} />
144+
148145
{/* We don't bother validating that you have both of these or neither even
149-
though the API requires that because we are going to change the API to
150-
always require both, at which point these become simple `required` fields */}
146+
though the API requires that because we are going to change the API to
147+
always require both, at which point these become simple `required` fields */}
151148
<FileField
152149
id="public-cert-file-input"
153150
name="signingKeypair.publicCert"
@@ -162,6 +159,19 @@ export function CreateIdpSideModalForm() {
162159
label="Private key"
163160
control={form.control}
164161
/>
162+
163+
<FormDivider />
164+
165+
<SideModal.Heading>Identity Provider</SideModal.Heading>
166+
{/* TODO: help text */}
167+
<TextField name="idpEntityId" label="Entity ID" required control={form.control} />
168+
<TextField
169+
name="groupAttributeName"
170+
label="Group attribute name"
171+
description="Name of the SAML attribute in the IdP response listing the user’s groups"
172+
control={form.control}
173+
/>
174+
<MetadataSourceField control={form.control} />
165175
</SideModalForm>
166176
)
167177
}

app/forms/idp/edit.tsx

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ import { TextField } from '~/components/form/fields/TextField'
1717
import { SideModalForm } from '~/components/form/SideModalForm'
1818
import { getIdpSelector, useIdpSelector } from '~/hooks/use-params'
1919
import { DateTime } from '~/ui/lib/DateTime'
20+
import { FormDivider } from '~/ui/lib/Divider'
2021
import { PropertiesTable } from '~/ui/lib/PropertiesTable'
21-
import { ResourceLabel } from '~/ui/lib/SideModal'
22+
import { ResourceLabel, SideModal } from '~/ui/lib/SideModal'
2223
import { Truncate } from '~/ui/lib/Truncate'
2324
import { pb } from '~/util/path-builder'
2425

@@ -73,17 +74,28 @@ export function EditIdpSideModalForm() {
7374
<NameField name="name" control={form.control} disabled />
7475
<DescriptionField name="description" control={form.control} required disabled />
7576
<TextField
76-
name="acsUrl"
77-
label="ACS URL"
78-
description="Service provider endpoint for the IdP to send the SAML response"
77+
name="technicalContactEmail"
78+
label="Technical contact email"
7979
required
8080
control={form.control}
8181
disabled
8282
/>
83+
84+
<FormDivider />
85+
86+
<SideModal.Heading>Service provider</SideModal.Heading>
8387
{/* TODO: help text */}
8488
<TextField
85-
name="idpEntityId"
86-
label="Entity ID"
89+
name="spClientId"
90+
label="Service provider client ID"
91+
required
92+
control={form.control}
93+
disabled
94+
/>
95+
<TextField
96+
name="acsUrl"
97+
label="ACS URL"
98+
description="Service provider endpoint for the IdP to send the SAML response"
8799
required
88100
control={form.control}
89101
disabled
@@ -96,10 +108,14 @@ export function EditIdpSideModalForm() {
96108
control={form.control}
97109
disabled
98110
/>
111+
112+
<FormDivider />
113+
114+
<SideModal.Heading>Identity Provider</SideModal.Heading>
99115
{/* TODO: help text */}
100116
<TextField
101-
name="spClientId"
102-
label="Service provider client ID"
117+
name="idpEntityId"
118+
label="Entity ID"
103119
required
104120
control={form.control}
105121
disabled
@@ -112,14 +128,6 @@ export function EditIdpSideModalForm() {
112128
control={form.control}
113129
disabled
114130
/>
115-
{/* TODO: Email field, probably */}
116-
<TextField
117-
name="technicalContactEmail"
118-
label="Technical contact email"
119-
required
120-
control={form.control}
121-
disabled
122-
/>
123131
</SideModalForm>
124132
)
125133
}

app/pages/system/silos/SiloPage.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ export function SiloPage() {
6262
heading="silos"
6363
icon={<Cloud16Icon />}
6464
summary="Silos provide strict tenancy separation between groups of users. Each silo has its own resource limits and access policies as well as its own subdomain for the web console and API."
65-
links={[docLinks.systemSilo, docLinks.systemIpPools, docLinks.access]}
65+
links={[
66+
docLinks.systemSilo,
67+
docLinks.identityProviders,
68+
docLinks.systemIpPools,
69+
docLinks.access,
70+
]}
6671
/>
6772
</PageHeader>
6873

app/ui/lib/SideModal.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ function SideModalBody({ children }: { children?: ReactNode }) {
170170

171171
SideModal.Body = SideModalBody
172172

173+
SideModal.Heading = classed.div`text-sans-semi-xl`
174+
173175
SideModal.Section = classed.div`p-8 space-y-6 border-secondary`
174176

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

0 commit comments

Comments
 (0)