@openedx/frontend-app-admin-console 1.0.0-alpha.6 → 1.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/authz-module/authz-home/index.js +21 -2
  2. package/dist/authz-module/authz-home/index.js.map +1 -1
  3. package/dist/authz-module/components/AddRoleButton.js +1 -1
  4. package/dist/authz-module/components/AddRoleButton.js.map +1 -1
  5. package/dist/authz-module/components/AuthZLayout.js +1 -1
  6. package/dist/authz-module/components/AuthZLayout.js.map +1 -1
  7. package/dist/authz-module/components/AuthZTitle.js +5 -3
  8. package/dist/authz-module/components/AuthZTitle.js.map +1 -1
  9. package/dist/authz-module/components/ExpandableButton.d.ts +17 -0
  10. package/dist/authz-module/components/ExpandableButton.js +16 -0
  11. package/dist/authz-module/components/ExpandableButton.js.map +1 -0
  12. package/dist/authz-module/components/TableCells.d.ts +5 -8
  13. package/dist/authz-module/components/TableCells.js +26 -59
  14. package/dist/authz-module/components/TableCells.js.map +1 -1
  15. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.d.ts +1 -1
  16. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.js +4 -3
  17. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.js.map +1 -1
  18. package/dist/authz-module/components/TableControlBar/OrgFilter.js +2 -2
  19. package/dist/authz-module/components/TableControlBar/OrgFilter.js.map +1 -1
  20. package/dist/authz-module/components/TableControlBar/SearchFilter.d.ts +2 -1
  21. package/dist/authz-module/components/TableControlBar/SearchFilter.js +2 -1
  22. package/dist/authz-module/components/TableControlBar/SearchFilter.js.map +1 -1
  23. package/dist/authz-module/components/TableControlBar/TableControlBar.d.ts +4 -1
  24. package/dist/authz-module/components/TableControlBar/TableControlBar.js +24 -24
  25. package/dist/authz-module/components/TableControlBar/TableControlBar.js.map +1 -1
  26. package/dist/authz-module/components/TableControlBar/types.d.ts +1 -0
  27. package/dist/authz-module/components/TableControlBar/types.js.map +1 -1
  28. package/dist/authz-module/components/TableFooter/TableFooter.d.ts +14 -1
  29. package/dist/authz-module/components/TableFooter/TableFooter.js +3 -2
  30. package/dist/authz-module/components/TableFooter/TableFooter.js.map +1 -1
  31. package/dist/authz-module/components/constants.d.ts +1 -0
  32. package/dist/authz-module/components/constants.js +2 -1
  33. package/dist/authz-module/components/constants.js.map +1 -1
  34. package/dist/authz-module/components/messages.d.ts +0 -5
  35. package/dist/authz-module/components/messages.js +2 -7
  36. package/dist/authz-module/components/messages.js.map +1 -1
  37. package/dist/authz-module/constants.d.ts +14 -6
  38. package/dist/authz-module/constants.js +23 -6
  39. package/dist/authz-module/constants.js.map +1 -1
  40. package/dist/authz-module/data/api.d.ts +12 -4
  41. package/dist/authz-module/data/api.js +11 -2
  42. package/dist/authz-module/data/api.js.map +1 -1
  43. package/dist/authz-module/data/hooks.d.ts +8 -8
  44. package/dist/authz-module/data/hooks.js +15 -20
  45. package/dist/authz-module/data/hooks.js.map +1 -1
  46. package/dist/authz-module/hooks/useExclusiveRowExpansion.d.ts +7 -0
  47. package/dist/authz-module/hooks/useExclusiveRowExpansion.js +24 -0
  48. package/dist/authz-module/hooks/useExclusiveRowExpansion.js.map +1 -0
  49. package/dist/authz-module/index.scss +120 -6
  50. package/dist/authz-module/messages.d.ts +23 -0
  51. package/dist/authz-module/messages.js +18 -0
  52. package/dist/authz-module/messages.js.map +1 -1
  53. package/dist/authz-module/role-assignation-wizard/hooks/useScopeListData.js.map +1 -1
  54. package/dist/authz-module/team-members/TeamMembersTable.js +55 -17
  55. package/dist/authz-module/team-members/TeamMembersTable.js.map +1 -1
  56. package/dist/authz-module/team-members/components/AssignedRolesCell.d.ts +20 -0
  57. package/dist/authz-module/team-members/components/AssignedRolesCell.js +54 -0
  58. package/dist/authz-module/team-members/components/AssignedRolesCell.js.map +1 -0
  59. package/dist/authz-module/team-members/components/MoreRolesToggle.d.ts +14 -0
  60. package/dist/authz-module/team-members/components/MoreRolesToggle.js +25 -0
  61. package/dist/authz-module/team-members/components/MoreRolesToggle.js.map +1 -0
  62. package/dist/authz-module/team-members/components/TeamMemberCells.d.ts +17 -0
  63. package/dist/authz-module/team-members/components/TeamMemberCells.js +21 -0
  64. package/dist/authz-module/team-members/components/TeamMemberCells.js.map +1 -0
  65. package/dist/authz-module/team-members/components/TeamMemberViewActionCell.d.ts +18 -0
  66. package/dist/authz-module/team-members/components/TeamMemberViewActionCell.js +42 -0
  67. package/dist/authz-module/team-members/components/TeamMemberViewActionCell.js.map +1 -0
  68. package/dist/authz-module/team-members/components/UserAssignmentsSubTable.d.ts +16 -0
  69. package/dist/authz-module/team-members/components/UserAssignmentsSubTable.js +74 -0
  70. package/dist/authz-module/team-members/components/UserAssignmentsSubTable.js.map +1 -0
  71. package/dist/authz-module/team-members/index.d.ts +1 -0
  72. package/dist/authz-module/team-members/index.js +2 -0
  73. package/dist/authz-module/team-members/index.js.map +1 -0
  74. package/dist/authz-module/team-members/messages.d.ts +56 -1
  75. package/dist/authz-module/team-members/messages.js +59 -4
  76. package/dist/authz-module/team-members/messages.js.map +1 -1
  77. package/dist/authz-module/utils.d.ts +6 -0
  78. package/dist/authz-module/utils.js +12 -10
  79. package/dist/authz-module/utils.js.map +1 -1
  80. package/dist/components/LoadingPage.d.ts +3 -0
  81. package/dist/components/LoadingPage.js +9 -1
  82. package/dist/components/LoadingPage.js.map +1 -1
  83. package/dist/components/messages.d.ts +8 -0
  84. package/dist/components/messages.js +10 -0
  85. package/dist/components/messages.js.map +1 -0
  86. package/dist/types.d.ts +29 -20
  87. package/dist/types.js.map +1 -1
  88. package/package.json +1 -1
  89. package/dist/authz-module/components/ViewMoreLink.d.ts +0 -8
  90. package/dist/authz-module/components/ViewMoreLink.js +0 -8
  91. package/dist/authz-module/components/ViewMoreLink.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/authz-module/data/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Org, Scope,\n UserRole,\n} from '@src/types';\nimport { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { getApiUrl } from '@src/data/utils';\n\nexport interface QuerySettings {\n roles: string | null;\n scopes: string | null;\n organizations: string | null;\n search: string | null;\n order: string | null;\n sortBy: string | null;\n pageSize: number;\n pageIndex: number;\n}\n\nexport interface GetUserAssignmentsResponse {\n results: UserRole[];\n count: number;\n next: string | null;\n previous: string | null;\n}\n\nexport interface RevokeUserRolesRequest {\n users: string;\n role: string;\n scope: string;\n querySettings?: QuerySettings;\n}\n\nexport interface DeleteRevokeUserRolesResponse {\n completed: {\n userIdentifiers: string;\n status: string;\n }[];\n errors: {\n userIdentifiers: string;\n error: string;\n }[];\n}\n\nexport interface PutAssignTeamMembersRoleResponse {\n completed: { userIdentifier: string; status: string }[];\n errors: { userIdentifier: string; scope: string; error: string }[];\n}\n\nexport interface AssignTeamMembersRoleRequest {\n users: string[];\n role: string;\n scopes: string[];\n}\n\nexport interface GetAllRoleAssignmentsResponse {\n results: UserRole[];\n count: number;\n next: string | null;\n previous: string | null;\n}\n\nexport interface GetOrgsResponse {\n count: number;\n next: string | null;\n previous: string | null;\n results: Org[];\n}\n\nexport interface GetScopesResponse {\n count: number;\n next: string | null;\n previous: string | null;\n results: Scope[];\n}\nexport interface ValidateUsersRequest {\n users: string[];\n}\n\nexport interface ValidateUsersResponse {\n validUsers: string[];\n invalidUsers: string[];\n summary: {\n total: number;\n validCount: number;\n invalidCount: number;\n };\n}\n\nexport interface GetScopesParams {\n scopeType?: string;\n search?: string;\n orgs?: string[];\n page?: number;\n pageSize?: number;\n managementPermissionOnly?: boolean;\n}\n\nexport interface WaffleFlagOverrides {\n on: string[];\n off: string[];\n}\n\n/**\n * Enablement state of the course-authoring waffle flag across scopes.\n * `orgOverrides`/`courseOverrides` list the org short names / course ids whose\n * override differs from `global` (explicitly forced `on` or `off`).\n */\nexport interface CourseAuthoringFlagStates {\n global: boolean;\n orgOverrides: WaffleFlagOverrides;\n courseOverrides: WaffleFlagOverrides;\n}\n\nexport const assignTeamMembersRole = async (\n data: AssignTeamMembersRoleRequest,\n): Promise<PutAssignTeamMembersRoleResponse> => {\n const res = await getAuthenticatedHttpClient().put(getApiUrl('/api/authz/v1/roles/users/'), data);\n return camelCaseObject(res.data);\n};\n\nexport const validateUsers = async (\n data: ValidateUsersRequest,\n): Promise<ValidateUsersResponse> => {\n const res = await getAuthenticatedHttpClient().post(\n getApiUrl('/api/authz/v1/users/validate/'),\n data,\n );\n return camelCaseObject(res.data);\n};\n\nexport const revokeUserRoles = async (\n data: RevokeUserRolesRequest,\n): Promise<DeleteRevokeUserRolesResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/roles/users/'));\n url.searchParams.append('users', data.users);\n url.searchParams.append('role', data.role);\n url.searchParams.append('scope', data.scope);\n\n // If this is not transformed to string, it shows a 404 with the token CSRF acquisition request\n const res = await getAuthenticatedHttpClient().delete(url.toString());\n return camelCaseObject(res.data);\n};\n\nexport const getAllRoleAssignments = async (querySettings: QuerySettings): Promise<GetAllRoleAssignmentsResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/assignments/'));\n\n if (querySettings.roles) {\n url.searchParams.set('roles', querySettings.roles);\n }\n if (querySettings.scopes) {\n url.searchParams.set('scopes', querySettings.scopes);\n }\n if (querySettings.organizations) {\n url.searchParams.set('orgs', querySettings.organizations);\n }\n if (querySettings.search) {\n url.searchParams.set('search', querySettings.search);\n }\n if (querySettings.sortBy && querySettings.order) {\n url.searchParams.set('sort_by', querySettings.sortBy);\n url.searchParams.set('order', querySettings.order);\n }\n url.searchParams.set('page_size', querySettings.pageSize.toString());\n url.searchParams.set('page', (querySettings.pageIndex + 1).toString());\n\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n\nexport const getOrgs = async (search?: string, page?: number, pageSize?: number): Promise<GetOrgsResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/orgs/'));\n if (search !== undefined) {\n url.searchParams.set('search', search);\n }\n if (page !== undefined) {\n url.searchParams.set('page', page.toString());\n }\n if (pageSize !== undefined) {\n url.searchParams.set('page_size', pageSize.toString());\n }\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n\nexport const getScopes = async (params: GetScopesParams): Promise<GetScopesResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/scopes/'));\n if (params.search) url.searchParams.set('search', params.search);\n if (params.scopeType) url.searchParams.set('scope_type', params.scopeType);\n if (params.orgs?.length) url.searchParams.set('orgs', params.orgs.join(','));\n if (params.managementPermissionOnly) url.searchParams.set('management_permission_only', 'true');\n url.searchParams.set('page', (params.page ?? 1).toString());\n url.searchParams.set('page_size', (params.pageSize ?? 10).toString());\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n\nexport const getCourseAuthoringFlagStates = async (): Promise<CourseAuthoringFlagStates> => {\n const { data } = await getAuthenticatedHttpClient().get(getApiUrl('/api/authz/v1/waffle-flag-states/'));\n return camelCaseObject(data);\n};\n\nexport const getUserAssignedRoles = async (username?: string, querySettings?: QuerySettings): Promise<GetUserAssignmentsResponse> => {\n const url = new URL(getApiUrl(`/api/authz/v1/users/${username}/assignments/`));\n\n if (querySettings?.roles) {\n url.searchParams.set('roles', querySettings.roles);\n }\n if (querySettings?.organizations) {\n url.searchParams.set('orgs', querySettings.organizations);\n }\n if (querySettings?.search) {\n url.searchParams.set('search', querySettings.search);\n }\n if (querySettings?.sortBy && querySettings?.order) {\n url.searchParams.set('sort_by', querySettings.sortBy);\n url.searchParams.set('order', querySettings?.order || '');\n }\n url.searchParams.set('page_size', querySettings?.pageSize?.toString() || '');\n url.searchParams.set('page', ((querySettings?.pageIndex ?? 0) + 1).toString());\n\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/authz-module/data/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Org, Scope, TeamMember, UserRole,\n} from '@src/types';\nimport { camelCaseObject, getAuthenticatedHttpClient } from '@openedx/frontend-base';\nimport { getApiUrl } from '@src/data/utils';\n\nexport interface QuerySettings {\n roles: string | null;\n scopes: string | null;\n organizations: string | null;\n search: string | null;\n order: string | null;\n sortBy: string | null;\n pageSize: number;\n pageIndex: number;\n}\n\nexport interface GetUserAssignmentsResponse {\n results: UserRole[];\n count: number;\n next: string | null;\n previous: string | null;\n}\n\nexport interface RevokeUserRolesRequest {\n users: string;\n role: string;\n scope: string;\n querySettings?: QuerySettings;\n}\n\nexport interface DeleteRevokeUserRolesResponse {\n completed: {\n userIdentifiers: string;\n status: string;\n }[];\n errors: {\n userIdentifiers: string;\n error: string;\n }[];\n}\n\nexport interface PutAssignTeamMembersRoleResponse {\n completed: { userIdentifier: string; status: string }[];\n errors: { userIdentifier: string; scope: string; error: string }[];\n}\n\nexport interface AssignTeamMembersRoleRequest {\n users: string[];\n role: string;\n scopes: string[];\n}\n\nexport interface GetTeamMembersAssignmentsResponse {\n results: TeamMember[];\n count: number;\n next: string | null;\n previous: string | null;\n}\n\nexport interface GetOrgsResponse {\n count: number;\n next: string | null;\n previous: string | null;\n results: Org[];\n}\n\nexport interface GetScopesResponse {\n count: number;\n next: string | null;\n previous: string | null;\n results: Scope[];\n}\nexport interface ValidateUsersRequest {\n users: string[];\n}\n\nexport interface ValidateUsersResponse {\n validUsers: string[];\n invalidUsers: string[];\n summary: {\n total: number;\n validCount: number;\n invalidCount: number;\n };\n}\n\nexport interface GetScopesParams {\n scopeType?: string;\n search?: string;\n orgs?: string[];\n page?: number;\n pageSize?: number;\n managementPermissionOnly?: boolean;\n}\n\nexport interface WaffleFlagOverrides {\n on: string[];\n off: string[];\n}\n\n/**\n * Enablement state of the course-authoring waffle flag across scopes.\n * `orgOverrides`/`courseOverrides` list the org short names / course ids whose\n * override differs from `global` (explicitly forced `on` or `off`).\n */\nexport interface CourseAuthoringFlagStates {\n global: boolean;\n orgOverrides: WaffleFlagOverrides;\n courseOverrides: WaffleFlagOverrides;\n}\n\nexport const assignTeamMembersRole = async (\n data: AssignTeamMembersRoleRequest,\n): Promise<PutAssignTeamMembersRoleResponse> => {\n const res = await getAuthenticatedHttpClient().put(getApiUrl('/api/authz/v1/roles/users/'), data);\n return camelCaseObject(res.data);\n};\n\nexport const validateUsers = async (\n data: ValidateUsersRequest,\n): Promise<ValidateUsersResponse> => {\n const res = await getAuthenticatedHttpClient().post(\n getApiUrl('/api/authz/v1/users/validate/'),\n data,\n );\n return camelCaseObject(res.data);\n};\n\nexport const revokeUserRoles = async (\n data: RevokeUserRolesRequest,\n): Promise<DeleteRevokeUserRolesResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/roles/users/'));\n url.searchParams.append('users', data.users);\n url.searchParams.append('role', data.role);\n url.searchParams.append('scope', data.scope);\n\n // If this is not transformed to string, it shows a 404 with the token CSRF acquisition request\n const res = await getAuthenticatedHttpClient().delete(url.toString());\n return camelCaseObject(res.data);\n};\n\n/**\n * Fetches team members grouped by user: one entry per user carrying the first few of\n * their role assignments plus `assignmentCount`, the number behind that slice.\n *\n * The role, org and scope filters apply to assignments before they are grouped, so they\n * decide both which users come back and which of each user's assignments are listed and\n * counted.\n */\nexport const getTeamMembersAssignments = async (querySettings: QuerySettings): Promise<GetTeamMembersAssignmentsResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/users/'));\n\n if (querySettings.roles) {\n url.searchParams.set('roles', querySettings.roles);\n }\n if (querySettings.scopes) {\n url.searchParams.set('scopes', querySettings.scopes);\n }\n if (querySettings.organizations) {\n url.searchParams.set('orgs', querySettings.organizations);\n }\n if (querySettings.search) {\n url.searchParams.set('search', querySettings.search);\n }\n if (querySettings.sortBy && querySettings.order) {\n url.searchParams.set('sort_by', querySettings.sortBy);\n url.searchParams.set('order', querySettings.order);\n }\n // The endpoint defaults `assignments_limit` to 3; set it only to change that default.\n url.searchParams.set('page_size', querySettings.pageSize.toString());\n url.searchParams.set('page', (querySettings.pageIndex + 1).toString());\n\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n\nexport const getOrgs = async (search?: string, page?: number, pageSize?: number): Promise<GetOrgsResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/orgs/'));\n if (search !== undefined) {\n url.searchParams.set('search', search);\n }\n if (page !== undefined) {\n url.searchParams.set('page', page.toString());\n }\n if (pageSize !== undefined) {\n url.searchParams.set('page_size', pageSize.toString());\n }\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n\nexport const getScopes = async (params: GetScopesParams): Promise<GetScopesResponse> => {\n const url = new URL(getApiUrl('/api/authz/v1/scopes/'));\n if (params.search) url.searchParams.set('search', params.search);\n if (params.scopeType) url.searchParams.set('scope_type', params.scopeType);\n if (params.orgs?.length) url.searchParams.set('orgs', params.orgs.join(','));\n if (params.managementPermissionOnly) url.searchParams.set('management_permission_only', 'true');\n url.searchParams.set('page', (params.page ?? 1).toString());\n url.searchParams.set('page_size', (params.pageSize ?? 10).toString());\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n\nexport const getCourseAuthoringFlagStates = async (): Promise<CourseAuthoringFlagStates> => {\n const { data } = await getAuthenticatedHttpClient().get(getApiUrl('/api/authz/v1/waffle-flag-states/'));\n return camelCaseObject(data);\n};\n\nexport const getUserAssignedRoles = async (username?: string, querySettings?: QuerySettings): Promise<GetUserAssignmentsResponse> => {\n const url = new URL(getApiUrl(`/api/authz/v1/users/${username}/assignments/`));\n\n if (querySettings?.roles) {\n url.searchParams.set('roles', querySettings.roles);\n }\n if (querySettings?.organizations) {\n url.searchParams.set('orgs', querySettings.organizations);\n }\n if (querySettings?.search) {\n url.searchParams.set('search', querySettings.search);\n }\n if (querySettings?.sortBy && querySettings?.order) {\n url.searchParams.set('sort_by', querySettings.sortBy);\n url.searchParams.set('order', querySettings?.order || '');\n }\n url.searchParams.set('page_size', querySettings?.pageSize?.toString() || '');\n url.searchParams.set('page', ((querySettings?.pageIndex ?? 0) + 1).toString());\n\n const { data } = await getAuthenticatedHttpClient().get(url);\n return camelCaseObject(data);\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { AssignTeamMembersRoleRequest, GetAllRoleAssignmentsResponse, GetOrgsResponse, GetScopesResponse, QuerySettings, RevokeUserRolesRequest, GetUserAssignmentsResponse, ValidateUsersRequest, GetScopesParams, CourseAuthoringFlagStates } from './api';
1
+ import { AssignTeamMembersRoleRequest, GetTeamMembersAssignmentsResponse, GetOrgsResponse, GetScopesResponse, QuerySettings, RevokeUserRolesRequest, GetUserAssignmentsResponse, ValidateUsersRequest, GetScopesParams, CourseAuthoringFlagStates } from './api';
2
2
  /**
3
3
  * React Query hook to add new team members to a specific scope or manage the corresponding roles.
4
4
  * It provides a mutation function to add users with specified roles to the team or assign new roles.
@@ -32,18 +32,18 @@ export declare const useRevokeUserRoles: () => import("@tanstack/react-query").U
32
32
  data: RevokeUserRolesRequest;
33
33
  }, unknown>;
34
34
  /**
35
- * React Query hook to fetch all role assignments across scopes and roles,
36
- * with support for filtering, sorting, and pagination.
37
- * It retrieves a comprehensive list of user-role assignments based
38
- * on the provided query settings.
35
+ * React Query hook to fetch team members grouped by user, with support for
36
+ * filtering, sorting, and pagination. Each result is one user carrying the first few of
37
+ * their role assignments plus how many there are; see `getTeamMembersAssignments` for
38
+ * how filters narrow both.
39
39
  *
40
- * @param querySettings - Optional parameters for filtering by roles, scopes,
40
+ * @param querySettings - Parameters for filtering by roles, scopes,
41
41
  * organizations, search term, sorting, and pagination.
42
42
  *
43
43
  * @example
44
- * const { data: roleAssignments } = useAllRoleAssignments({ roles: 'editor', pageSize: 20 });
44
+ * const { data: teamMembers } = useTeamMembersAssignments({ roles: 'editor', pageSize: 20 });
45
45
  */
46
- export declare const useAllRoleAssignments: (querySettings: QuerySettings) => import("@tanstack/react-query").UseQueryResult<GetAllRoleAssignmentsResponse, Error>;
46
+ export declare const useTeamMembersAssignments: (querySettings: QuerySettings) => import("@tanstack/react-query").UseQueryResult<GetTeamMembersAssignmentsResponse, Error>;
47
47
  /**
48
48
  * React Query hook to fetch a paginated, searchable list of organizations.
49
49
  * Results are cached for 30 minutes — suitable for both filter dropdowns and full listings.
@@ -9,10 +9,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { useInfiniteQuery, useMutation, useQuery, useQueryClient, } from '@tanstack/react-query';
11
11
  import { appId } from '../../constants';
12
- import { assignTeamMembersRole, getAllRoleAssignments, getOrgs, getScopes, revokeUserRoles, getUserAssignedRoles, validateUsers, getCourseAuthoringFlagStates, } from './api';
12
+ import { assignTeamMembersRole, getTeamMembersAssignments, getOrgs, getScopes, revokeUserRoles, getUserAssignedRoles, validateUsers, getCourseAuthoringFlagStates, } from './api';
13
13
  const authzQueryKeys = {
14
14
  all: [appId, 'authz'],
15
- allRoleAssignments: (querySettings) => [...authzQueryKeys.all, 'allRoleAssignments', querySettings],
15
+ teamMembersAssignments: (querySettings) => [...authzQueryKeys.all, 'teamMembersAssignments', querySettings],
16
16
  orgs: (search, page, pageSize) => [...authzQueryKeys.all, 'organizations', search, page, pageSize],
17
17
  scopes: (params) => [...authzQueryKeys.all, 'scopes', params],
18
18
  userRoles: (username, querySettings) => [...authzQueryKeys.all, 'userRoles', username, querySettings],
@@ -34,7 +34,7 @@ export const useAssignTeamMembersRole = () => {
34
34
  if (!error) {
35
35
  queryClient.invalidateQueries({ queryKey: [...authzQueryKeys.all, 'userRoles'] });
36
36
  queryClient.invalidateQueries({
37
- predicate: (query) => query.queryKey.includes('allRoleAssignments'),
37
+ predicate: (query) => query.queryKey.includes('teamMembersAssignments'),
38
38
  });
39
39
  }
40
40
  },
@@ -67,33 +67,28 @@ export const useRevokeUserRoles = () => {
67
67
  predicate: (query) => query.queryKey.includes('userRoles'),
68
68
  });
69
69
  queryClient.invalidateQueries({
70
- predicate: (query) => query.queryKey.includes('allRoleAssignments'),
70
+ predicate: (query) => query.queryKey.includes('teamMembersAssignments'),
71
71
  });
72
72
  },
73
73
  });
74
74
  };
75
75
  /**
76
- * React Query hook to fetch all role assignments across scopes and roles,
77
- * with support for filtering, sorting, and pagination.
78
- * It retrieves a comprehensive list of user-role assignments based
79
- * on the provided query settings.
76
+ * React Query hook to fetch team members grouped by user, with support for
77
+ * filtering, sorting, and pagination. Each result is one user carrying the first few of
78
+ * their role assignments plus how many there are; see `getTeamMembersAssignments` for
79
+ * how filters narrow both.
80
80
  *
81
- * @param querySettings - Optional parameters for filtering by roles, scopes,
81
+ * @param querySettings - Parameters for filtering by roles, scopes,
82
82
  * organizations, search term, sorting, and pagination.
83
83
  *
84
84
  * @example
85
- * const { data: roleAssignments } = useAllRoleAssignments({ roles: 'editor', pageSize: 20 });
85
+ * const { data: teamMembers } = useTeamMembersAssignments({ roles: 'editor', pageSize: 20 });
86
86
  */
87
- export const useAllRoleAssignments = (querySettings) => {
88
- const result = useQuery({
89
- queryKey: authzQueryKeys.allRoleAssignments(querySettings),
90
- queryFn: () => getAllRoleAssignments(querySettings),
91
- staleTime: 1000 * 60 * 30, // refetch after 30 minutes
92
- retry: false,
93
- refetchOnWindowFocus: false,
94
- });
95
- return result;
96
- };
87
+ export const useTeamMembersAssignments = (querySettings) => (useQuery({
88
+ queryKey: authzQueryKeys.teamMembersAssignments(querySettings),
89
+ queryFn: () => getTeamMembersAssignments(querySettings),
90
+ staleTime: 1000 * 60 * 30, // refetch after 30 minutes
91
+ }));
97
92
  /**
98
93
  * React Query hook to fetch a paginated, searchable list of organizations.
99
94
  * Results are cached for 30 minutes — suitable for both filter dropdowns and full listings.
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/authz-module/data/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n useInfiniteQuery, useMutation, useQuery, useQueryClient,\n} from '@tanstack/react-query';\nimport { appId } from '@src/constants';\nimport {\n assignTeamMembersRole, AssignTeamMembersRoleRequest, getAllRoleAssignments,\n GetAllRoleAssignmentsResponse, getOrgs, GetOrgsResponse,\n getScopes, GetScopesResponse, QuerySettings, revokeUserRoles,\n RevokeUserRolesRequest, getUserAssignedRoles, GetUserAssignmentsResponse,\n validateUsers, ValidateUsersRequest, GetScopesParams,\n getCourseAuthoringFlagStates, CourseAuthoringFlagStates,\n} from './api';\n\nconst authzQueryKeys = {\n all: [appId, 'authz'] as const,\n allRoleAssignments: (querySettings?: QuerySettings) => [...authzQueryKeys.all, 'allRoleAssignments', querySettings] as const,\n orgs: (search?: string, page?: number, pageSize?: number) => [...authzQueryKeys.all, 'organizations', search, page, pageSize] as const,\n scopes: (params?: Omit<GetScopesParams, 'page'>) => [...authzQueryKeys.all, 'scopes', params] as const,\n userRoles: (username?: string, querySettings?: QuerySettings) => [...authzQueryKeys.all, 'userRoles', username, querySettings] as const,\n courseAuthoringFlagStates: () => [...authzQueryKeys.all, 'courseAuthoringFlagStates'] as const,\n};\n\n/**\n * React Query hook to add new team members to a specific scope or manage the corresponding roles.\n * It provides a mutation function to add users with specified roles to the team or assign new roles.\n *\n * @example\n * const { mutate: assignTeamMembersRole } = useAssignTeamMembersRole();\n * assignTeamMembersRole({ data: { libraryId: 'lib:123', users: ['jdoe'], role: 'editor' } });\n */\nexport const useAssignTeamMembersRole = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async ({ data }: {\n data: AssignTeamMembersRoleRequest;\n }) => assignTeamMembersRole(data),\n onSettled: (_data, error) => {\n if (!error) {\n queryClient.invalidateQueries({ queryKey: [...authzQueryKeys.all, 'userRoles'] });\n queryClient.invalidateQueries({\n predicate: (query) => query.queryKey.includes('allRoleAssignments'),\n });\n }\n },\n });\n};\n\n/**\n * React Query hook to validate users exist without assigning roles.\n * It checks if the provided usernames/email addresses are valid.\n *\n * @example\n * const { mutate: validateUsers } = useValidateUsers();\n * validateUsers({ data: { users: ['jdoe', 'jane@example.com'] } });\n */\nexport const useValidateUsers = () => useMutation({\n mutationFn: async ({ data }: {\n data: ValidateUsersRequest;\n }) => validateUsers(data),\n});\n\n/**\n * React Query hook to remove roles for a specific team member within a scope.\n *\n * @example\n * const { mutate: revokeUserRoles } = useRevokeUserRoles();\n * revokeUserRoles({ data: { libraryId: 'lib:123', users: ['jdoe'], role: 'editor' } });\n */\nexport const useRevokeUserRoles = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async ({ data }: {\n data: RevokeUserRolesRequest;\n }) => revokeUserRoles(data),\n onSettled: () => {\n queryClient.invalidateQueries({\n predicate: (query) => query.queryKey.includes('userRoles'),\n });\n queryClient.invalidateQueries({\n predicate: (query) => query.queryKey.includes('allRoleAssignments'),\n });\n },\n });\n};\n\n/**\n * React Query hook to fetch all role assignments across scopes and roles,\n * with support for filtering, sorting, and pagination.\n * It retrieves a comprehensive list of user-role assignments based\n * on the provided query settings.\n *\n * @param querySettings - Optional parameters for filtering by roles, scopes,\n * organizations, search term, sorting, and pagination.\n *\n * @example\n * const { data: roleAssignments } = useAllRoleAssignments({ roles: 'editor', pageSize: 20 });\n */\nexport const useAllRoleAssignments = (querySettings: QuerySettings) => {\n const result = useQuery<GetAllRoleAssignmentsResponse, Error>({\n queryKey: authzQueryKeys.allRoleAssignments(querySettings),\n queryFn: () => getAllRoleAssignments(querySettings),\n staleTime: 1000 * 60 * 30, // refetch after 30 minutes\n retry: false,\n refetchOnWindowFocus: false,\n });\n return result;\n};\n\n/**\n * React Query hook to fetch a paginated, searchable list of organizations.\n * Results are cached for 30 minutes — suitable for both filter dropdowns and full listings.\n *\n * @param search - Optional text filter applied to organization names.\n * @param page - 1-based page number; defaults to the first page when omitted.\n * @param pageSize - Items per page; defaults to the API default when omitted.\n * @returns A `QueryResult<GetOrgsResponse>` with `results`, `count`, `next`, and `previous`.\n *\n * @example\n * ```tsx\n * const { data } = useOrgs('edX');\n * const orgs = data?.results ?? [];\n * ```\n */\nexport const useOrgs = (search?: string, page?: number, pageSize?: number) => useQuery<GetOrgsResponse, Error>({\n queryKey: authzQueryKeys.orgs(search, page, pageSize),\n queryFn: () => getOrgs(search, page, pageSize),\n staleTime: 1000 * 60 * 30,\n refetchOnWindowFocus: false,\n});\n\n/**\n * React Query hook to fetch a paginated, filterable list of scopes (courses or libraries).\n * Uses infinite query to support infinite scroll — call `fetchNextPage` to load more results.\n *\n * @param params - Filter parameters (all optional):\n * - `search` — text filter applied to scope names\n * - `scopeType` — filter by scope type (e.g. course, library)\n * - `org` — filter by organization\n * - `pageSize` — number of items per page\n * - `managementPermissionOnly` — when true, returns only scopes the requester can manage\n * @returns An `InfiniteQueryResult` whose `data.pages` contains the accumulated `GetScopesResponse` pages.\n *\n * @example\n * ```tsx\n * const { data, fetchNextPage, hasNextPage } = useScopes({ search: 'intro', orgs: ['edX'] });\n * const scopes = data?.pages.flatMap((p) => p.results) ?? [];\n * ```\n */\nexport const useScopes = (params: Omit<GetScopesParams, 'page'> = {}) => useInfiniteQuery<GetScopesResponse, Error>({\n queryKey: authzQueryKeys.scopes(params),\n queryFn: ({ pageParam }) => getScopes({ ...params, page: pageParam as number }),\n getNextPageParam: (lastPage) => {\n if (!lastPage.next) return undefined;\n try {\n const nextUrl = new URL(lastPage.next);\n const page = nextUrl.searchParams.get('page');\n return page ? parseInt(page, 10) : undefined;\n } catch {\n return undefined;\n }\n },\n initialPageParam: 1,\n staleTime: 1000 * 60 * 5,\n refetchOnWindowFocus: false,\n});\n\n/*\n * React Query hook to fetch all the roles assigned to a specific user.\n * It retrieves the full list of roles with the corresponding permissions.\n * @param username - The username of the user\n * @param querySettings - Optional query parameters for filtering, sorting, and pagination\n *\n * @example\n * ```tsx\n * const { data: userRoles } = useUserAssignedRoles('jdoe', querySettings);\n * ```\n*/\nexport const useUserAssignedRoles = (\n username?: string,\n querySettings?: QuerySettings,\n) => useQuery<GetUserAssignmentsResponse, Error>({\n queryKey: authzQueryKeys.userRoles(username, querySettings),\n queryFn: () => getUserAssignedRoles(username, querySettings),\n staleTime: 1000 * 60 * 30, // refetch after 30 minutes\n enabled: !!username,\n refetchOnWindowFocus: false,\n});\n\n/**\n * React Query hook to fetch the enablement state of the course-authoring waffle flag\n * across scopes (global, org overrides, course overrides).\n *\n * Follows the same caching rules as the permission-validation hooks.\n *\n * @example\n * ```tsx\n * const { data } = useCourseAuthoringFlagStates();\n * ```\n */\nexport const useCourseAuthoringFlagStates = () => useQuery<CourseAuthoringFlagStates, Error>({\n queryKey: authzQueryKeys.courseAuthoringFlagStates(),\n queryFn: () => getCourseAuthoringFlagStates(),\n staleTime: 1000 * 60 * 30,\n refetchOnWindowFocus: false,\n retry: false,\n});\n"]}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../src/authz-module/data/hooks.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n useInfiniteQuery, useMutation, useQuery, useQueryClient,\n} from '@tanstack/react-query';\nimport { appId } from '@src/constants';\nimport {\n assignTeamMembersRole, AssignTeamMembersRoleRequest, getTeamMembersAssignments,\n GetTeamMembersAssignmentsResponse, getOrgs, GetOrgsResponse,\n getScopes, GetScopesResponse, QuerySettings, revokeUserRoles,\n RevokeUserRolesRequest, getUserAssignedRoles, GetUserAssignmentsResponse,\n validateUsers, ValidateUsersRequest, GetScopesParams,\n getCourseAuthoringFlagStates, CourseAuthoringFlagStates,\n} from './api';\n\nconst authzQueryKeys = {\n all: [appId, 'authz'] as const,\n teamMembersAssignments: (querySettings?: QuerySettings) => [...authzQueryKeys.all, 'teamMembersAssignments', querySettings] as const,\n orgs: (search?: string, page?: number, pageSize?: number) => [...authzQueryKeys.all, 'organizations', search, page, pageSize] as const,\n scopes: (params?: Omit<GetScopesParams, 'page'>) => [...authzQueryKeys.all, 'scopes', params] as const,\n userRoles: (username?: string, querySettings?: QuerySettings) => [...authzQueryKeys.all, 'userRoles', username, querySettings] as const,\n courseAuthoringFlagStates: () => [...authzQueryKeys.all, 'courseAuthoringFlagStates'] as const,\n};\n\n/**\n * React Query hook to add new team members to a specific scope or manage the corresponding roles.\n * It provides a mutation function to add users with specified roles to the team or assign new roles.\n *\n * @example\n * const { mutate: assignTeamMembersRole } = useAssignTeamMembersRole();\n * assignTeamMembersRole({ data: { libraryId: 'lib:123', users: ['jdoe'], role: 'editor' } });\n */\nexport const useAssignTeamMembersRole = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async ({ data }: {\n data: AssignTeamMembersRoleRequest;\n }) => assignTeamMembersRole(data),\n onSettled: (_data, error) => {\n if (!error) {\n queryClient.invalidateQueries({ queryKey: [...authzQueryKeys.all, 'userRoles'] });\n queryClient.invalidateQueries({\n predicate: (query) => query.queryKey.includes('teamMembersAssignments'),\n });\n }\n },\n });\n};\n\n/**\n * React Query hook to validate users exist without assigning roles.\n * It checks if the provided usernames/email addresses are valid.\n *\n * @example\n * const { mutate: validateUsers } = useValidateUsers();\n * validateUsers({ data: { users: ['jdoe', 'jane@example.com'] } });\n */\nexport const useValidateUsers = () => useMutation({\n mutationFn: async ({ data }: {\n data: ValidateUsersRequest;\n }) => validateUsers(data),\n});\n\n/**\n * React Query hook to remove roles for a specific team member within a scope.\n *\n * @example\n * const { mutate: revokeUserRoles } = useRevokeUserRoles();\n * revokeUserRoles({ data: { libraryId: 'lib:123', users: ['jdoe'], role: 'editor' } });\n */\nexport const useRevokeUserRoles = () => {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async ({ data }: {\n data: RevokeUserRolesRequest;\n }) => revokeUserRoles(data),\n onSettled: () => {\n queryClient.invalidateQueries({\n predicate: (query) => query.queryKey.includes('userRoles'),\n });\n queryClient.invalidateQueries({\n predicate: (query) => query.queryKey.includes('teamMembersAssignments'),\n });\n },\n });\n};\n\n/**\n * React Query hook to fetch team members grouped by user, with support for\n * filtering, sorting, and pagination. Each result is one user carrying the first few of\n * their role assignments plus how many there are; see `getTeamMembersAssignments` for\n * how filters narrow both.\n *\n * @param querySettings - Parameters for filtering by roles, scopes,\n * organizations, search term, sorting, and pagination.\n *\n * @example\n * const { data: teamMembers } = useTeamMembersAssignments({ roles: 'editor', pageSize: 20 });\n */\nexport const useTeamMembersAssignments = (querySettings: QuerySettings) => (\n useQuery<GetTeamMembersAssignmentsResponse, Error>({\n queryKey: authzQueryKeys.teamMembersAssignments(querySettings),\n queryFn: () => getTeamMembersAssignments(querySettings),\n staleTime: 1000 * 60 * 30, // refetch after 30 minutes\n })\n);\n\n/**\n * React Query hook to fetch a paginated, searchable list of organizations.\n * Results are cached for 30 minutes — suitable for both filter dropdowns and full listings.\n *\n * @param search - Optional text filter applied to organization names.\n * @param page - 1-based page number; defaults to the first page when omitted.\n * @param pageSize - Items per page; defaults to the API default when omitted.\n * @returns A `QueryResult<GetOrgsResponse>` with `results`, `count`, `next`, and `previous`.\n *\n * @example\n * ```tsx\n * const { data } = useOrgs('edX');\n * const orgs = data?.results ?? [];\n * ```\n */\nexport const useOrgs = (search?: string, page?: number, pageSize?: number) => useQuery<GetOrgsResponse, Error>({\n queryKey: authzQueryKeys.orgs(search, page, pageSize),\n queryFn: () => getOrgs(search, page, pageSize),\n staleTime: 1000 * 60 * 30,\n refetchOnWindowFocus: false,\n});\n\n/**\n * React Query hook to fetch a paginated, filterable list of scopes (courses or libraries).\n * Uses infinite query to support infinite scroll — call `fetchNextPage` to load more results.\n *\n * @param params - Filter parameters (all optional):\n * - `search` — text filter applied to scope names\n * - `scopeType` — filter by scope type (e.g. course, library)\n * - `org` — filter by organization\n * - `pageSize` — number of items per page\n * - `managementPermissionOnly` — when true, returns only scopes the requester can manage\n * @returns An `InfiniteQueryResult` whose `data.pages` contains the accumulated `GetScopesResponse` pages.\n *\n * @example\n * ```tsx\n * const { data, fetchNextPage, hasNextPage } = useScopes({ search: 'intro', orgs: ['edX'] });\n * const scopes = data?.pages.flatMap((p) => p.results) ?? [];\n * ```\n */\nexport const useScopes = (params: Omit<GetScopesParams, 'page'> = {}) => useInfiniteQuery<GetScopesResponse, Error>({\n queryKey: authzQueryKeys.scopes(params),\n queryFn: ({ pageParam }) => getScopes({ ...params, page: pageParam as number }),\n getNextPageParam: (lastPage) => {\n if (!lastPage.next) return undefined;\n try {\n const nextUrl = new URL(lastPage.next);\n const page = nextUrl.searchParams.get('page');\n return page ? parseInt(page, 10) : undefined;\n } catch {\n return undefined;\n }\n },\n initialPageParam: 1,\n staleTime: 1000 * 60 * 5,\n refetchOnWindowFocus: false,\n});\n\n/*\n * React Query hook to fetch all the roles assigned to a specific user.\n * It retrieves the full list of roles with the corresponding permissions.\n * @param username - The username of the user\n * @param querySettings - Optional query parameters for filtering, sorting, and pagination\n *\n * @example\n * ```tsx\n * const { data: userRoles } = useUserAssignedRoles('jdoe', querySettings);\n * ```\n*/\nexport const useUserAssignedRoles = (\n username?: string,\n querySettings?: QuerySettings,\n) => useQuery<GetUserAssignmentsResponse, Error>({\n queryKey: authzQueryKeys.userRoles(username, querySettings),\n queryFn: () => getUserAssignedRoles(username, querySettings),\n staleTime: 1000 * 60 * 30, // refetch after 30 minutes\n enabled: !!username,\n refetchOnWindowFocus: false,\n});\n\n/**\n * React Query hook to fetch the enablement state of the course-authoring waffle flag\n * across scopes (global, org overrides, course overrides).\n *\n * Follows the same caching rules as the permission-validation hooks.\n *\n * @example\n * ```tsx\n * const { data } = useCourseAuthoringFlagStates();\n * ```\n */\nexport const useCourseAuthoringFlagStates = () => useQuery<CourseAuthoringFlagStates, Error>({\n queryKey: authzQueryKeys.courseAuthoringFlagStates(),\n queryFn: () => getCourseAuthoringFlagStates(),\n staleTime: 1000 * 60 * 30,\n refetchOnWindowFocus: false,\n retry: false,\n});\n"]}
@@ -0,0 +1,7 @@
1
+ import { type DataTableRow } from '@openedx/paragon';
2
+ /**
3
+ * Returns a handler that toggles `row`, collapsing any other expanded row first so only one
4
+ * is open at a time. Paragon's `isExpandable` allows several, and a table whose rows expand
5
+ * into a nested table only reads clearly with one breakdown showing.
6
+ */
7
+ export declare const useExclusiveRowExpansion: (row: DataTableRow<unknown>) => () => void;
@@ -0,0 +1,24 @@
1
+ import { useContext } from 'react';
2
+ import { DataTableContext } from '@openedx/paragon';
3
+ /**
4
+ * Returns a handler that toggles `row`, collapsing any other expanded row first so only one
5
+ * is open at a time. Paragon's `isExpandable` allows several, and a table whose rows expand
6
+ * into a nested table only reads clearly with one breakdown showing.
7
+ */
8
+ export const useExclusiveRowExpansion = (row) => {
9
+ const instance = useContext(DataTableContext);
10
+ return () => {
11
+ var _a, _b;
12
+ if (!row.isExpanded && instance) {
13
+ const expanded = ((_a = instance.state) === null || _a === void 0 ? void 0 : _a.expanded) || {};
14
+ Object.keys(expanded).forEach((rowId) => {
15
+ var _a;
16
+ if (rowId !== row.id && expanded[rowId]) {
17
+ (_a = instance.toggleRowExpanded) === null || _a === void 0 ? void 0 : _a.call(instance, rowId, false);
18
+ }
19
+ });
20
+ }
21
+ (_b = row.toggleRowExpanded) === null || _b === void 0 ? void 0 : _b.call(row);
22
+ };
23
+ };
24
+ //# sourceMappingURL=useExclusiveRowExpansion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useExclusiveRowExpansion.js","sourceRoot":"","sources":["../../../src/authz-module/hooks/useExclusiveRowExpansion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAqB,MAAM,kBAAkB,CAAC;AASvE;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAA0B,EAAE,EAAE;IACrE,MAAM,QAAQ,GAAG,UAAU,CAAC,gBAAgB,CAAsB,CAAC;IAEnE,OAAO,GAAG,EAAE;;QACV,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,CAAA,MAAA,QAAQ,CAAC,KAAK,0CAAE,QAAQ,KAAI,EAAE,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;;gBACtC,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACxC,MAAA,QAAQ,CAAC,iBAAiB,yDAAG,KAAK,EAAE,KAAK,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,MAAA,GAAG,CAAC,iBAAiB,mDAAI,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useContext } from 'react';\nimport { DataTableContext, type DataTableRow } from '@openedx/paragon';\n\ninterface DataTableInstance {\n state?: {\n expanded?: Record<string, boolean>;\n };\n toggleRowExpanded?: (rowId: string, expanded: boolean) => void;\n}\n\n/**\n * Returns a handler that toggles `row`, collapsing any other expanded row first so only one\n * is open at a time. Paragon's `isExpandable` allows several, and a table whose rows expand\n * into a nested table only reads clearly with one breakdown showing.\n */\nexport const useExclusiveRowExpansion = (row: DataTableRow<unknown>) => {\n const instance = useContext(DataTableContext) as DataTableInstance;\n\n return () => {\n if (!row.isExpanded && instance) {\n const expanded = instance.state?.expanded || {};\n Object.keys(expanded).forEach((rowId) => {\n if (rowId !== row.id && expanded[rowId]) {\n instance.toggleRowExpanded?.(rowId, false);\n }\n });\n }\n row.toggleRowExpanded?.();\n };\n};\n"]}
@@ -3,10 +3,6 @@
3
3
  .authz-module {
4
4
  --height-action-divider: 30px;
5
5
 
6
- .pgn__data-table-wrapper {
7
- padding: 1rem;
8
- }
9
-
10
6
  .filters .dropdown-toggle::after {
11
7
  display: none !important;
12
8
  }
@@ -26,7 +22,6 @@
26
22
 
27
23
  .authz-action-divider {
28
24
  border-right: var(--pgn-size-border-width) solid var(--pgn-color-border);
29
- height: var(--height-action-divider);
30
25
  width: 0;
31
26
  }
32
27
 
@@ -73,6 +68,120 @@
73
68
  max-height: 80vh;
74
69
  }
75
70
  }
71
+
72
+ // Where `.text-truncate` cuts; sized to the design's character budget.
73
+ .authz-cell-username { max-width: 15rem; } // ~24 characters
74
+ .authz-cell-email { max-width: 17rem; } // ~28 characters
75
+
76
+ &.team-members-table {
77
+ // Every row is two lines tall: the assigned-roles cell stacks scope over org.
78
+ th,
79
+ td {
80
+ padding-top: var(--pgn-spacing-spacer-3);
81
+ padding-bottom: var(--pgn-spacing-spacer-3);
82
+ }
83
+
84
+ // Keep the "+N more roles" label on one line.
85
+ td:nth-child(4) {
86
+ white-space: nowrap;
87
+ }
88
+
89
+ /*
90
+ Auto-layout starves "Assigned roles" in favour of the short Username/Email values,
91
+ so widths are pinned. Below `md` these percentages would crush the toggle and action
92
+ columns, so the table falls back to content sizing and scrolls inside Paragon's
93
+ `.pgn__data-table-container`.
94
+ */
95
+ @media (--pgn-size-breakpoint-min-width-md) {
96
+ .pgn__data-table {
97
+ table-layout: fixed;
98
+ }
99
+
100
+ th:nth-child(1) { width: 16%; } // Username
101
+ th:nth-child(2) { width: 18%; } // Email
102
+ th:nth-child(3) { width: 46%; } // Assigned roles
103
+ th:nth-child(4) { width: 13%; } // "+N more roles" toggle
104
+ th:nth-child(5) { width: 7%; } // Actions
105
+
106
+ td {
107
+ overflow: hidden;
108
+ }
109
+
110
+ // The nested table sizes its own columns; it must not inherit the widths above.
111
+ .team-members-table__subtable {
112
+ .pgn__data-table {
113
+ table-layout: auto;
114
+ }
115
+
116
+ th:nth-child(1),
117
+ th:nth-child(2),
118
+ th:nth-child(3) {
119
+ width: auto;
120
+ }
121
+ }
122
+ }
123
+
124
+ // One line per row, so it keeps tighter padding.
125
+ .team-members-table__subtable {
126
+ th,
127
+ td {
128
+ padding-top: var(--pgn-spacing-spacer-2);
129
+ padding-bottom: var(--pgn-spacing-spacer-2);
130
+ }
131
+ }
132
+ }
133
+
134
+ .team-members-table__subtable {
135
+ // The module turns `hr` horizontal below `sm`; this footer divider stays vertical.
136
+ hr {
137
+ border-right: var(--pgn-size-border-width) solid var(--pgn-color-border);
138
+ border-top: none;
139
+ height: 1rem;
140
+ width: 0;
141
+ }
142
+
143
+ // The Card already pads; the module's blanket 1rem would double it up.
144
+ .pgn__data-table-wrapper {
145
+ padding: 0;
146
+ }
147
+
148
+ // Matches PermissionTable's `bg-info-100 text-primary` band. Paragon renders its own
149
+ // `thead`, so the tokens are used rather than the utility classes.
150
+ thead th {
151
+ background-color: var(--pgn-color-info-100);
152
+ color: var(--pgn-color-primary-base);
153
+ }
154
+
155
+ /*
156
+ Paragon stripes with `.pgn__data-table.is-striped tr:nth-child(2n)` — a descendant
157
+ selector, so the striped outer table reaches in and `isStriped={false}` on the inner
158
+ one cannot override it. The `:not()` keeps a nested table that wants stripes.
159
+ */
160
+ .pgn__data-table:not(.is-striped) tr {
161
+ background-color: transparent;
162
+
163
+ // With the stripes gone, rows need an explicit divider to stay readable.
164
+ &:not(:last-child) td {
165
+ border-bottom: var(--pgn-size-border-width) solid var(--pgn-color-border);
166
+ }
167
+ }
168
+ }
169
+
170
+ // Floor the badge to the widest label, so "in" and the scope align down the column.
171
+ .authz-assigned-roles .authz-role-badge { min-width: 11rem; }
172
+
173
+ .authz-scope-cell {
174
+ min-width: 0; // Lets the flex child shrink far enough for `.text-truncate` to cut.
175
+ max-width: 25rem; // org subline, ~40 characters
176
+
177
+ &__name {
178
+ max-width: 22rem; // ~35 characters
179
+ }
180
+
181
+ &__org {
182
+ line-height: 1.2;
183
+ }
184
+ }
76
185
 
77
186
  @media(--pgn-size-breakpoint-max-width-sm){
78
187
  .flex-column-sm {
@@ -84,6 +193,12 @@
84
193
  width: 100%;
85
194
  }
86
195
  }
196
+
197
+ @media (--pgn-size-breakpoint-min-width-md) {
198
+ .authz-action-divider {
199
+ height: var(--height-action-divider);
200
+ }
201
+ }
87
202
  }
88
203
 
89
204
  .highlighted-users-input {
@@ -132,4 +247,3 @@
132
247
  .scope-list {
133
248
  max-height: 500px;
134
249
  }
135
-
@@ -39,10 +39,33 @@ declare const messages: {
39
39
  defaultMessage: string;
40
40
  description: string;
41
41
  };
42
+ 'authz.scope.aggregate.course': {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ 'authz.scope.aggregate.library': {
48
+ id: string;
49
+ defaultMessage: string;
50
+ description: string;
51
+ };
42
52
  'authz.team.toast.retry.label': {
43
53
  id: string;
44
54
  defaultMessage: string;
45
55
  description: string;
46
56
  };
47
57
  };
58
+ /** Aggregate scope labels keyed by the kind of resource the scope covers. */
59
+ export declare const AGGREGATE_SCOPE_LABELS: {
60
+ course: {
61
+ id: string;
62
+ defaultMessage: string;
63
+ description: string;
64
+ };
65
+ library: {
66
+ id: string;
67
+ defaultMessage: string;
68
+ description: string;
69
+ };
70
+ };
48
71
  export default messages;
@@ -40,11 +40,29 @@ const messages = defineMessages({
40
40
  defaultMessage: '<Bold>The request took too long.</Bold> <Br></Br>Please check your connection and try again.',
41
41
  description: 'Request timeout message',
42
42
  },
43
+ // Aggregate scope labels, shared by every table that lists a scope beside its
44
+ // organization. The scope column names only the kind of resource; the organization
45
+ // column says how far it reaches. The wizard keeps its own, longer wording.
46
+ 'authz.scope.aggregate.course': {
47
+ id: 'authz.scope.aggregate.course',
48
+ defaultMessage: 'All courses',
49
+ description: 'Scope column label for a role that covers every course, either across the platform or within one organization. The organization column shows which.',
50
+ },
51
+ 'authz.scope.aggregate.library': {
52
+ id: 'authz.scope.aggregate.library',
53
+ defaultMessage: 'All libraries',
54
+ description: 'Scope column label for a role that covers every library, either across the platform or within one organization. The organization column shows which.',
55
+ },
43
56
  'authz.team.toast.retry.label': {
44
57
  id: 'authz.team.toast.retry.label',
45
58
  defaultMessage: 'Retry',
46
59
  description: 'Label for retry button.',
47
60
  },
48
61
  });
62
+ /** Aggregate scope labels keyed by the kind of resource the scope covers. */
63
+ export const AGGREGATE_SCOPE_LABELS = {
64
+ course: messages['authz.scope.aggregate.course'],
65
+ library: messages['authz.scope.aggregate.library'],
66
+ };
49
67
  export default messages;
50
68
  //# sourceMappingURL=messages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/authz-module/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAC7B;IACE,gCAAgC,EAAE;QAChC,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,kCAAkC;QAClD,WAAW,EAAE,+EAA+E;KAC7F;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,iCAAiC;KAC/C;IACD,wCAAwC,EAAE;QACxC,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,gFAAgF;QAChG,WAAW,EAAE,uBAAuB;KACrC;IACD,kDAAkD,EAAE;QAClD,EAAE,EAAE,kDAAkD;QACtD,cAAc,EAAE,6KAA6K;QAC7L,WAAW,EAAE,2CAA2C;KACzD;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,2FAA2F;QAC3G,WAAW,EAAE,+BAA+B;KAC7C;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,iGAAiG;QACjH,WAAW,EAAE,2BAA2B;KACzC;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,kGAAkG;QAClH,WAAW,EAAE,yCAAyC;KACvD;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,8FAA8F;QAC9G,WAAW,EAAE,yBAAyB;KACvC;IACD,8BAA8B,EAAE;QAC9B,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,yBAAyB;KACvC;CACF,CACF,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages(\n {\n 'authz.management.home.nav.link': {\n id: 'authz.management.home.nav.link',\n defaultMessage: 'Roles and Permissions Management',\n description: 'Text for the roles and permissions management home page title navigation link',\n },\n 'authz.management.assign.role.title': {\n id: 'authz.management.assign.role.title',\n defaultMessage: 'Assign Role',\n description: 'Text for the assign role button',\n },\n 'authz.team.toast.default.error.message': {\n id: 'authz.team.toast.default.error.message',\n defaultMessage: '<Bold>Something went wrong on our end.</Bold> <Br></Br>Please try again later.',\n description: 'Default error message',\n },\n 'authz.team.remove.user.toast.success.description': {\n id: 'authz.team.remove.user.toast.success.description',\n defaultMessage: 'The {role} role has been successfully removed.{rolesCount, plural, =0 { The user no longer has access to this library and has been removed from the member list.} other {}}',\n description: 'Team management remove user toast success',\n },\n 'authz.team.toast.500.error.message': {\n id: 'authz.team.toast.500.error.message',\n defaultMessage: '<Bold>We\\'re experiencing technical difficulties.</Bold> <Br></Br>Please try again later.',\n description: 'Internal server error message',\n },\n 'authz.team.toast.502.error.message': {\n id: 'authz.team.toast.502.error.message',\n defaultMessage: '<Bold>We\\'re having trouble connecting to our services.</Bold> <Br></Br>Please try again later.',\n description: 'Bad gateway error message',\n },\n 'authz.team.toast.503.error.message': {\n id: 'authz.team.toast.503.error.message',\n defaultMessage: '<Bold>The service is temporarily unavailable.</Bold> <Br></Br>Please try again in a few moments.',\n description: 'Service temporarily unavailable message',\n },\n 'authz.team.toast.408.error.message': {\n id: 'authz.team.toast.408.error.message',\n defaultMessage: '<Bold>The request took too long.</Bold> <Br></Br>Please check your connection and try again.',\n description: 'Request timeout message',\n },\n 'authz.team.toast.retry.label': {\n id: 'authz.team.toast.retry.label',\n defaultMessage: 'Retry',\n description: 'Label for retry button.',\n },\n },\n);\n\nexport default messages;\n"]}
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/authz-module/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,QAAQ,GAAG,cAAc,CAC7B;IACE,gCAAgC,EAAE;QAChC,EAAE,EAAE,gCAAgC;QACpC,cAAc,EAAE,kCAAkC;QAClD,WAAW,EAAE,+EAA+E;KAC7F;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,iCAAiC;KAC/C;IACD,wCAAwC,EAAE;QACxC,EAAE,EAAE,wCAAwC;QAC5C,cAAc,EAAE,gFAAgF;QAChG,WAAW,EAAE,uBAAuB;KACrC;IACD,kDAAkD,EAAE;QAClD,EAAE,EAAE,kDAAkD;QACtD,cAAc,EAAE,6KAA6K;QAC7L,WAAW,EAAE,2CAA2C;KACzD;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,2FAA2F;QAC3G,WAAW,EAAE,+BAA+B;KAC7C;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,iGAAiG;QACjH,WAAW,EAAE,2BAA2B;KACzC;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,kGAAkG;QAClH,WAAW,EAAE,yCAAyC;KACvD;IACD,oCAAoC,EAAE;QACpC,EAAE,EAAE,oCAAoC;QACxC,cAAc,EAAE,8FAA8F;QAC9G,WAAW,EAAE,yBAAyB;KACvC;IACD,8EAA8E;IAC9E,mFAAmF;IACnF,4EAA4E;IAC5E,8BAA8B,EAAE;QAC9B,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,aAAa;QAC7B,WAAW,EAAE,qJAAqJ;KACnK;IACD,+BAA+B,EAAE;QAC/B,EAAE,EAAE,+BAA+B;QACnC,cAAc,EAAE,eAAe;QAC/B,WAAW,EAAE,sJAAsJ;KACpK;IACD,8BAA8B,EAAE;QAC9B,EAAE,EAAE,8BAA8B;QAClC,cAAc,EAAE,OAAO;QACvB,WAAW,EAAE,yBAAyB;KACvC;CACF,CACF,CAAC;AAEF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,MAAM,EAAE,QAAQ,CAAC,8BAA8B,CAAC;IAChD,OAAO,EAAE,QAAQ,CAAC,+BAA+B,CAAC;CACnD,CAAC;AAEF,eAAe,QAAQ,CAAC","sourcesContent":["import { defineMessages } from '@openedx/frontend-base';\n\nconst messages = defineMessages(\n {\n 'authz.management.home.nav.link': {\n id: 'authz.management.home.nav.link',\n defaultMessage: 'Roles and Permissions Management',\n description: 'Text for the roles and permissions management home page title navigation link',\n },\n 'authz.management.assign.role.title': {\n id: 'authz.management.assign.role.title',\n defaultMessage: 'Assign Role',\n description: 'Text for the assign role button',\n },\n 'authz.team.toast.default.error.message': {\n id: 'authz.team.toast.default.error.message',\n defaultMessage: '<Bold>Something went wrong on our end.</Bold> <Br></Br>Please try again later.',\n description: 'Default error message',\n },\n 'authz.team.remove.user.toast.success.description': {\n id: 'authz.team.remove.user.toast.success.description',\n defaultMessage: 'The {role} role has been successfully removed.{rolesCount, plural, =0 { The user no longer has access to this library and has been removed from the member list.} other {}}',\n description: 'Team management remove user toast success',\n },\n 'authz.team.toast.500.error.message': {\n id: 'authz.team.toast.500.error.message',\n defaultMessage: '<Bold>We\\'re experiencing technical difficulties.</Bold> <Br></Br>Please try again later.',\n description: 'Internal server error message',\n },\n 'authz.team.toast.502.error.message': {\n id: 'authz.team.toast.502.error.message',\n defaultMessage: '<Bold>We\\'re having trouble connecting to our services.</Bold> <Br></Br>Please try again later.',\n description: 'Bad gateway error message',\n },\n 'authz.team.toast.503.error.message': {\n id: 'authz.team.toast.503.error.message',\n defaultMessage: '<Bold>The service is temporarily unavailable.</Bold> <Br></Br>Please try again in a few moments.',\n description: 'Service temporarily unavailable message',\n },\n 'authz.team.toast.408.error.message': {\n id: 'authz.team.toast.408.error.message',\n defaultMessage: '<Bold>The request took too long.</Bold> <Br></Br>Please check your connection and try again.',\n description: 'Request timeout message',\n },\n // Aggregate scope labels, shared by every table that lists a scope beside its\n // organization. The scope column names only the kind of resource; the organization\n // column says how far it reaches. The wizard keeps its own, longer wording.\n 'authz.scope.aggregate.course': {\n id: 'authz.scope.aggregate.course',\n defaultMessage: 'All courses',\n description: 'Scope column label for a role that covers every course, either across the platform or within one organization. The organization column shows which.',\n },\n 'authz.scope.aggregate.library': {\n id: 'authz.scope.aggregate.library',\n defaultMessage: 'All libraries',\n description: 'Scope column label for a role that covers every library, either across the platform or within one organization. The organization column shows which.',\n },\n 'authz.team.toast.retry.label': {\n id: 'authz.team.toast.retry.label',\n defaultMessage: 'Retry',\n description: 'Label for retry button.',\n },\n },\n);\n\n/** Aggregate scope labels keyed by the kind of resource the scope covers. */\nexport const AGGREGATE_SCOPE_LABELS = {\n course: messages['authz.scope.aggregate.course'],\n library: messages['authz.scope.aggregate.library'],\n};\n\nexport default messages;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"useScopeListData.js","sourceRoot":"","sources":["../../../../src/authz-module/role-assignation-wizard/hooks/useScopeListData.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Scope } from '@src/types';\nimport { useOrgs, useScopes } from '@src/authz-module/data/hooks';\nimport { useCourseAuthoringFlag } from '@src/authz-module/hooks/useCourseAuthoringFlag';\nimport { getOrgAggregateScopeKey, getPlatformAggregateScopeKey } from '@src/authz-module/constants';\nimport type { ContextType } from '@src/authz-module/constants';\nimport messages from '@src/authz-module/role-assignation-wizard/messages';\nimport useScopePermissions from './useScopePermissions';\n\ninterface UseScopeListDataParams {\n contextType: string | undefined;\n search: string;\n orgs: string[];\n}\n\nconst groupByOrg = (acc: Record<string, Scope[]>, scope: Scope): Record<string, Scope[]> => {\n const orgSlug = scope.org!.shortName;\n if (!acc[orgSlug]) acc[orgSlug] = [];\n acc[orgSlug].push(scope);\n return acc;\n};\n\nconst useScopeListData = ({ contextType, search, orgs }: UseScopeListDataParams) => {\n const intl = useIntl();\n const {\n data: scopesData,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n isLoading,\n isError,\n } = useScopes({\n scopeType: contextType,\n search: search || undefined,\n orgs: orgs.length ? orgs : undefined,\n managementPermissionOnly: true,\n });\n\n const { data: orgsData } = useOrgs();\n const organizations = orgsData?.results;\n\n const { isCourseEnabled, isOrgAuthoringEnabled } = useCourseAuthoringFlag();\n\n const { allScopes, totalCount } = useMemo(\n () => {\n const scopes = scopesData?.pages.flatMap((page) => page.results) ?? [];\n const serverCount = scopesData?.pages[0]?.count ?? 0;\n // Course scopes are gated by the course-authoring flag; libraries always pass.\n if (contextType !== 'course') return { allScopes: scopes, totalCount: serverCount };\n const enabledScopes = scopes.filter((scope) => isCourseEnabled(scope.externalKey));\n // The server count includes authoring-disabled courses this filter hides; subtract\n // the ones already loaded so the reported total converges as pages arrive.\n return {\n allScopes: enabledScopes,\n totalCount: serverCount - (scopes.length - enabledScopes.length),\n };\n },\n [scopesData, contextType, isCourseEnabled],\n );\n\n const scopesByOrg = useMemo(\n () => allScopes\n .filter((s: Scope) => !!s.org)\n .reduce<Record<string, Scope[]>>(groupByOrg, {}),\n [allScopes],\n );\n\n const orderedOrgs = useMemo(() => {\n const orgSlugs = new Set(Object.keys(scopesByOrg));\n // Add orgs from the organizations list (respecting the active org filter)\n organizations?.forEach((org) => {\n if (!orgs.length || orgs.includes(org.shortName)) {\n orgSlugs.add(org.shortName);\n }\n });\n return [...orgSlugs].sort();\n }, [scopesByOrg, organizations, orgs]);\n\n const { hasPlatformPermission, orgHasPermission } = useScopePermissions({ contextType, orderedOrgs });\n\n const aggregateDescription = contextType === 'course'\n ? intl.formatMessage(messages['wizard.step2.scope.aggregate.description.course'])\n : intl.formatMessage(messages['wizard.step2.scope.aggregate.description.library']);\n\n const platformAggregateLabel = contextType === 'course'\n ? intl.formatMessage(messages['wizard.step2.scope.aggregate.platform.label.course'])\n : intl.formatMessage(messages['wizard.step2.scope.aggregate.platform.label.library']);\n\n const orgAggregateLabel = contextType === 'course'\n ? intl.formatMessage(messages['wizard.step2.scopeList.aggregate.label.course'])\n : intl.formatMessage(messages['wizard.step2.scopeList.aggregate.label.library']);\n\n const platformAggregateScopeItem: Scope | null = (contextType && hasPlatformPermission)\n ? {\n externalKey: getPlatformAggregateScopeKey(contextType as ContextType),\n displayName: platformAggregateLabel,\n description: aggregateDescription,\n org: null,\n }\n : null;\n\n /**\n * Builds a map of org-level aggregate scopes keyed by org slug.\n *\n * Each entry represents a wildcard scope that grants access to all courses or\n * libraries within an org (e.g. `course-v1:OrgSlug+*` or `lib:OrgSlug:*`).\n * Only orgs where the current user already holds permission are included.\n *\n * Returns an empty object when `contextType` is not yet defined.\n */\n const orgAggregateScopeItems = useMemo<Record<string, Scope>>(() => {\n if (!contextType) return {};\n return Object.fromEntries(\n orderedOrgs\n .filter((orgSlug) => orgHasPermission[orgSlug])\n // The org-wide aggregate is only offered when authoring is enabled for that org.\n .filter((orgSlug) => contextType !== 'course' || isOrgAuthoringEnabled(orgSlug))\n .map((orgSlug) => [\n orgSlug,\n {\n externalKey: getOrgAggregateScopeKey(contextType as ContextType, orgSlug),\n displayName: orgAggregateLabel,\n description: aggregateDescription,\n org: { id: '0', name: orgSlug, shortName: orgSlug },\n } satisfies Scope,\n ]),\n );\n }, [orderedOrgs, contextType, orgHasPermission, orgAggregateLabel, aggregateDescription, isOrgAuthoringEnabled]);\n\n return {\n organizations,\n orderedOrgs,\n scopesByOrg,\n allScopes,\n totalCount,\n queryState: {\n isLoading, isFetchingNextPage, hasNextPage, isError, fetchNextPage,\n },\n platformAggregateScopeItem,\n orgAggregateScopeItems,\n };\n};\n\nexport default useScopeListData;\n"]}
1
+ {"version":3,"file":"useScopeListData.js","sourceRoot":"","sources":["../../../../src/authz-module/role-assignation-wizard/hooks/useScopeListData.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport { Scope } from '@src/types';\nimport { useOrgs, useScopes } from '@src/authz-module/data/hooks';\nimport { useCourseAuthoringFlag } from '@src/authz-module/hooks/useCourseAuthoringFlag';\nimport { getOrgAggregateScopeKey, getPlatformAggregateScopeKey } from '@src/authz-module/constants';\nimport type { ContextType } from '@src/authz-module/constants';\nimport messages from '../messages';\nimport useScopePermissions from './useScopePermissions';\n\ninterface UseScopeListDataParams {\n contextType: string | undefined;\n search: string;\n orgs: string[];\n}\n\nconst groupByOrg = (acc: Record<string, Scope[]>, scope: Scope): Record<string, Scope[]> => {\n const orgSlug = scope.org!.shortName;\n if (!acc[orgSlug]) acc[orgSlug] = [];\n acc[orgSlug].push(scope);\n return acc;\n};\n\nconst useScopeListData = ({ contextType, search, orgs }: UseScopeListDataParams) => {\n const intl = useIntl();\n const {\n data: scopesData,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n isLoading,\n isError,\n } = useScopes({\n scopeType: contextType,\n search: search || undefined,\n orgs: orgs.length ? orgs : undefined,\n managementPermissionOnly: true,\n });\n\n const { data: orgsData } = useOrgs();\n const organizations = orgsData?.results;\n\n const { isCourseEnabled, isOrgAuthoringEnabled } = useCourseAuthoringFlag();\n\n const { allScopes, totalCount } = useMemo(\n () => {\n const scopes = scopesData?.pages.flatMap((page) => page.results) ?? [];\n const serverCount = scopesData?.pages[0]?.count ?? 0;\n // Course scopes are gated by the course-authoring flag; libraries always pass.\n if (contextType !== 'course') return { allScopes: scopes, totalCount: serverCount };\n const enabledScopes = scopes.filter((scope) => isCourseEnabled(scope.externalKey));\n // The server count includes authoring-disabled courses this filter hides; subtract\n // the ones already loaded so the reported total converges as pages arrive.\n return {\n allScopes: enabledScopes,\n totalCount: serverCount - (scopes.length - enabledScopes.length),\n };\n },\n [scopesData, contextType, isCourseEnabled],\n );\n\n const scopesByOrg = useMemo(\n () => allScopes\n .filter((s: Scope) => !!s.org)\n .reduce<Record<string, Scope[]>>(groupByOrg, {}),\n [allScopes],\n );\n\n const orderedOrgs = useMemo(() => {\n const orgSlugs = new Set(Object.keys(scopesByOrg));\n // Add orgs from the organizations list (respecting the active org filter)\n organizations?.forEach((org) => {\n if (!orgs.length || orgs.includes(org.shortName)) {\n orgSlugs.add(org.shortName);\n }\n });\n return [...orgSlugs].sort();\n }, [scopesByOrg, organizations, orgs]);\n\n const { hasPlatformPermission, orgHasPermission } = useScopePermissions({ contextType, orderedOrgs });\n\n const aggregateDescription = contextType === 'course'\n ? intl.formatMessage(messages['wizard.step2.scope.aggregate.description.course'])\n : intl.formatMessage(messages['wizard.step2.scope.aggregate.description.library']);\n\n const platformAggregateLabel = contextType === 'course'\n ? intl.formatMessage(messages['wizard.step2.scope.aggregate.platform.label.course'])\n : intl.formatMessage(messages['wizard.step2.scope.aggregate.platform.label.library']);\n\n const orgAggregateLabel = contextType === 'course'\n ? intl.formatMessage(messages['wizard.step2.scopeList.aggregate.label.course'])\n : intl.formatMessage(messages['wizard.step2.scopeList.aggregate.label.library']);\n\n const platformAggregateScopeItem: Scope | null = (contextType && hasPlatformPermission)\n ? {\n externalKey: getPlatformAggregateScopeKey(contextType as ContextType),\n displayName: platformAggregateLabel,\n description: aggregateDescription,\n org: null,\n }\n : null;\n\n /**\n * Builds a map of org-level aggregate scopes keyed by org slug.\n *\n * Each entry represents a wildcard scope that grants access to all courses or\n * libraries within an org (e.g. `course-v1:OrgSlug+*` or `lib:OrgSlug:*`).\n * Only orgs where the current user already holds permission are included.\n *\n * Returns an empty object when `contextType` is not yet defined.\n */\n const orgAggregateScopeItems = useMemo<Record<string, Scope>>(() => {\n if (!contextType) return {};\n return Object.fromEntries(\n orderedOrgs\n .filter((orgSlug) => orgHasPermission[orgSlug])\n // The org-wide aggregate is only offered when authoring is enabled for that org.\n .filter((orgSlug) => contextType !== 'course' || isOrgAuthoringEnabled(orgSlug))\n .map((orgSlug) => [\n orgSlug,\n {\n externalKey: getOrgAggregateScopeKey(contextType as ContextType, orgSlug),\n displayName: orgAggregateLabel,\n description: aggregateDescription,\n org: { id: '0', name: orgSlug, shortName: orgSlug },\n } satisfies Scope,\n ]),\n );\n }, [orderedOrgs, contextType, orgHasPermission, orgAggregateLabel, aggregateDescription, isOrgAuthoringEnabled]);\n\n return {\n organizations,\n orderedOrgs,\n scopesByOrg,\n allScopes,\n totalCount,\n queryState: {\n isLoading, isFetchingNextPage, hasNextPage, isError, fetchNextPage,\n },\n platformAggregateScopeItem,\n orgAggregateScopeItems,\n };\n};\n\nexport default useScopeListData;\n"]}