diff --git a/superset-frontend/src/features/roles/RoleListEditModal.test.tsx b/superset-frontend/src/features/roles/RoleListEditModal.test.tsx index b05f946d808..3853b484368 100644 --- a/superset-frontend/src/features/roles/RoleListEditModal.test.tsx +++ b/superset-frontend/src/features/roles/RoleListEditModal.test.tsx @@ -169,6 +169,7 @@ describe('RoleListEditModal', () => { true, ); + // updateRoleUsers is called with the hydrated user IDs const userArg = mockUpdateRoleUsers.mock.calls[0][1]; expect(userArg).toEqual([5, 7]); expect(userArg.every((id: unknown) => typeof id === 'number')).toBe(true); @@ -225,6 +226,8 @@ describe('RoleListEditModal', () => { expect(decodedQuery).toEqual({ page_size: 100, page: 0, + order_column: 'id', + order_direction: 'asc', filters: [ { col: 'roles', diff --git a/superset-frontend/src/features/roles/RoleListEditModal.tsx b/superset-frontend/src/features/roles/RoleListEditModal.tsx index d14f8b9755a..cd143edb1b9 100644 --- a/superset-frontend/src/features/roles/RoleListEditModal.tsx +++ b/superset-frontend/src/features/roles/RoleListEditModal.tsx @@ -129,8 +129,18 @@ function RoleListEditModal({ fetchPaginatedData({ endpoint: `/api/v1/security/users/`, pageSize: 100, - setData: setRoleUsers, + setData: (users: UserObject[]) => { + const seen = new Set(); + setRoleUsers( + users.filter(u => { + if (seen.has(u.id)) return false; + seen.add(u.id); + return true; + }), + ); + }, filters, + orderBy: { column: 'id', direction: 'asc' }, setLoadingState: (loading: boolean) => setLoadingRoleUsers(loading), loadingKey: 'roleUsers', addDangerToast, @@ -218,7 +228,6 @@ function RoleListEditModal({ value: user.id, label: user.username, })); - formRef.current.setFieldsValue({ roleUsers: userOptions, }); @@ -279,8 +288,8 @@ function RoleListEditModal({ const handleFormSubmit = async (values: RoleForm) => { try { - const userIds = values.roleUsers?.map(user => user.value) || []; const permissionIds = mapSelectedIds(values.rolePermissions); + const userIds = mapSelectedIds(values.roleUsers); const groupIds = mapSelectedIds(values.roleGroups); await Promise.all([ updateRoleName(id, values.roleName), diff --git a/superset-frontend/src/utils/fetchOptions.ts b/superset-frontend/src/utils/fetchOptions.ts index d9ac7b067ed..48ccaa8e5ad 100644 --- a/superset-frontend/src/utils/fetchOptions.ts +++ b/superset-frontend/src/utils/fetchOptions.ts @@ -28,6 +28,7 @@ interface FetchPaginatedOptions { setData: (data: any[]) => void; setLoadingState: Dispatch>; filters?: SupersetFilter[]; + orderBy?: { column: string; direction: 'asc' | 'desc' }; loadingKey: string; addDangerToast: (message: string) => void; errorMessage?: string; @@ -38,6 +39,8 @@ interface QueryObj { page_size: number; page: number; filters?: SupersetFilter[]; + order_column?: string; + order_direction?: 'asc' | 'desc'; } interface SupersetFilter { @@ -51,6 +54,7 @@ export const fetchPaginatedData = async ({ pageSize = 100, setData, filters, + orderBy, setLoadingState, loadingKey, addDangerToast, @@ -66,6 +70,10 @@ export const fetchPaginatedData = async ({ if (filters) { queryObj.filters = filters; } + if (orderBy) { + queryObj.order_column = orderBy.column; + queryObj.order_direction = orderBy.direction; + } const encodedQuery = rison.encode(queryObj); const response = await SupersetClient.get({