@openedx/frontend-app-admin-console 1.0.0-alpha.0

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 (236) hide show
  1. package/LICENSE +661 -0
  2. package/README.rst +164 -0
  3. package/dist/Main.d.ts +3 -0
  4. package/dist/Main.js +15 -0
  5. package/dist/Main.js.map +1 -0
  6. package/dist/app.d.ts +3 -0
  7. package/dist/app.js +10 -0
  8. package/dist/app.js.map +1 -0
  9. package/dist/authz-module/audit-user/index.d.ts +2 -0
  10. package/dist/authz-module/audit-user/index.js +191 -0
  11. package/dist/authz-module/audit-user/index.js.map +1 -0
  12. package/dist/authz-module/audit-user/messages.d.ts +58 -0
  13. package/dist/authz-module/audit-user/messages.js +60 -0
  14. package/dist/authz-module/audit-user/messages.js.map +1 -0
  15. package/dist/authz-module/authz-home/index.d.ts +2 -0
  16. package/dist/authz-module/authz-home/index.js +23 -0
  17. package/dist/authz-module/authz-home/index.js.map +1 -0
  18. package/dist/authz-module/authz-home/messages.d.ts +23 -0
  19. package/dist/authz-module/authz-home/messages.js +25 -0
  20. package/dist/authz-module/authz-home/messages.js.map +1 -0
  21. package/dist/authz-module/components/AddRoleButton.d.ts +6 -0
  22. package/dist/authz-module/components/AddRoleButton.js +22 -0
  23. package/dist/authz-module/components/AddRoleButton.js.map +1 -0
  24. package/dist/authz-module/components/AnchorButton.d.ts +2 -0
  25. package/dist/authz-module/components/AnchorButton.js +35 -0
  26. package/dist/authz-module/components/AnchorButton.js.map +1 -0
  27. package/dist/authz-module/components/AuthZLayout.d.ts +12 -0
  28. package/dist/authz-module/components/AuthZLayout.js +19 -0
  29. package/dist/authz-module/components/AuthZLayout.js.map +1 -0
  30. package/dist/authz-module/components/AuthZTitle.d.ts +20 -0
  31. package/dist/authz-module/components/AuthZTitle.js +22 -0
  32. package/dist/authz-module/components/AuthZTitle.js.map +1 -0
  33. package/dist/authz-module/components/ConfirmDeletionModal.d.ts +15 -0
  34. package/dist/authz-module/components/ConfirmDeletionModal.js +21 -0
  35. package/dist/authz-module/components/ConfirmDeletionModal.js.map +1 -0
  36. package/dist/authz-module/components/ErrorPage/index.d.ts +3 -0
  37. package/dist/authz-module/components/ErrorPage/index.js +59 -0
  38. package/dist/authz-module/components/ErrorPage/index.js.map +1 -0
  39. package/dist/authz-module/components/ErrorPage/messages.d.ts +53 -0
  40. package/dist/authz-module/components/ErrorPage/messages.js +55 -0
  41. package/dist/authz-module/components/ErrorPage/messages.js.map +1 -0
  42. package/dist/authz-module/components/PermissionTable.d.ts +9 -0
  43. package/dist/authz-module/components/PermissionTable.js +24 -0
  44. package/dist/authz-module/components/PermissionTable.js.map +1 -0
  45. package/dist/authz-module/components/RenderAdminRole.d.ts +5 -0
  46. package/dist/authz-module/components/RenderAdminRole.js +13 -0
  47. package/dist/authz-module/components/RenderAdminRole.js.map +1 -0
  48. package/dist/authz-module/components/RenderPermissionColumn.d.ts +6 -0
  49. package/dist/authz-module/components/RenderPermissionColumn.js +8 -0
  50. package/dist/authz-module/components/RenderPermissionColumn.js.map +1 -0
  51. package/dist/authz-module/components/RenderPermissionInLine.d.ts +6 -0
  52. package/dist/authz-module/components/RenderPermissionInLine.js +8 -0
  53. package/dist/authz-module/components/RenderPermissionInLine.js.map +1 -0
  54. package/dist/authz-module/components/ResourceTooltip.d.ts +11 -0
  55. package/dist/authz-module/components/ResourceTooltip.js +9 -0
  56. package/dist/authz-module/components/ResourceTooltip.js.map +1 -0
  57. package/dist/authz-module/components/RoleCard/constants.d.ts +14 -0
  58. package/dist/authz-module/components/RoleCard/constants.js +15 -0
  59. package/dist/authz-module/components/RoleCard/constants.js.map +1 -0
  60. package/dist/authz-module/components/RoleCard/messages.d.ts +73 -0
  61. package/dist/authz-module/components/RoleCard/messages.js +75 -0
  62. package/dist/authz-module/components/RoleCard/messages.js.map +1 -0
  63. package/dist/authz-module/components/TableCells.d.ts +29 -0
  64. package/dist/authz-module/components/TableCells.js +137 -0
  65. package/dist/authz-module/components/TableCells.js.map +1 -0
  66. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.d.ts +3 -0
  67. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.js +47 -0
  68. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.js.map +1 -0
  69. package/dist/authz-module/components/TableControlBar/OrgFilter.d.ts +5 -0
  70. package/dist/authz-module/components/TableControlBar/OrgFilter.js +36 -0
  71. package/dist/authz-module/components/TableControlBar/OrgFilter.js.map +1 -0
  72. package/dist/authz-module/components/TableControlBar/RolesFilter.d.ts +4 -0
  73. package/dist/authz-module/components/TableControlBar/RolesFilter.js +29 -0
  74. package/dist/authz-module/components/TableControlBar/RolesFilter.js.map +1 -0
  75. package/dist/authz-module/components/TableControlBar/ScopesFilter.d.ts +4 -0
  76. package/dist/authz-module/components/TableControlBar/ScopesFilter.js +45 -0
  77. package/dist/authz-module/components/TableControlBar/ScopesFilter.js.map +1 -0
  78. package/dist/authz-module/components/TableControlBar/SearchFilter.d.ts +7 -0
  79. package/dist/authz-module/components/TableControlBar/SearchFilter.js +8 -0
  80. package/dist/authz-module/components/TableControlBar/SearchFilter.js.map +1 -0
  81. package/dist/authz-module/components/TableControlBar/TableControlBar.d.ts +5 -0
  82. package/dist/authz-module/components/TableControlBar/TableControlBar.js +99 -0
  83. package/dist/authz-module/components/TableControlBar/TableControlBar.js.map +1 -0
  84. package/dist/authz-module/components/TableControlBar/types.d.ts +18 -0
  85. package/dist/authz-module/components/TableControlBar/types.js +2 -0
  86. package/dist/authz-module/components/TableControlBar/types.js.map +1 -0
  87. package/dist/authz-module/components/TableFooter/TableFooter.d.ts +2 -0
  88. package/dist/authz-module/components/TableFooter/TableFooter.js +15 -0
  89. package/dist/authz-module/components/TableFooter/TableFooter.js.map +1 -0
  90. package/dist/authz-module/components/UserPermissions.d.ts +9 -0
  91. package/dist/authz-module/components/UserPermissions.js +56 -0
  92. package/dist/authz-module/components/UserPermissions.js.map +1 -0
  93. package/dist/authz-module/components/ViewMoreLink.d.ts +8 -0
  94. package/dist/authz-module/components/ViewMoreLink.js +8 -0
  95. package/dist/authz-module/components/ViewMoreLink.js.map +1 -0
  96. package/dist/authz-module/components/constants.d.ts +13 -0
  97. package/dist/authz-module/components/constants.js +80 -0
  98. package/dist/authz-module/components/constants.js.map +1 -0
  99. package/dist/authz-module/components/messages.d.ts +183 -0
  100. package/dist/authz-module/components/messages.js +185 -0
  101. package/dist/authz-module/components/messages.js.map +1 -0
  102. package/dist/authz-module/constants.d.ts +38 -0
  103. package/dist/authz-module/constants.js +77 -0
  104. package/dist/authz-module/constants.js.map +1 -0
  105. package/dist/authz-module/data/api.d.ts +109 -0
  106. package/dist/authz-module/data/api.js +107 -0
  107. package/dist/authz-module/data/api.js.map +1 -0
  108. package/dist/authz-module/data/hooks.d.ts +94 -0
  109. package/dist/authz-module/data/hooks.js +191 -0
  110. package/dist/authz-module/data/hooks.js.map +1 -0
  111. package/dist/authz-module/hooks/useCourseAuthoringFlag.d.ts +26 -0
  112. package/dist/authz-module/hooks/useCourseAuthoringFlag.js +86 -0
  113. package/dist/authz-module/hooks/useCourseAuthoringFlag.js.map +1 -0
  114. package/dist/authz-module/hooks/useQuerySettings.d.ts +27 -0
  115. package/dist/authz-module/hooks/useQuerySettings.js +72 -0
  116. package/dist/authz-module/hooks/useQuerySettings.js.map +1 -0
  117. package/dist/authz-module/hooks/useViewTeamPermissions.d.ts +5 -0
  118. package/dist/authz-module/hooks/useViewTeamPermissions.js +13 -0
  119. package/dist/authz-module/hooks/useViewTeamPermissions.js.map +1 -0
  120. package/dist/authz-module/index.d.ts +3 -0
  121. package/dist/authz-module/index.js +20 -0
  122. package/dist/authz-module/index.js.map +1 -0
  123. package/dist/authz-module/index.scss +131 -0
  124. package/dist/authz-module/messages.d.ts +48 -0
  125. package/dist/authz-module/messages.js +50 -0
  126. package/dist/authz-module/messages.js.map +1 -0
  127. package/dist/authz-module/role-assignation-wizard/AssignRoleWizard.d.ts +8 -0
  128. package/dist/authz-module/role-assignation-wizard/AssignRoleWizard.js +154 -0
  129. package/dist/authz-module/role-assignation-wizard/AssignRoleWizard.js.map +1 -0
  130. package/dist/authz-module/role-assignation-wizard/AssignRoleWizardPage.d.ts +2 -0
  131. package/dist/authz-module/role-assignation-wizard/AssignRoleWizardPage.js +39 -0
  132. package/dist/authz-module/role-assignation-wizard/AssignRoleWizardPage.js.map +1 -0
  133. package/dist/authz-module/role-assignation-wizard/components/DefineApplicationScopeStep.d.ts +8 -0
  134. package/dist/authz-module/role-assignation-wizard/components/DefineApplicationScopeStep.js +39 -0
  135. package/dist/authz-module/role-assignation-wizard/components/DefineApplicationScopeStep.js.map +1 -0
  136. package/dist/authz-module/role-assignation-wizard/components/HighlightedUsersInput.d.ts +11 -0
  137. package/dist/authz-module/role-assignation-wizard/components/HighlightedUsersInput.js +36 -0
  138. package/dist/authz-module/role-assignation-wizard/components/HighlightedUsersInput.js.map +1 -0
  139. package/dist/authz-module/role-assignation-wizard/components/OrgSection.d.ts +10 -0
  140. package/dist/authz-module/role-assignation-wizard/components/OrgSection.js +14 -0
  141. package/dist/authz-module/role-assignation-wizard/components/OrgSection.js.map +1 -0
  142. package/dist/authz-module/role-assignation-wizard/components/ScopeCheckboxItem.d.ts +8 -0
  143. package/dist/authz-module/role-assignation-wizard/components/ScopeCheckboxItem.js +5 -0
  144. package/dist/authz-module/role-assignation-wizard/components/ScopeCheckboxItem.js.map +1 -0
  145. package/dist/authz-module/role-assignation-wizard/components/ScopeFilterBar.d.ts +12 -0
  146. package/dist/authz-module/role-assignation-wizard/components/ScopeFilterBar.js +12 -0
  147. package/dist/authz-module/role-assignation-wizard/components/ScopeFilterBar.js.map +1 -0
  148. package/dist/authz-module/role-assignation-wizard/components/ScopeList.d.ts +20 -0
  149. package/dist/authz-module/role-assignation-wizard/components/ScopeList.js +30 -0
  150. package/dist/authz-module/role-assignation-wizard/components/ScopeList.js.map +1 -0
  151. package/dist/authz-module/role-assignation-wizard/components/SelectUsersAndRoleStep.d.ts +12 -0
  152. package/dist/authz-module/role-assignation-wizard/components/SelectUsersAndRoleStep.js +34 -0
  153. package/dist/authz-module/role-assignation-wizard/components/SelectUsersAndRoleStep.js.map +1 -0
  154. package/dist/authz-module/role-assignation-wizard/constants.d.ts +5 -0
  155. package/dist/authz-module/role-assignation-wizard/constants.js +6 -0
  156. package/dist/authz-module/role-assignation-wizard/constants.js.map +1 -0
  157. package/dist/authz-module/role-assignation-wizard/hooks/useScopeListData.d.ts +23 -0
  158. package/dist/authz-module/role-assignation-wizard/hooks/useScopeListData.js +112 -0
  159. package/dist/authz-module/role-assignation-wizard/hooks/useScopeListData.js.map +1 -0
  160. package/dist/authz-module/role-assignation-wizard/hooks/useScopePermissions.d.ts +10 -0
  161. package/dist/authz-module/role-assignation-wizard/hooks/useScopePermissions.js +54 -0
  162. package/dist/authz-module/role-assignation-wizard/hooks/useScopePermissions.js.map +1 -0
  163. package/dist/authz-module/role-assignation-wizard/messages.d.ts +243 -0
  164. package/dist/authz-module/role-assignation-wizard/messages.js +258 -0
  165. package/dist/authz-module/role-assignation-wizard/messages.js.map +1 -0
  166. package/dist/authz-module/role-assignation-wizard/utils.d.ts +5 -0
  167. package/dist/authz-module/role-assignation-wizard/utils.js +16 -0
  168. package/dist/authz-module/role-assignation-wizard/utils.js.map +1 -0
  169. package/dist/authz-module/roles-permissions/RolesPermissions.d.ts +2 -0
  170. package/dist/authz-module/roles-permissions/RolesPermissions.js +35 -0
  171. package/dist/authz-module/roles-permissions/RolesPermissions.js.map +1 -0
  172. package/dist/authz-module/roles-permissions/course/constants.d.ts +39 -0
  173. package/dist/authz-module/roles-permissions/course/constants.js +474 -0
  174. package/dist/authz-module/roles-permissions/course/constants.js.map +1 -0
  175. package/dist/authz-module/roles-permissions/index.d.ts +10 -0
  176. package/dist/authz-module/roles-permissions/index.js +15 -0
  177. package/dist/authz-module/roles-permissions/index.js.map +1 -0
  178. package/dist/authz-module/roles-permissions/library/constants.d.ts +18 -0
  179. package/dist/authz-module/roles-permissions/library/constants.js +193 -0
  180. package/dist/authz-module/roles-permissions/library/constants.js.map +1 -0
  181. package/dist/authz-module/roles-permissions/messages.d.ts +63 -0
  182. package/dist/authz-module/roles-permissions/messages.js +65 -0
  183. package/dist/authz-module/roles-permissions/messages.js.map +1 -0
  184. package/dist/authz-module/roles-permissions/utils.d.ts +41 -0
  185. package/dist/authz-module/roles-permissions/utils.js +70 -0
  186. package/dist/authz-module/roles-permissions/utils.js.map +1 -0
  187. package/dist/authz-module/team-members/TeamMembersTable.d.ts +5 -0
  188. package/dist/authz-module/team-members/TeamMembersTable.js +107 -0
  189. package/dist/authz-module/team-members/TeamMembersTable.js.map +1 -0
  190. package/dist/authz-module/team-members/messages.d.ts +33 -0
  191. package/dist/authz-module/team-members/messages.js +35 -0
  192. package/dist/authz-module/team-members/messages.js.map +1 -0
  193. package/dist/authz-module/utils.d.ts +24 -0
  194. package/dist/authz-module/utils.js +45 -0
  195. package/dist/authz-module/utils.js.map +1 -0
  196. package/dist/components/LoadingPage.d.ts +2 -0
  197. package/dist/components/LoadingPage.js +5 -0
  198. package/dist/components/LoadingPage.js.map +1 -0
  199. package/dist/components/ToastManager/ToastManagerContext.d.ts +24 -0
  200. package/dist/components/ToastManager/ToastManagerContext.js +91 -0
  201. package/dist/components/ToastManager/ToastManagerContext.js.map +1 -0
  202. package/dist/constants.d.ts +11 -0
  203. package/dist/constants.js +15 -0
  204. package/dist/constants.js.map +1 -0
  205. package/dist/data/api.d.ts +4 -0
  206. package/dist/data/api.js +21 -0
  207. package/dist/data/api.js.map +1 -0
  208. package/dist/data/hooks.d.ts +38 -0
  209. package/dist/data/hooks.js +69 -0
  210. package/dist/data/hooks.js.map +1 -0
  211. package/dist/data/types.d.ts +38 -0
  212. package/dist/data/types.js +2 -0
  213. package/dist/data/types.js.map +1 -0
  214. package/dist/data/utils.d.ts +6 -0
  215. package/dist/data/utils.js +11 -0
  216. package/dist/data/utils.js.map +1 -0
  217. package/dist/i18n/index.d.ts +1 -0
  218. package/dist/i18n/index.js +2 -0
  219. package/dist/i18n/index.js.map +1 -0
  220. package/dist/index.d.ts +3 -0
  221. package/dist/index.js +4 -0
  222. package/dist/index.js.map +1 -0
  223. package/dist/messages.d.ts +8 -0
  224. package/dist/messages.js +10 -0
  225. package/dist/messages.js.map +1 -0
  226. package/dist/providers.d.ts +3 -0
  227. package/dist/providers.js +4 -0
  228. package/dist/providers.js.map +1 -0
  229. package/dist/routes.d.ts +11 -0
  230. package/dist/routes.js +16 -0
  231. package/dist/routes.js.map +1 -0
  232. package/dist/style.scss +15 -0
  233. package/dist/types.d.ts +93 -0
  234. package/dist/types.js +2 -0
  235. package/dist/types.js.map +1 -0
  236. package/package.json +88 -0
@@ -0,0 +1,72 @@
1
+ import { useCallback, useState } from 'react';
2
+ var SortOrderKeys;
3
+ (function (SortOrderKeys) {
4
+ SortOrderKeys["ASC"] = "asc";
5
+ SortOrderKeys["DESC"] = "desc";
6
+ })(SortOrderKeys || (SortOrderKeys = {}));
7
+ /**
8
+ * Custom hook to manage query settings for table data fetching
9
+ * Converts DataTable filter/sort/pagination settings to API query parameters
10
+ * and manages URL synchronization
11
+ *
12
+ * @param initialQuerySettings - Initial query settings
13
+ * @returns Object containing querySettings and handleTableFetch function
14
+ */
15
+ export const useQuerySettings = (initialQuerySettings = {
16
+ roles: null,
17
+ scopes: null,
18
+ organizations: null,
19
+ search: null,
20
+ pageSize: 10,
21
+ pageIndex: 0,
22
+ order: null,
23
+ sortBy: null,
24
+ }) => {
25
+ const [querySettings, setQuerySettings] = useState(initialQuerySettings);
26
+ const handleTableFetch = useCallback((tableFilters) => {
27
+ setQuerySettings((prevSettings) => {
28
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
29
+ // Extract filters
30
+ const rolesFilter = (_d = (_c = (_b = (_a = tableFilters.filters) === null || _a === void 0 ? void 0 : _a.find((filter) => filter.id === 'role')) === null || _b === void 0 ? void 0 : _b.value) === null || _c === void 0 ? void 0 : _c.join(',')) !== null && _d !== void 0 ? _d : '';
31
+ const searchFilter = (_g = (_f = (_e = tableFilters.filters) === null || _e === void 0 ? void 0 : _e.find((filter) => filter.id === 'username')) === null || _f === void 0 ? void 0 : _f.value) !== null && _g !== void 0 ? _g : '';
32
+ const organizationsFilter = (_l = (_k = (_j = (_h = tableFilters.filters) === null || _h === void 0 ? void 0 : _h.find((filter) => filter.id === 'org')) === null || _j === void 0 ? void 0 : _j.value) === null || _k === void 0 ? void 0 : _k.join(',')) !== null && _l !== void 0 ? _l : '';
33
+ const scopesFilter = (_q = (_p = (_o = (_m = tableFilters.filters) === null || _m === void 0 ? void 0 : _m.find((filter) => filter.id === 'scope')) === null || _o === void 0 ? void 0 : _o.value) === null || _p === void 0 ? void 0 : _p.join(',')) !== null && _q !== void 0 ? _q : '';
34
+ // Extract pagination
35
+ const { pageSize = 10, pageIndex = 0 } = tableFilters;
36
+ // Extract and convert sorting
37
+ let sortByOption = '';
38
+ let sortByOrder = '';
39
+ if ((_r = tableFilters.sortBy) === null || _r === void 0 ? void 0 : _r.length) {
40
+ sortByOption = (_s = tableFilters.sortBy[0]) === null || _s === void 0 ? void 0 : _s.id.replace(/([A-Z])/g, '_$1').toLowerCase();
41
+ sortByOrder = ((_t = tableFilters.sortBy[0]) === null || _t === void 0 ? void 0 : _t.desc) ? SortOrderKeys.DESC : SortOrderKeys.ASC;
42
+ }
43
+ const newQuerySettings = {
44
+ roles: rolesFilter || null,
45
+ scopes: scopesFilter || null,
46
+ organizations: organizationsFilter || null,
47
+ search: searchFilter || null,
48
+ sortBy: sortByOption || null,
49
+ order: sortByOrder || null,
50
+ pageSize,
51
+ pageIndex,
52
+ };
53
+ const hasChanged = (prevSettings.roles !== newQuerySettings.roles
54
+ || prevSettings.scopes !== newQuerySettings.scopes
55
+ || prevSettings.organizations !== newQuerySettings.organizations
56
+ || prevSettings.search !== newQuerySettings.search
57
+ || prevSettings.pageSize !== newQuerySettings.pageSize
58
+ || prevSettings.pageIndex !== newQuerySettings.pageIndex
59
+ || prevSettings.sortBy !== newQuerySettings.sortBy
60
+ || prevSettings.order !== newQuerySettings.order);
61
+ if (!hasChanged) {
62
+ return prevSettings; // No change, prevent unnecessary update
63
+ }
64
+ return newQuerySettings;
65
+ });
66
+ }, []);
67
+ return {
68
+ querySettings,
69
+ handleTableFetch,
70
+ };
71
+ };
72
+ //# sourceMappingURL=useQuerySettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useQuerySettings.js","sourceRoot":"","sources":["../../../src/authz-module/hooks/useQuerySettings.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from 'react';\nimport { QuerySettings } from '@src/authz-module/data/api';\n\ninterface DataTableFilters {\n pageSize: number;\n pageIndex: number;\n sortBy: { id: string; desc: boolean }[];\n filters: { id: string; value: any }[];\n}\n\ninterface UseQuerySettingsReturn {\n querySettings: QuerySettings;\n handleTableFetch: (tableFilters: DataTableFilters) => void;\n}\n\nenum SortOrderKeys {\n ASC = 'asc',\n DESC = 'desc',\n}\n\n/**\n * Custom hook to manage query settings for table data fetching\n * Converts DataTable filter/sort/pagination settings to API query parameters\n * and manages URL synchronization\n *\n * @param initialQuerySettings - Initial query settings\n * @returns Object containing querySettings and handleTableFetch function\n */\nexport const useQuerySettings = (\n initialQuerySettings: QuerySettings = {\n roles: null,\n scopes: null,\n organizations: null,\n search: null,\n pageSize: 10,\n pageIndex: 0,\n order: null,\n sortBy: null,\n },\n): UseQuerySettingsReturn => {\n const [querySettings, setQuerySettings] = useState<QuerySettings>(initialQuerySettings);\n\n const handleTableFetch = useCallback((tableFilters: DataTableFilters) => {\n setQuerySettings((prevSettings) => {\n // Extract filters\n const rolesFilter = tableFilters.filters?.find((filter) => filter.id === 'role')?.value?.join(',') ?? '';\n const searchFilter = tableFilters.filters?.find((filter) => filter.id === 'username')?.value ?? '';\n const organizationsFilter = tableFilters.filters?.find((filter) => filter.id === 'org')?.value?.join(',') ?? '';\n const scopesFilter = tableFilters.filters?.find((filter) => filter.id === 'scope')?.value?.join(',') ?? '';\n\n // Extract pagination\n const { pageSize = 10, pageIndex = 0 } = tableFilters;\n\n // Extract and convert sorting\n let sortByOption = '';\n let sortByOrder = '';\n if (tableFilters.sortBy?.length) {\n sortByOption = tableFilters.sortBy[0]?.id.replace(/([A-Z])/g, '_$1').toLowerCase();\n sortByOrder = tableFilters.sortBy[0]?.desc ? SortOrderKeys.DESC : SortOrderKeys.ASC;\n }\n\n const newQuerySettings: QuerySettings = {\n roles: rolesFilter || null,\n scopes: scopesFilter || null,\n organizations: organizationsFilter || null,\n search: searchFilter || null,\n sortBy: sortByOption || null,\n order: sortByOrder || null,\n pageSize,\n pageIndex,\n };\n\n const hasChanged = (\n prevSettings.roles !== newQuerySettings.roles\n || prevSettings.scopes !== newQuerySettings.scopes\n || prevSettings.organizations !== newQuerySettings.organizations\n || prevSettings.search !== newQuerySettings.search\n || prevSettings.pageSize !== newQuerySettings.pageSize\n || prevSettings.pageIndex !== newQuerySettings.pageIndex\n || prevSettings.sortBy !== newQuerySettings.sortBy\n || prevSettings.order !== newQuerySettings.order\n );\n\n if (!hasChanged) {\n return prevSettings; // No change, prevent unnecessary update\n }\n\n return newQuerySettings;\n });\n }, []);\n\n return {\n querySettings,\n handleTableFetch,\n };\n};\n"]}
@@ -0,0 +1,5 @@
1
+ export declare const useViewTeamPermissions: () => {
2
+ isCourseViewAllowed: boolean;
3
+ isLibraryViewAllowed: boolean;
4
+ isLoading: boolean;
5
+ };
@@ -0,0 +1,13 @@
1
+ import { useValidateUserPermissionsNonSuspense } from '../../data/hooks';
2
+ import { CONTENT_COURSE_PERMISSIONS, CONTENT_LIBRARY_PERMISSIONS, VIEW_TEAM_PERMISSIONS, } from '../roles-permissions';
3
+ export const useViewTeamPermissions = () => {
4
+ const { data: permissions, isLoading } = useValidateUserPermissionsNonSuspense(VIEW_TEAM_PERMISSIONS);
5
+ const isCourseViewAllowed = permissions
6
+ ? permissions.some((p) => p.action === CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM && p.allowed)
7
+ : false;
8
+ const isLibraryViewAllowed = permissions
9
+ ? permissions.some((p) => p.action === CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM && p.allowed)
10
+ : false;
11
+ return { isCourseViewAllowed, isLibraryViewAllowed, isLoading };
12
+ };
13
+ //# sourceMappingURL=useViewTeamPermissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useViewTeamPermissions.js","sourceRoot":"","sources":["../../../src/authz-module/hooks/useViewTeamPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qCAAqC,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EACL,0BAA0B,EAAE,2BAA2B,EAAE,qBAAqB,GAC/E,MAAM,qCAAqC,CAAC;AAE7C,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,qCAAqC,CAAC,qBAAqB,CAAC,CAAC;IAEtG,MAAM,mBAAmB,GAAG,WAAW;QACrC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,0BAA0B,CAAC,gBAAgB,IAAI,CAAC,CAAC,OAAO,CAAC;QAChG,CAAC,CAAC,KAAK,CAAC;IAEV,MAAM,oBAAoB,GAAG,WAAW;QACtC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,2BAA2B,CAAC,iBAAiB,IAAI,CAAC,CAAC,OAAO,CAAC;QAClG,CAAC,CAAC,KAAK,CAAC;IAEV,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,SAAS,EAAE,CAAC;AAClE,CAAC,CAAC","sourcesContent":["import { useValidateUserPermissionsNonSuspense } from '@src/data/hooks';\nimport {\n CONTENT_COURSE_PERMISSIONS, CONTENT_LIBRARY_PERMISSIONS, VIEW_TEAM_PERMISSIONS,\n} from '@src/authz-module/roles-permissions';\n\nexport const useViewTeamPermissions = () => {\n const { data: permissions, isLoading } = useValidateUserPermissionsNonSuspense(VIEW_TEAM_PERMISSIONS);\n\n const isCourseViewAllowed = permissions\n ? permissions.some((p) => p.action === CONTENT_COURSE_PERMISSIONS.VIEW_COURSE_TEAM && p.allowed)\n : false;\n\n const isLibraryViewAllowed = permissions\n ? permissions.some((p) => p.action === CONTENT_LIBRARY_PERMISSIONS.VIEW_LIBRARY_TEAM && p.allowed)\n : false;\n\n return { isCourseViewAllowed, isLibraryViewAllowed, isLoading };\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import './index.scss';
2
+ declare const AuthZModule: () => import("react").JSX.Element;
3
+ export default AuthZModule;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Suspense } from 'react';
3
+ import { Routes, Route } from 'react-router-dom';
4
+ import { ErrorBoundary } from 'react-error-boundary';
5
+ import { QueryErrorResetBoundary } from '@tanstack/react-query';
6
+ import LoadingPage from '../components/LoadingPage';
7
+ import ErrorFallback from './components/ErrorPage';
8
+ import { CustomErrors } from '../constants';
9
+ import AuthzHome from './authz-home';
10
+ import AuditUserPage from './audit-user';
11
+ import AssignRoleWizardPage from './role-assignation-wizard/AssignRoleWizardPage';
12
+ import { ROUTES } from './constants';
13
+ import './index.scss';
14
+ const NotFoundError = () => {
15
+ const error = new Error(CustomErrors.NOT_FOUND);
16
+ throw error;
17
+ };
18
+ const AuthZModule = () => (_jsx(QueryErrorResetBoundary, { children: ({ reset }) => (_jsx(ErrorBoundary, { fallbackRender: ErrorFallback, onReset: reset, children: _jsx(Suspense, { fallback: _jsx(LoadingPage, {}), children: _jsxs(Routes, { children: [_jsx(Route, { index: true, element: _jsx(AuthzHome, {}) }), _jsx(Route, { path: ROUTES.AUDIT_USER_PATH, element: _jsx(AuditUserPage, {}) }), _jsx(Route, { path: ROUTES.ASSIGN_ROLE_WIZARD_PATH, element: _jsx(AssignRoleWizardPage, {}) }), _jsx(Route, { path: "*", element: _jsx(NotFoundError, {}) })] }) }) })) }));
19
+ export default AuthZModule;
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/authz-module/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,WAAW,MAAM,6BAA6B,CAAC;AACtD,OAAO,aAAa,MAAM,wCAAwC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,SAAS,MAAM,cAAc,CAAC;AACrC,OAAO,aAAa,MAAM,cAAc,CAAC;AACzC,OAAO,oBAAoB,MAAM,gDAAgD,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,cAAc,CAAC;AAEtB,MAAM,aAAa,GAAG,GAAG,EAAE;IACzB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,KAAK,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,CACxB,KAAC,uBAAuB,cACrB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CACd,KAAC,aAAa,IAAC,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,YAC1D,KAAC,QAAQ,IAAC,QAAQ,EAAE,KAAC,WAAW,KAAG,YACjC,MAAC,MAAM,eACL,KAAC,KAAK,IAAC,KAAK,QAAC,OAAO,EAAE,KAAC,SAAS,KAAG,GAAI,EACvC,KAAC,KAAK,IAAC,IAAI,EAAE,MAAM,CAAC,eAAe,EAAE,OAAO,EAAE,KAAC,aAAa,KAAG,GAAI,EACnE,KAAC,KAAK,IAAC,IAAI,EAAE,MAAM,CAAC,uBAAuB,EAAE,OAAO,EAAE,KAAC,oBAAoB,KAAG,GAAI,EAClF,KAAC,KAAK,IAAC,IAAI,EAAC,GAAG,EAAC,OAAO,EAAE,KAAC,aAAa,KAAG,GAAI,IACvC,GACA,GACG,CACjB,GACuB,CAC3B,CAAC;AAEF,eAAe,WAAW,CAAC","sourcesContent":["import { Suspense } from 'react';\nimport { Routes, Route } from 'react-router-dom';\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { QueryErrorResetBoundary } from '@tanstack/react-query';\nimport LoadingPage from '@src/components/LoadingPage';\nimport ErrorFallback from '@src/authz-module/components/ErrorPage';\nimport { CustomErrors } from '@src/constants';\nimport AuthzHome from './authz-home';\nimport AuditUserPage from './audit-user';\nimport AssignRoleWizardPage from './role-assignation-wizard/AssignRoleWizardPage';\nimport { ROUTES } from './constants';\n\nimport './index.scss';\n\nconst NotFoundError = () => {\n const error = new Error(CustomErrors.NOT_FOUND);\n throw error;\n};\n\nconst AuthZModule = () => (\n <QueryErrorResetBoundary>\n {({ reset }) => (\n <ErrorBoundary fallbackRender={ErrorFallback} onReset={reset}>\n <Suspense fallback={<LoadingPage />}>\n <Routes>\n <Route index element={<AuthzHome />} />\n <Route path={ROUTES.AUDIT_USER_PATH} element={<AuditUserPage />} />\n <Route path={ROUTES.ASSIGN_ROLE_WIZARD_PATH} element={<AssignRoleWizardPage />} />\n <Route path=\"*\" element={<NotFoundError />} />\n </Routes>\n </Suspense>\n </ErrorBoundary>\n )}\n </QueryErrorResetBoundary>\n);\n\nexport default AuthZModule;\n"]}
@@ -0,0 +1,131 @@
1
+ @use "@openedx/paragon/styles/css/core/custom-media-breakpoints" as paragonCustomMediaBreakpoints;
2
+
3
+ .authz-module {
4
+ --height-action-divider: 30px;
5
+
6
+ .pgn__data-table-wrapper {
7
+ padding: 1rem;
8
+ }
9
+
10
+ .filters .dropdown-toggle::after {
11
+ display: none !important;
12
+ }
13
+ .pgn__data-table tr:has(span[data-role="Super Admin"]),
14
+ .pgn__data-table tr:has(span[data-role="Global Staff"]) {
15
+ background-color: var(--pgn-color-primary-200);
16
+ }
17
+ /*
18
+ This is a workaround to fix the height of the table when the dropdown menu is open,
19
+ to prevent the table from collapsing and hiding the dropdown menu.
20
+ The min-height value is set to 700px based on the height of the table and the dropdown menu,
21
+ but it can be adjusted if needed.
22
+ */
23
+ .pgn__data-table-layout-wrapper:has(.dropdown-menu.show) {
24
+ min-height: 700px;
25
+ }
26
+
27
+ hr {
28
+ border-right: var(--pgn-size-border-width) solid var(--pgn-color-border);
29
+ height: var(--height-action-divider);
30
+ width: 0;
31
+ }
32
+
33
+ .tab-content {
34
+ background-color: var(--pgn-color-light-200);
35
+ }
36
+
37
+ .collapsible-card {
38
+ border: none;
39
+
40
+ .collapsible-body {
41
+ padding: 0;
42
+ }
43
+ }
44
+
45
+ .collapsible-trigger {
46
+ background-color: var(--pgn-color-info-100);
47
+ border: none;
48
+ border-radius: 0 !important;
49
+ color: var(--pgn-color-primary-base);
50
+ padding: 1rem 2rem 1rem 1rem;
51
+ }
52
+
53
+ .permission-chip {
54
+ .pgn__chip__label {
55
+ font-weight: var(--pgn-typography-font-weight-base);
56
+ }
57
+
58
+ .pgn__icon {
59
+ width: var(--pgn-size-icon-xs);
60
+ height: var(--pgn-size-icon-xs);
61
+ }
62
+ }
63
+
64
+ .permission-table {
65
+ td {
66
+ line-height: 24px;
67
+ }
68
+ }
69
+
70
+ @media(--pgn-size-breakpoint-max-width-sm){
71
+ .flex-column-sm {
72
+ flex-direction: column;
73
+ }
74
+ hr {
75
+ border-top: var(--pgn-size-border-width) solid var(--pgn-color-border);
76
+ border-right: none;
77
+ width: 100%;
78
+ }
79
+ }
80
+ }
81
+
82
+ .highlighted-users-input {
83
+ &__layer {
84
+ font-family: inherit;
85
+ font-size: 1rem;
86
+ line-height: 1.5;
87
+ padding: 0.375rem 0.75rem;
88
+ white-space: pre-wrap;
89
+ word-break: break-word;
90
+ overflow-wrap: break-word;
91
+ width: 100%;
92
+
93
+ &.form-control {
94
+ font-family: inherit;
95
+ font-size: 1rem;
96
+ line-height: 1.5;
97
+ padding: 0.375rem 0.75rem;
98
+ }
99
+ }
100
+
101
+ &__overlay {
102
+ position: absolute;
103
+ inset: 0;
104
+ background: #fff;
105
+ border: 1px solid transparent;
106
+ border-radius: 0.25rem;
107
+ overflow: hidden;
108
+ pointer-events: none;
109
+ z-index: 0;
110
+ }
111
+
112
+ &__textarea {
113
+ position: relative;
114
+ z-index: 1;
115
+ min-height: 100px;
116
+ resize: vertical;
117
+
118
+ &--highlighted.form-control {
119
+ color: transparent;
120
+ background: transparent;
121
+ }
122
+ }
123
+ }
124
+
125
+ .scope-list {
126
+ max-height: 500px;
127
+ }
128
+
129
+ .scope-search-input {
130
+ width: 18.75rem; // 300px
131
+ }
@@ -0,0 +1,48 @@
1
+ declare const messages: {
2
+ 'authz.management.home.nav.link': {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ 'authz.management.assign.role.title': {
8
+ id: string;
9
+ defaultMessage: string;
10
+ description: string;
11
+ };
12
+ 'authz.team.toast.default.error.message': {
13
+ id: string;
14
+ defaultMessage: string;
15
+ description: string;
16
+ };
17
+ 'authz.team.remove.user.toast.success.description': {
18
+ id: string;
19
+ defaultMessage: string;
20
+ description: string;
21
+ };
22
+ 'authz.team.toast.500.error.message': {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
27
+ 'authz.team.toast.502.error.message': {
28
+ id: string;
29
+ defaultMessage: string;
30
+ description: string;
31
+ };
32
+ 'authz.team.toast.503.error.message': {
33
+ id: string;
34
+ defaultMessage: string;
35
+ description: string;
36
+ };
37
+ 'authz.team.toast.408.error.message': {
38
+ id: string;
39
+ defaultMessage: string;
40
+ description: string;
41
+ };
42
+ 'authz.team.toast.retry.label': {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ };
48
+ export default messages;
@@ -0,0 +1,50 @@
1
+ import { defineMessages } from '@openedx/frontend-base';
2
+ const messages = defineMessages({
3
+ 'authz.management.home.nav.link': {
4
+ id: 'authz.management.home.nav.link',
5
+ defaultMessage: 'Roles and Permissions Management',
6
+ description: 'Text for the roles and permissions management home page title navigation link',
7
+ },
8
+ 'authz.management.assign.role.title': {
9
+ id: 'authz.management.assign.role.title',
10
+ defaultMessage: 'Assign Role',
11
+ description: 'Text for the assign role button',
12
+ },
13
+ 'authz.team.toast.default.error.message': {
14
+ id: 'authz.team.toast.default.error.message',
15
+ defaultMessage: '<Bold>Something went wrong on our end.</Bold> <Br></Br>Please try again later.',
16
+ description: 'Default error message',
17
+ },
18
+ 'authz.team.remove.user.toast.success.description': {
19
+ id: 'authz.team.remove.user.toast.success.description',
20
+ 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 {}}',
21
+ description: 'Team management remove user toast success',
22
+ },
23
+ 'authz.team.toast.500.error.message': {
24
+ id: 'authz.team.toast.500.error.message',
25
+ defaultMessage: '<Bold>We\'re experiencing technical difficulties.</Bold> <Br></Br>Please try again later.',
26
+ description: 'Internal server error message',
27
+ },
28
+ 'authz.team.toast.502.error.message': {
29
+ id: 'authz.team.toast.502.error.message',
30
+ defaultMessage: '<Bold>We\'re having trouble connecting to our services.</Bold> <Br></Br>Please try again later.',
31
+ description: 'Bad gateway error message',
32
+ },
33
+ 'authz.team.toast.503.error.message': {
34
+ id: 'authz.team.toast.503.error.message',
35
+ defaultMessage: '<Bold>The service is temporarily unavailable.</Bold> <Br></Br>Please try again in a few moments.',
36
+ description: 'Service temporarily unavailable message',
37
+ },
38
+ 'authz.team.toast.408.error.message': {
39
+ id: 'authz.team.toast.408.error.message',
40
+ defaultMessage: '<Bold>The request took too long.</Bold> <Br></Br>Please check your connection and try again.',
41
+ description: 'Request timeout message',
42
+ },
43
+ 'authz.team.toast.retry.label': {
44
+ id: 'authz.team.toast.retry.label',
45
+ defaultMessage: 'Retry',
46
+ description: 'Label for retry button.',
47
+ },
48
+ });
49
+ export default messages;
50
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,8 @@
1
+ import { RoleMetadata } from '../../types';
2
+ interface AssignRoleWizardProps {
3
+ onClose: () => void;
4
+ initialUsers?: string;
5
+ roles?: RoleMetadata[];
6
+ }
7
+ declare const AssignRoleWizard: ({ onClose, initialUsers, roles, }: AssignRoleWizardProps) => import("react").JSX.Element;
8
+ export default AssignRoleWizard;
@@ -0,0 +1,154 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { useState, useCallback, useRef, useEffect, } from 'react';
12
+ import { useIntl } from '@openedx/frontend-base';
13
+ import { Stepper, Button, StatefulButton, Icon, } from '@openedx/paragon';
14
+ import { SpinnerSimple } from '@openedx/paragon/icons';
15
+ import { useToastManager } from '../../components/ToastManager/ToastManagerContext';
16
+ import SelectUsersAndRoleStep from './components/SelectUsersAndRoleStep';
17
+ import DefineApplicationScopeStep from './components/DefineApplicationScopeStep';
18
+ import { useValidateUsers, useAssignTeamMembersRole } from '../data/hooks';
19
+ import messages from './messages';
20
+ import { formatRoleAssignmentError } from './utils';
21
+ const STEPS = {
22
+ SELECT_USERS_AND_ROLE: 'select-users-and-role',
23
+ DEFINE_APPLICATION_SCOPE: 'define-application-scope',
24
+ };
25
+ const parseUsers = (input) => input
26
+ .split(',')
27
+ .map((u) => u.trim())
28
+ .filter(Boolean);
29
+ const getInitialState = (initialUsers) => ({
30
+ activeStep: STEPS.SELECT_USERS_AND_ROLE,
31
+ users: initialUsers,
32
+ selectedRole: null,
33
+ selectedScopes: new Set(),
34
+ invalidUsers: [],
35
+ validatedUsers: [],
36
+ });
37
+ const AssignRoleWizard = ({ onClose, initialUsers = '', roles = [], }) => {
38
+ const intl = useIntl();
39
+ const { showToast, showErrorToast } = useToastManager();
40
+ const [activeStep, setActiveStep] = useState(STEPS.SELECT_USERS_AND_ROLE);
41
+ const [users, setUsers] = useState(initialUsers);
42
+ const [selectedRole, setSelectedRole] = useState(null);
43
+ const [selectedScopes, setSelectedScopes] = useState(new Set());
44
+ const [invalidUsers, setInvalidUsers] = useState([]);
45
+ const [validatedUsers, setValidatedUsers] = useState([]);
46
+ const [assignmentErrors, setAssignmentErrors] = useState([]);
47
+ const usersInputRef = useRef(null);
48
+ const validateUsersMutation = useValidateUsers();
49
+ const assignRoleMutation = useAssignTeamMembersRole();
50
+ const handleUsersChange = useCallback((value) => {
51
+ setInvalidUsers((prev) => (prev.length > 0 ? [] : prev));
52
+ setUsers(value);
53
+ }, []);
54
+ const resetState = () => {
55
+ const initialState = getInitialState(initialUsers);
56
+ setActiveStep(initialState.activeStep);
57
+ setUsers(initialState.users);
58
+ setSelectedRole(initialState.selectedRole);
59
+ setSelectedScopes(initialState.selectedScopes);
60
+ setInvalidUsers(initialState.invalidUsers);
61
+ setValidatedUsers(initialState.validatedUsers);
62
+ setAssignmentErrors([]);
63
+ };
64
+ const handleClose = () => {
65
+ resetState();
66
+ onClose();
67
+ };
68
+ const validateUsersAndProceed = () => __awaiter(void 0, void 0, void 0, function* () {
69
+ var _a;
70
+ if (validateUsersMutation.isPending)
71
+ return;
72
+ const usersList = parseUsers(users);
73
+ if (usersList.length === 0 || !selectedRole)
74
+ return;
75
+ setInvalidUsers([]);
76
+ try {
77
+ const result = yield validateUsersMutation.mutateAsync({ data: { users: usersList } });
78
+ if (((_a = result.invalidUsers) === null || _a === void 0 ? void 0 : _a.length) > 0) {
79
+ setInvalidUsers(result.invalidUsers);
80
+ }
81
+ else {
82
+ setValidatedUsers(usersList);
83
+ setActiveStep(STEPS.DEFINE_APPLICATION_SCOPE);
84
+ }
85
+ }
86
+ catch (error) {
87
+ showErrorToast(error, validateUsersAndProceed);
88
+ }
89
+ });
90
+ const handleScopeToggle = useCallback((scopeId) => {
91
+ setSelectedScopes((prev) => {
92
+ const next = new Set(prev);
93
+ if (next.has(scopeId))
94
+ next.delete(scopeId);
95
+ else
96
+ next.add(scopeId);
97
+ return next;
98
+ });
99
+ }, []);
100
+ const handleSave = () => __awaiter(void 0, void 0, void 0, function* () {
101
+ var _a;
102
+ if (!selectedRole || selectedScopes.size === 0 || validatedUsers.length === 0)
103
+ return;
104
+ setAssignmentErrors([]);
105
+ try {
106
+ const result = yield assignRoleMutation.mutateAsync({
107
+ data: {
108
+ users: validatedUsers,
109
+ role: selectedRole,
110
+ scopes: Array.from(selectedScopes),
111
+ },
112
+ });
113
+ if (((_a = result.errors) === null || _a === void 0 ? void 0 : _a.length) > 0) {
114
+ setAssignmentErrors(result.errors.map((e) => formatRoleAssignmentError(intl, e)));
115
+ showToast({
116
+ message: intl.formatMessage(messages['wizard.save.errors.summary']),
117
+ type: 'error',
118
+ });
119
+ }
120
+ else {
121
+ showToast({
122
+ message: intl.formatMessage(messages['wizard.save.success']),
123
+ type: 'success',
124
+ });
125
+ resetState();
126
+ onClose();
127
+ }
128
+ }
129
+ catch (error) {
130
+ showErrorToast(error, handleSave);
131
+ }
132
+ });
133
+ useEffect(() => {
134
+ if (invalidUsers.length && usersInputRef.current) {
135
+ usersInputRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });
136
+ }
137
+ }, [invalidUsers]);
138
+ const parsedUsers = parseUsers(users);
139
+ const canProceed = parsedUsers.length > 0 && !!selectedRole;
140
+ const canSave = selectedScopes.size > 0;
141
+ return (_jsxs(Stepper, { activeKey: activeStep, children: [_jsx(Stepper.Header, { className: "bg-info-100" }), _jsxs("div", { className: "bg-light-200 p-5", children: [_jsx(Stepper.Step, { eventKey: STEPS.SELECT_USERS_AND_ROLE, title: intl.formatMessage(messages['wizard.step.selectUsersAndRole.title']), hasError: invalidUsers.length > 0, description: invalidUsers.length > 0 ? intl.formatMessage(messages['wizard.step.selectUsersAndRole.error']) : '', index: 0, children: _jsx(SelectUsersAndRoleStep, { users: users, setUsers: handleUsersChange, selectedRole: selectedRole, setSelectedRole: setSelectedRole, roles: roles, invalidUsers: invalidUsers, inputRef: usersInputRef }) }), _jsx(Stepper.Step, { eventKey: STEPS.DEFINE_APPLICATION_SCOPE, title: intl.formatMessage(messages['wizard.step.defineScope.title']), index: 1, children: _jsx(DefineApplicationScopeStep, { selectedRole: selectedRole, selectedScopes: selectedScopes, onScopeToggle: handleScopeToggle, assignmentErrors: assignmentErrors }) })] }), _jsxs("div", { className: "p-5", children: [_jsxs(Stepper.ActionRow, { eventKey: STEPS.SELECT_USERS_AND_ROLE, children: [_jsx(Button, { variant: "outline-primary", onClick: handleClose, children: intl.formatMessage(messages['wizard.button.cancel']) }), _jsx(Stepper.ActionRow.Spacer, {}), _jsx(StatefulButton, { labels: {
142
+ default: intl.formatMessage(messages['wizard.button.next']),
143
+ pending: intl.formatMessage(messages['wizard.button.next.pending']),
144
+ }, icons: { pending: _jsx(Icon, { src: SpinnerSimple }) }, variant: invalidUsers.length ? 'danger' : 'primary', state: validateUsersMutation.isPending ? 'pending' : 'default', onClick: validateUsersAndProceed, disabled: !canProceed || validateUsersMutation.isPending })] }), _jsxs(Stepper.ActionRow, { eventKey: STEPS.DEFINE_APPLICATION_SCOPE, children: [_jsx(Button, { variant: "outline-primary", onClick: handleClose, children: intl.formatMessage(messages['wizard.button.cancel']) }), _jsx(Button, { variant: "tertiary", onClick: () => {
145
+ setSelectedScopes(new Set());
146
+ setAssignmentErrors([]);
147
+ setActiveStep(STEPS.SELECT_USERS_AND_ROLE);
148
+ }, children: intl.formatMessage(messages['wizard.button.back']) }), _jsx(Stepper.ActionRow.Spacer, {}), _jsx(StatefulButton, { labels: {
149
+ default: intl.formatMessage(messages['wizard.button.save']),
150
+ pending: intl.formatMessage(messages['wizard.button.save.pending']),
151
+ }, icons: { pending: _jsx(Icon, { src: SpinnerSimple }) }, state: assignRoleMutation.isPending ? 'pending' : 'default', onClick: handleSave, disabled: !canSave || assignRoleMutation.isPending })] })] })] }));
152
+ };
153
+ export default AssignRoleWizard;
154
+ //# sourceMappingURL=AssignRoleWizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssignRoleWizard.js","sourceRoot":"","sources":["../../../src/authz-module/role-assignation-wizard/AssignRoleWizard.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useState, useCallback, useRef, useEffect,\n} from 'react';\nimport { useIntl } from '@openedx/frontend-base';\nimport {\n Stepper, Button, StatefulButton, Icon,\n} from '@openedx/paragon';\nimport { SpinnerSimple } from '@openedx/paragon/icons';\nimport { RoleMetadata } from '@src/types';\nimport { useToastManager } from '@src/components/ToastManager/ToastManagerContext';\nimport SelectUsersAndRoleStep from './components/SelectUsersAndRoleStep';\nimport DefineApplicationScopeStep from './components/DefineApplicationScopeStep';\nimport { useValidateUsers, useAssignTeamMembersRole } from '@src/authz-module/data/hooks';\nimport messages from './messages';\nimport { formatRoleAssignmentError } from './utils';\n\nconst STEPS = {\n SELECT_USERS_AND_ROLE: 'select-users-and-role',\n DEFINE_APPLICATION_SCOPE: 'define-application-scope',\n} as const;\n\ntype StepKey = typeof STEPS[keyof typeof STEPS];\n\ninterface AssignRoleWizardProps {\n onClose: () => void;\n initialUsers?: string;\n roles?: RoleMetadata[];\n}\n\nconst parseUsers = (input: string): string[] => input\n .split(',')\n .map((u) => u.trim())\n .filter(Boolean);\n\nconst getInitialState = (initialUsers: string) => ({\n activeStep: STEPS.SELECT_USERS_AND_ROLE as StepKey,\n users: initialUsers,\n selectedRole: null as string | null,\n selectedScopes: new Set<string>(),\n invalidUsers: [] as string[],\n validatedUsers: [] as string[],\n});\n\nconst AssignRoleWizard = ({\n onClose, initialUsers = '', roles = [],\n}: AssignRoleWizardProps) => {\n const intl = useIntl();\n const { showToast, showErrorToast } = useToastManager();\n const [activeStep, setActiveStep] = useState<StepKey>(STEPS.SELECT_USERS_AND_ROLE);\n const [users, setUsers] = useState(initialUsers);\n const [selectedRole, setSelectedRole] = useState<string | null>(null);\n const [selectedScopes, setSelectedScopes] = useState<Set<string>>(new Set());\n\n const [invalidUsers, setInvalidUsers] = useState<string[]>([]);\n const [validatedUsers, setValidatedUsers] = useState<string[]>([]);\n const [assignmentErrors, setAssignmentErrors] = useState<string[]>([]);\n\n const usersInputRef = useRef<HTMLTextAreaElement>(null);\n\n const validateUsersMutation = useValidateUsers();\n const assignRoleMutation = useAssignTeamMembersRole();\n\n const handleUsersChange = useCallback((value: string) => {\n setInvalidUsers((prev) => (prev.length > 0 ? [] : prev));\n setUsers(value);\n }, []);\n\n const resetState = () => {\n const initialState = getInitialState(initialUsers);\n setActiveStep(initialState.activeStep);\n setUsers(initialState.users);\n setSelectedRole(initialState.selectedRole);\n setSelectedScopes(initialState.selectedScopes);\n setInvalidUsers(initialState.invalidUsers);\n setValidatedUsers(initialState.validatedUsers);\n setAssignmentErrors([]);\n };\n\n const handleClose = () => {\n resetState();\n onClose();\n };\n\n const validateUsersAndProceed = async () => {\n if (validateUsersMutation.isPending) return;\n const usersList = parseUsers(users);\n if (usersList.length === 0 || !selectedRole) return;\n\n setInvalidUsers([]);\n\n try {\n const result = await validateUsersMutation.mutateAsync({ data: { users: usersList } });\n if (result.invalidUsers?.length > 0) {\n setInvalidUsers(result.invalidUsers);\n } else {\n setValidatedUsers(usersList);\n setActiveStep(STEPS.DEFINE_APPLICATION_SCOPE);\n }\n } catch (error) {\n showErrorToast(error, validateUsersAndProceed);\n }\n };\n\n const handleScopeToggle = useCallback((scopeId: string) => {\n setSelectedScopes((prev) => {\n const next = new Set(prev);\n if (next.has(scopeId))\n next.delete(scopeId);\n else\n next.add(scopeId);\n return next;\n });\n }, []);\n\n const handleSave = async () => {\n if (!selectedRole || selectedScopes.size === 0 || validatedUsers.length === 0) return;\n setAssignmentErrors([]);\n\n try {\n const result = await assignRoleMutation.mutateAsync({\n data: {\n users: validatedUsers,\n role: selectedRole,\n scopes: Array.from(selectedScopes),\n },\n });\n\n if (result.errors?.length > 0) {\n setAssignmentErrors(result.errors.map((e) => formatRoleAssignmentError(intl, e)));\n showToast({\n message: intl.formatMessage(messages['wizard.save.errors.summary']),\n type: 'error',\n });\n } else {\n showToast({\n message: intl.formatMessage(messages['wizard.save.success']),\n type: 'success',\n });\n resetState();\n onClose();\n }\n } catch (error) {\n showErrorToast(error, handleSave);\n }\n };\n\n useEffect(() => {\n if (invalidUsers.length && usersInputRef.current) {\n usersInputRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n }, [invalidUsers]);\n\n const parsedUsers = parseUsers(users);\n const canProceed = parsedUsers.length > 0 && !!selectedRole;\n const canSave = selectedScopes.size > 0;\n\n return (\n <Stepper activeKey={activeStep}>\n <Stepper.Header className=\"bg-info-100\" />\n\n <div className=\"bg-light-200 p-5\">\n <Stepper.Step\n eventKey={STEPS.SELECT_USERS_AND_ROLE}\n title={intl.formatMessage(messages['wizard.step.selectUsersAndRole.title'])}\n hasError={invalidUsers.length > 0}\n description={invalidUsers.length > 0 ? intl.formatMessage(messages['wizard.step.selectUsersAndRole.error']) : ''}\n index={0}\n >\n <SelectUsersAndRoleStep\n users={users}\n setUsers={handleUsersChange}\n selectedRole={selectedRole}\n setSelectedRole={setSelectedRole}\n roles={roles}\n invalidUsers={invalidUsers}\n inputRef={usersInputRef}\n />\n </Stepper.Step>\n\n <Stepper.Step\n eventKey={STEPS.DEFINE_APPLICATION_SCOPE}\n title={intl.formatMessage(messages['wizard.step.defineScope.title'])}\n index={1}\n >\n <DefineApplicationScopeStep\n selectedRole={selectedRole}\n selectedScopes={selectedScopes}\n onScopeToggle={handleScopeToggle}\n assignmentErrors={assignmentErrors}\n />\n </Stepper.Step>\n </div>\n\n <div className=\"p-5\">\n <Stepper.ActionRow eventKey={STEPS.SELECT_USERS_AND_ROLE}>\n <Button variant=\"outline-primary\" onClick={handleClose}>\n {intl.formatMessage(messages['wizard.button.cancel'])}\n </Button>\n <Stepper.ActionRow.Spacer />\n <StatefulButton\n labels={{\n default: intl.formatMessage(messages['wizard.button.next']),\n pending: intl.formatMessage(messages['wizard.button.next.pending']),\n }}\n icons={{ pending: <Icon src={SpinnerSimple} /> }}\n variant={invalidUsers.length ? 'danger' : 'primary'}\n state={validateUsersMutation.isPending ? 'pending' : 'default'}\n onClick={validateUsersAndProceed}\n disabled={!canProceed || validateUsersMutation.isPending}\n />\n </Stepper.ActionRow>\n\n <Stepper.ActionRow eventKey={STEPS.DEFINE_APPLICATION_SCOPE}>\n <Button variant=\"outline-primary\" onClick={handleClose}>\n {intl.formatMessage(messages['wizard.button.cancel'])}\n </Button>\n <Button\n variant=\"tertiary\"\n onClick={() => {\n setSelectedScopes(new Set());\n setAssignmentErrors([]);\n setActiveStep(STEPS.SELECT_USERS_AND_ROLE);\n }}\n >\n {intl.formatMessage(messages['wizard.button.back'])}\n </Button>\n <Stepper.ActionRow.Spacer />\n <StatefulButton\n labels={{\n default: intl.formatMessage(messages['wizard.button.save']),\n pending: intl.formatMessage(messages['wizard.button.save.pending']),\n }}\n icons={{ pending: <Icon src={SpinnerSimple} /> }}\n state={assignRoleMutation.isPending ? 'pending' : 'default'}\n onClick={handleSave}\n disabled={!canSave || assignRoleMutation.isPending}\n />\n </Stepper.ActionRow>\n </div>\n </Stepper>\n );\n};\n\nexport default AssignRoleWizard;\n"]}
@@ -0,0 +1,2 @@
1
+ declare const AssignRoleWizardPage: () => import("react").JSX.Element;
2
+ export default AssignRoleWizardPage;
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useNavigate, useSearchParams } from 'react-router-dom';
3
+ import { useIntl } from '@openedx/frontend-base';
4
+ import { useValidateUserPermissionsNonSuspense } from '../../data/hooks';
5
+ import AssignRoleWizard from './AssignRoleWizard';
6
+ import AuthZLayout from '../components/AuthZLayout';
7
+ import { ROUTES } from '../constants';
8
+ import messages from './messages';
9
+ import { CONTENT_COURSE_PERMISSIONS, CONTENT_LIBRARY_PERMISSIONS, courseRolesMetadata, libraryRolesMetadata, MANAGE_TEAM_PERMISSIONS, } from '../roles-permissions';
10
+ import { useCourseAuthoringFlag } from '../hooks/useCourseAuthoringFlag';
11
+ const AssignRoleWizardPage = () => {
12
+ var _a;
13
+ const intl = useIntl();
14
+ const navigate = useNavigate();
15
+ const [searchParams] = useSearchParams();
16
+ const initialUsers = searchParams.get('users') || '';
17
+ const raw = (_a = searchParams.get('from')) !== null && _a !== void 0 ? _a : '';
18
+ const returnTo = (raw.startsWith('/') && !raw.startsWith('//')) ? raw : ROUTES.HOME_PATH;
19
+ const presetUser = initialUsers.trim();
20
+ const destination = (presetUser && !presetUser.includes(','))
21
+ ? `${ROUTES.HOME_PATH}/user/${presetUser}`
22
+ : returnTo;
23
+ const { data: managePermissions } = useValidateUserPermissionsNonSuspense(MANAGE_TEAM_PERMISSIONS);
24
+ const { isCourseAuthoringEnabled } = useCourseAuthoringFlag();
25
+ const rolesAssignable = managePermissions === null || managePermissions === void 0 ? void 0 : managePermissions.flatMap((p) => {
26
+ if (!p.allowed)
27
+ return [];
28
+ if (p.action === CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM)
29
+ return libraryRolesMetadata;
30
+ if (p.action === CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TEAM) {
31
+ // Course (authoring) roles are only assignable when the course-authoring flag is enabled.
32
+ return isCourseAuthoringEnabled ? courseRolesMetadata : [];
33
+ }
34
+ return [];
35
+ });
36
+ return (_jsx(AuthZLayout, { context: { id: '', title: '', org: '' }, navLinks: [{ label: intl.formatMessage(messages['wizard.page.breadcrumb']), to: returnTo }], activeLabel: intl.formatMessage(messages['wizard.page.title']), pageTitle: intl.formatMessage(messages['wizard.page.title']), pageSubtitle: "", actions: [], children: _jsx(AssignRoleWizard, { onClose: () => navigate(destination), initialUsers: initialUsers, roles: rolesAssignable }) }));
37
+ };
38
+ export default AssignRoleWizardPage;
39
+ //# sourceMappingURL=AssignRoleWizardPage.js.map