Add new user and role selectors for pagination

This commit is contained in:
Owen
2026-05-05 20:53:36 -07:00
parent 51f1693dbd
commit a8f4d2b7d1
4 changed files with 42 additions and 1007 deletions

View File

@@ -6,11 +6,9 @@ import { useEnvContext } from "@app/hooks/useEnvContext";
import { useOrgContext } from "@app/hooks/useOrgContext";
import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { getUserDisplayName } from "@app/lib/getUserDisplayName";
import { orgQueries } from "@app/lib/queries";
import { build } from "@server/build";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { UserType } from "@server/types/UserTypes";
import { useQuery } from "@tanstack/react-query";
import { useTranslations } from "next-intl";
@@ -51,12 +49,6 @@ export function EditPolicyForm({
env.server.maxmind_asn_path && env.server.maxmind_asn_path.length > 0
);
const { data: orgRoles = [], isLoading: isLoadingOrgRoles } = useQuery(
orgQueries.roles({ orgId: org.org.orgId })
);
const { data: orgUsers = [], isLoading: isLoadingOrgUsers } = useQuery(
orgQueries.users({ orgId: org.org.orgId })
);
const { data: orgIdps = [], isLoading: isLoadingOrgIdps } = useQuery(
orgQueries.identityProviders({
orgId: org.org.orgId,
@@ -64,26 +56,6 @@ export function EditPolicyForm({
})
);
const allRoles = useMemo(
() =>
orgRoles
.map((role) => ({
id: role.roleId.toString(),
text: role.name
}))
.filter((role) => role.text !== "Admin"),
[orgRoles]
);
const allUsers = useMemo(
() =>
orgUsers.map((user) => ({
id: user.id.toString(),
text: `${getUserDisplayName({ email: user.email, username: user.username })}${user.type !== UserType.Internal ? ` (${user.idpName})` : ""}`
})),
[orgUsers]
);
const allIdps = useMemo(() => {
if (build === "saas") {
if (isPaidUser(tierMatrix.orgOidc)) {
@@ -98,17 +70,18 @@ export function EditPolicyForm({
return [];
}, [orgIdps, isPaidUser]);
if (isLoadingOrgRoles || isLoadingOrgUsers || isLoadingOrgIdps) {
if (isLoadingOrgIdps) {
return <></>;
}
return (
<SettingsContainer>
{!hidePolicyNameForm && <EditPolicyNameSectionForm readonly={readonly} />}
{!hidePolicyNameForm && (
<EditPolicyNameSectionForm readonly={readonly} />
)}
<EditPolicyUsersRolesSectionForm
allRoles={allRoles}
allUsers={allUsers}
orgId={org.org.orgId}
allIdps={allIdps}
readonly={readonly}
/>

View File

@@ -23,8 +23,9 @@ import type { AxiosResponse } from "axios";
import { useRouter } from "next/navigation";
import { createPolicySchema } from ".";
import { RolesSelector } from "@app/components/roles-selector";
import { UsersSelector } from "@app/components/users-selector";
import { SwitchInput } from "@app/components/SwitchInput";
import { Tag, TagInput } from "@app/components/tags/tag-input";
import { Button } from "@app/components/ui/button";
import {
Form,
@@ -50,15 +51,13 @@ import { useForm, useWatch } from "react-hook-form";
// ─── PolicyUsersRolesSection ──────────────────────────────────────────────────
type PolicyUsersRolesSectionProps = {
allRoles: { id: string; text: string }[];
allUsers: { id: string; text: string }[];
orgId: string;
allIdps: { id: number; text: string }[];
readonly?: boolean;
};
export function EditPolicyUsersRolesSectionForm({
allRoles,
allUsers,
orgId,
allIdps,
readonly
}: PolicyUsersRolesSectionProps) {
@@ -98,12 +97,6 @@ export function EditPolicyUsersRolesSectionForm({
control: form.control,
name: "skipToIdpId"
});
const [activeRolesTagIndex, setActiveRolesTagIndex] = useState<
number | null
>(null);
const [activeUsersTagIndex, setActiveUsersTagIndex] = useState<
number | null
>(null);
const [, formAction, isSubmitting] = useActionState(onSubmit, null);
@@ -190,43 +183,21 @@ export function EditPolicyUsersRolesSectionForm({
{t("roles")}
</FormLabel>
<FormControl>
<TagInput
{...field}
activeTagIndex={
activeRolesTagIndex
<RolesSelector
orgId={orgId}
selectedRoles={
field.value
}
setActiveTagIndex={
setActiveRolesTagIndex
}
placeholder={t(
"accessRoleSelect2"
)}
size="sm"
tags={
form.getValues()
.roles
}
setTags={(newRoles) => {
onSelectRoles={(
roles
) =>
form.setValue(
"roles",
newRoles as [
Tag,
...Tag[]
]
);
}}
enableAutocomplete={
true
roles
)
}
autocompleteOptions={
allRoles
}
allowDuplicates={false}
restrictTagsToAutocompleteOptions={
true
}
sortTags={true}
disabled={readonly}
restrictAdminRole
/>
</FormControl>
<FormMessage />
@@ -247,42 +218,19 @@ export function EditPolicyUsersRolesSectionForm({
{t("users")}
</FormLabel>
<FormControl>
<TagInput
{...field}
activeTagIndex={
activeUsersTagIndex
<UsersSelector
orgId={orgId}
selectedUsers={
field.value
}
setActiveTagIndex={
setActiveUsersTagIndex
}
placeholder={t(
"accessUserSelect"
)}
size="sm"
tags={
form.getValues()
.users
}
setTags={(newUsers) => {
onSelectUsers={(
users
) =>
form.setValue(
"users",
newUsers as [
Tag,
...Tag[]
]
);
}}
enableAutocomplete={
true
users
)
}
autocompleteOptions={
allUsers
}
allowDuplicates={false}
restrictTagsToAutocompleteOptions={
true
}
sortTags={true}
disabled={readonly}
/>
</FormControl>

View File

@@ -18,12 +18,14 @@ export type UsersSelectorProps = {
orgId: string;
selectedUsers?: SelectedUser[];
onSelectUsers: (users: SelectedUser[]) => void;
disabled?: boolean;
};
export function UsersSelector({
orgId,
selectedUsers = [],
onSelectUsers
onSelectUsers,
disabled
}: UsersSelectorProps) {
const t = useTranslations();
const [userSearchQuery, setUserSearchQuery] = useState("");
@@ -58,6 +60,7 @@ export function UsersSelector({
options={usersShown}
value={selectedUsers}
onChange={onSelectUsers}
disabled={disabled}
/>
);
}