feat(admission): add group VPN exceptions
CI / validate (push) Successful in 5m45s
Release / release (push) Successful in 7m21s

This commit is contained in:
dmg
2026-08-02 10:16:16 -04:00
parent 24808b0f8c
commit 71856bb869
34 changed files with 1820 additions and 138 deletions
@@ -0,0 +1,60 @@
"use client";
import { useFormStatus } from "react-dom";
export function UserGroupSelect({
action,
effectiveGroupId,
groups,
search,
userId,
userLabel,
}: {
action: (formData: FormData) => Promise<void>;
effectiveGroupId: string;
groups: Array<{ id: string; name: string }>;
search: string;
userId: string;
userLabel: string;
}) {
const helpId = `group-help-${userId}`;
return (
<form action={action} className="flex items-center gap-2">
<input name="userId" type="hidden" value={userId} />
<input name="search" type="hidden" value={search} />
<span className="sr-only" id={helpId}>Changing this selection applies the group immediately.</span>
<GroupSelectControl effectiveGroupId={effectiveGroupId} groups={groups} helpId={helpId} userLabel={userLabel} />
</form>
);
}
function GroupSelectControl({
effectiveGroupId,
groups,
helpId,
userLabel,
}: {
effectiveGroupId: string;
groups: Array<{ id: string; name: string }>;
helpId: string;
userLabel: string;
}) {
const { pending } = useFormStatus();
return (
<>
<select
aria-describedby={helpId}
aria-label={`Group for ${userLabel}`}
className="max-w-44 border border-line bg-canvas px-3 py-2 font-mono text-xs outline-none focus:border-accent disabled:cursor-wait disabled:opacity-60"
defaultValue={effectiveGroupId}
disabled={pending}
name="groupId"
onChange={(event) => event.currentTarget.form?.requestSubmit()}
>
{groups.map((group) => <option key={group.id} value={group.id}>{group.name}</option>)}
</select>
<span aria-live="polite" className="sr-only">{pending ? "Updating group." : ""}</span>
<button className="sr-only focus:not-sr-only" disabled={pending} type="submit">Apply group</button>
</>
);
}