Skip to content

Commit 91216bd

Browse files
committed
chore: add delete button
1 parent eeafdd2 commit 91216bd

File tree

1 file changed

+81
-21
lines changed

1 file changed

+81
-21
lines changed

site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({
9595
<Tabs active={tab}>
9696
<TabsList>
9797
<TabLink to="?tab=groups" value="groups">
98-
Group Sync Settings
98+
Group sync settings
9999
</TabLink>
100100
<TabLink to="?tab=roles" value="roles">
101-
Role Sync Settings
101+
Role sync settings
102102
</TabLink>
103103
</TabsList>
104104
</Tabs>
@@ -168,6 +168,7 @@ const IdpMappingTable: FC<IdpMappingTableProps> = ({
168168
<TableRow>
169169
<TableCell width="45%">IdP {type}</TableCell>
170170
<TableCell width="55%">Coder {type}</TableCell>
171+
<TableCell width="10%" />
171172
</TableRow>
172173
</TableHead>
173174
<TableBody>
@@ -206,13 +207,30 @@ const IdpMappingTable: FC<IdpMappingTableProps> = ({
206207
);
207208
};
208209

209-
const GroupRow: FC<GroupRowProps> = ({ idpGroup, coderGroup }) => {
210+
interface GroupRowProps {
211+
idpGroup: string;
212+
coderGroup: readonly string[];
213+
onDelete: (idpOrg: string) => void;
214+
}
215+
216+
const GroupRow: FC<GroupRowProps> = ({ idpGroup, coderGroup, onDelete }) => {
210217
return (
211218
<TableRow data-testid={`group-${idpGroup}`}>
212219
<TableCell>{idpGroup}</TableCell>
213220
<TableCell>
214221
<IdpPillList roles={coderGroup} />
215222
</TableCell>
223+
<TableCell>
224+
<Button
225+
variant="outline"
226+
className="w-8 h-8 px-1.5 py-1.5 text-content-secondary"
227+
aria-label="delete"
228+
onClick={() => onDelete(idpGroup)}
229+
>
230+
<Trash />
231+
<span className="sr-only">Delete IdP mapping</span>
232+
</Button>
233+
</TableCell>
216234
</TableRow>
217235
);
218236
};
@@ -264,6 +282,20 @@ const IdpGroupSyncForm = ({
264282
return groupIds.map((groupId) => groupsMap.get(groupId) || groupId);
265283
};
266284

285+
const handleDelete = async (idpOrg: string) => {
286+
const newMapping = Object.fromEntries(
287+
Object.entries(form.values.mapping || {}).filter(
288+
([key]) => key !== idpOrg,
289+
),
290+
);
291+
const newSyncSettings = {
292+
...form.values,
293+
mapping: newMapping,
294+
};
295+
void form.setFieldValue("mapping", newSyncSettings.mapping);
296+
form.handleSubmit();
297+
};
298+
267299
const SYNC_FIELD_ID = "sync-field";
268300
const REGEX_FILTER_ID = "regex-filter";
269301
const AUTO_CREATE_MISSING_GROUPS_ID = "auto-create-missing-groups";
@@ -361,7 +393,7 @@ const IdpGroupSyncForm = ({
361393
onChange={setCoderGroups}
362394
defaultOptions={groups.map((group) => ({
363395
label: group.display_name || group.name,
364-
value: group.name,
396+
value: group.id,
365397
}))}
366398
hidePlaceholderWhenSelected
367399
placeholder="Select group"
@@ -399,7 +431,7 @@ const IdpGroupSyncForm = ({
399431
</div>
400432
</div>
401433
<div className="flex gap-12">
402-
<div className="flex flex-col gap-4 w-full">
434+
<div className="flex flex-col w-full">
403435
<IdpMappingTable type="Group" isEmpty={groupMappingCount === 0}>
404436
{groupSyncSettings?.mapping &&
405437
Object.entries(groupSyncSettings.mapping)
@@ -409,15 +441,18 @@ const IdpGroupSyncForm = ({
409441
key={idpGroup}
410442
idpGroup={idpGroup}
411443
coderGroup={getGroupNames(groups)}
444+
onDelete={handleDelete}
412445
/>
413446
))}
414447
</IdpMappingTable>
415448
<div className="flex justify-between">
416-
<ExportPolicyButton
417-
syncSettings={groupSyncSettings}
418-
organization={organization}
419-
type="groups"
420-
/>
449+
<span className="pt-2">
450+
<ExportPolicyButton
451+
syncSettings={groupSyncSettings}
452+
organization={organization}
453+
type="groups"
454+
/>
455+
</span>
421456
<TableRowCount count={groupMappingCount} type="groups" />
422457
</div>
423458
</div>
@@ -435,6 +470,7 @@ const IdpGroupSyncForm = ({
435470
key={idpGroup}
436471
idpGroup={idpGroup}
437472
coderGroup={getGroupNames([groupId])}
473+
onDelete={handleDelete}
438474
/>
439475
))}
440476
</IdpMappingTable>
@@ -482,6 +518,20 @@ const IdpRoleSyncForm = ({
482518
const [idpRoleName, setIdpRoleName] = useState("");
483519
const [coderRoles, setCoderRoles] = useState<Option[]>([]);
484520

521+
const handleDelete = async (idpOrg: string) => {
522+
const newMapping = Object.fromEntries(
523+
Object.entries(form.values.mapping || {}).filter(
524+
([key]) => key !== idpOrg,
525+
),
526+
);
527+
const newSyncSettings = {
528+
...form.values,
529+
mapping: newMapping,
530+
};
531+
void form.setFieldValue("mapping", newSyncSettings.mapping);
532+
form.handleSubmit();
533+
};
534+
485535
const SYNC_FIELD_ID = "sync-field";
486536
const IDP_ROLE_NAME_ID = "idp-role-name";
487537

@@ -592,15 +642,18 @@ const IdpRoleSyncForm = ({
592642
key={idpRole}
593643
idpRole={idpRole}
594644
coderRoles={roles}
645+
onDelete={handleDelete}
595646
/>
596647
))}
597648
</IdpMappingTable>
598649
<div className="flex justify-between">
599-
<ExportPolicyButton
600-
syncSettings={roleSyncSettings}
601-
organization={organization}
602-
type="roles"
603-
/>
650+
<span className="pt-2">
651+
<ExportPolicyButton
652+
syncSettings={roleSyncSettings}
653+
organization={organization}
654+
type="roles"
655+
/>
656+
</span>
604657
<TableRowCount count={roleMappingCount} type="roles" />
605658
</div>
606659
</div>
@@ -610,23 +663,30 @@ const IdpRoleSyncForm = ({
610663
);
611664
};
612665

613-
interface GroupRowProps {
614-
idpGroup: string;
615-
coderGroup: readonly string[];
616-
}
617-
618666
interface RoleRowProps {
619667
idpRole: string;
620668
coderRoles: readonly string[];
669+
onDelete: (idpOrg: string) => void;
621670
}
622671

623-
const RoleRow: FC<RoleRowProps> = ({ idpRole, coderRoles }) => {
672+
const RoleRow: FC<RoleRowProps> = ({ idpRole, coderRoles, onDelete }) => {
624673
return (
625674
<TableRow data-testid={`role-${idpRole}`}>
626675
<TableCell>{idpRole}</TableCell>
627676
<TableCell>
628677
<IdpPillList roles={coderRoles} />
629678
</TableCell>
679+
<TableCell>
680+
<Button
681+
variant="outline"
682+
className="w-8 h-8 px-1.5 py-1.5 text-content-secondary"
683+
aria-label="delete"
684+
onClick={() => onDelete(idpRole)}
685+
>
686+
<Trash />
687+
<span className="sr-only">Delete IdP mapping</span>
688+
</Button>
689+
</TableCell>
630690
</TableRow>
631691
);
632692
};

0 commit comments

Comments
 (0)