@openedx/frontend-app-admin-console 1.0.0-alpha.1 → 1.0.0-alpha.10

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 (112) hide show
  1. package/dist/authz-module/audit-user/index.js +5 -9
  2. package/dist/authz-module/audit-user/index.js.map +1 -1
  3. package/dist/authz-module/authz-home/index.js +21 -2
  4. package/dist/authz-module/authz-home/index.js.map +1 -1
  5. package/dist/authz-module/components/AddRoleButton.js +1 -1
  6. package/dist/authz-module/components/AddRoleButton.js.map +1 -1
  7. package/dist/authz-module/components/AuthZLayout.d.ts +7 -6
  8. package/dist/authz-module/components/AuthZLayout.js +9 -3
  9. package/dist/authz-module/components/AuthZLayout.js.map +1 -1
  10. package/dist/authz-module/components/AuthZTitle.d.ts +3 -2
  11. package/dist/authz-module/components/AuthZTitle.js +9 -7
  12. package/dist/authz-module/components/AuthZTitle.js.map +1 -1
  13. package/dist/authz-module/components/ExpandableButton.d.ts +17 -0
  14. package/dist/authz-module/components/ExpandableButton.js +16 -0
  15. package/dist/authz-module/components/ExpandableButton.js.map +1 -0
  16. package/dist/authz-module/components/PermissionTable.js +5 -1
  17. package/dist/authz-module/components/PermissionTable.js.map +1 -1
  18. package/dist/authz-module/components/TableCells.d.ts +5 -8
  19. package/dist/authz-module/components/TableCells.js +26 -59
  20. package/dist/authz-module/components/TableCells.js.map +1 -1
  21. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.d.ts +1 -1
  22. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.js +4 -3
  23. package/dist/authz-module/components/TableControlBar/MultipleChoiceFilter.js.map +1 -1
  24. package/dist/authz-module/components/TableControlBar/OrgFilter.js +2 -2
  25. package/dist/authz-module/components/TableControlBar/OrgFilter.js.map +1 -1
  26. package/dist/authz-module/components/TableControlBar/SearchFilter.d.ts +2 -1
  27. package/dist/authz-module/components/TableControlBar/SearchFilter.js +2 -1
  28. package/dist/authz-module/components/TableControlBar/SearchFilter.js.map +1 -1
  29. package/dist/authz-module/components/TableControlBar/TableControlBar.d.ts +4 -1
  30. package/dist/authz-module/components/TableControlBar/TableControlBar.js +24 -24
  31. package/dist/authz-module/components/TableControlBar/TableControlBar.js.map +1 -1
  32. package/dist/authz-module/components/TableControlBar/types.d.ts +1 -0
  33. package/dist/authz-module/components/TableControlBar/types.js.map +1 -1
  34. package/dist/authz-module/components/TableFooter/TableFooter.d.ts +14 -1
  35. package/dist/authz-module/components/TableFooter/TableFooter.js +3 -2
  36. package/dist/authz-module/components/TableFooter/TableFooter.js.map +1 -1
  37. package/dist/authz-module/components/constants.d.ts +1 -0
  38. package/dist/authz-module/components/constants.js +2 -1
  39. package/dist/authz-module/components/constants.js.map +1 -1
  40. package/dist/authz-module/components/messages.d.ts +0 -5
  41. package/dist/authz-module/components/messages.js +2 -7
  42. package/dist/authz-module/components/messages.js.map +1 -1
  43. package/dist/authz-module/constants.d.ts +18 -8
  44. package/dist/authz-module/constants.js +30 -11
  45. package/dist/authz-module/constants.js.map +1 -1
  46. package/dist/authz-module/data/api.d.ts +12 -4
  47. package/dist/authz-module/data/api.js +11 -2
  48. package/dist/authz-module/data/api.js.map +1 -1
  49. package/dist/authz-module/data/hooks.d.ts +8 -8
  50. package/dist/authz-module/data/hooks.js +15 -20
  51. package/dist/authz-module/data/hooks.js.map +1 -1
  52. package/dist/authz-module/hooks/useExclusiveRowExpansion.d.ts +7 -0
  53. package/dist/authz-module/hooks/useExclusiveRowExpansion.js +24 -0
  54. package/dist/authz-module/hooks/useExclusiveRowExpansion.js.map +1 -0
  55. package/dist/authz-module/index.scss +150 -13
  56. package/dist/authz-module/messages.d.ts +23 -0
  57. package/dist/authz-module/messages.js +18 -0
  58. package/dist/authz-module/messages.js.map +1 -1
  59. package/dist/authz-module/role-assignation-wizard/AssignRoleWizard.js +1 -1
  60. package/dist/authz-module/role-assignation-wizard/AssignRoleWizard.js.map +1 -1
  61. package/dist/authz-module/role-assignation-wizard/AssignRoleWizardPage.js +4 -4
  62. package/dist/authz-module/role-assignation-wizard/AssignRoleWizardPage.js.map +1 -1
  63. package/dist/authz-module/role-assignation-wizard/components/ScopeFilterBar.js +1 -1
  64. package/dist/authz-module/role-assignation-wizard/components/ScopeFilterBar.js.map +1 -1
  65. package/dist/authz-module/role-assignation-wizard/hooks/useScopeListData.js.map +1 -1
  66. package/dist/authz-module/roles-permissions/RolesPermissions.js +3 -3
  67. package/dist/authz-module/roles-permissions/RolesPermissions.js.map +1 -1
  68. package/dist/authz-module/team-members/TeamMembersTable.js +102 -58
  69. package/dist/authz-module/team-members/TeamMembersTable.js.map +1 -1
  70. package/dist/authz-module/team-members/components/AssignedRolesCell.d.ts +20 -0
  71. package/dist/authz-module/team-members/components/AssignedRolesCell.js +54 -0
  72. package/dist/authz-module/team-members/components/AssignedRolesCell.js.map +1 -0
  73. package/dist/authz-module/team-members/components/MoreRolesToggle.d.ts +14 -0
  74. package/dist/authz-module/team-members/components/MoreRolesToggle.js +25 -0
  75. package/dist/authz-module/team-members/components/MoreRolesToggle.js.map +1 -0
  76. package/dist/authz-module/team-members/components/TeamMemberCells.d.ts +17 -0
  77. package/dist/authz-module/team-members/components/TeamMemberCells.js +21 -0
  78. package/dist/authz-module/team-members/components/TeamMemberCells.js.map +1 -0
  79. package/dist/authz-module/team-members/components/TeamMemberViewActionCell.d.ts +18 -0
  80. package/dist/authz-module/team-members/components/TeamMemberViewActionCell.js +42 -0
  81. package/dist/authz-module/team-members/components/TeamMemberViewActionCell.js.map +1 -0
  82. package/dist/authz-module/team-members/components/UserAssignmentsSubTable.d.ts +16 -0
  83. package/dist/authz-module/team-members/components/UserAssignmentsSubTable.js +74 -0
  84. package/dist/authz-module/team-members/components/UserAssignmentsSubTable.js.map +1 -0
  85. package/dist/authz-module/team-members/index.d.ts +1 -0
  86. package/dist/authz-module/team-members/index.js +2 -0
  87. package/dist/authz-module/team-members/index.js.map +1 -0
  88. package/dist/authz-module/team-members/messages.d.ts +56 -1
  89. package/dist/authz-module/team-members/messages.js +59 -4
  90. package/dist/authz-module/team-members/messages.js.map +1 -1
  91. package/dist/authz-module/utils.d.ts +6 -0
  92. package/dist/authz-module/utils.js +12 -10
  93. package/dist/authz-module/utils.js.map +1 -1
  94. package/dist/components/LoadingPage.d.ts +3 -0
  95. package/dist/components/LoadingPage.js +9 -1
  96. package/dist/components/LoadingPage.js.map +1 -1
  97. package/dist/components/messages.d.ts +8 -0
  98. package/dist/components/messages.js +10 -0
  99. package/dist/components/messages.js.map +1 -0
  100. package/dist/index.d.ts +0 -1
  101. package/dist/index.js +0 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/routes.d.ts +3 -1
  104. package/dist/routes.js +17 -4
  105. package/dist/routes.js.map +1 -1
  106. package/dist/style.scss +19 -2
  107. package/dist/types.d.ts +29 -20
  108. package/dist/types.js.map +1 -1
  109. package/package.json +6 -3
  110. package/dist/authz-module/components/ViewMoreLink.d.ts +0 -8
  111. package/dist/authz-module/components/ViewMoreLink.js +0 -8
  112. package/dist/authz-module/components/ViewMoreLink.js.map +0 -1
@@ -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,8 +3,20 @@
3
3
  .authz-module {
4
4
  --height-action-divider: 30px;
5
5
 
6
- .pgn__data-table-wrapper {
7
- padding: 1rem;
6
+ // Paragon scrolls the layout wrapper ≤1400px, which clips the table's box-shadow;
7
+ // the inner .pgn__data-table-container already handles horizontal scroll.
8
+ .pgn__data-table-layout-wrapper {
9
+ overflow-x: visible;
10
+
11
+ // A flex item won't shrink below its content by default, so without this the main
12
+ // column grows to the table's width and the inner container never gets to scroll.
13
+ .pgn__data-table-layout-main {
14
+ min-width: 0;
15
+ }
16
+ }
17
+
18
+ .title-border-bottom {
19
+ border-bottom: var(--pgn-size-nav-tabs-border-width) solid var(--pgn-color-nav-tabs-base-border-base);
8
20
  }
9
21
 
10
22
  .filters .dropdown-toggle::after {
@@ -24,16 +36,11 @@
24
36
  min-height: 700px;
25
37
  }
26
38
 
27
- hr {
39
+ .authz-action-divider {
28
40
  border-right: var(--pgn-size-border-width) solid var(--pgn-color-border);
29
- height: var(--height-action-divider);
30
41
  width: 0;
31
42
  }
32
43
 
33
- .tab-content {
34
- background-color: var(--pgn-color-light-200);
35
- }
36
-
37
44
  .collapsible-card {
38
45
  border: none;
39
46
 
@@ -62,21 +69,155 @@
62
69
  }
63
70
 
64
71
  .permission-table {
72
+ border-collapse: separate;
73
+ border-spacing: 0;
74
+
65
75
  td {
66
76
  line-height: 24px;
67
77
  }
78
+
79
+ thead th::after {
80
+ content: '';
81
+ position: absolute;
82
+ top: 100%;
83
+ left: 0;
84
+ right: 0;
85
+ height: 6px;
86
+ background: linear-gradient(rgba(0, 0, 0, 0.15), transparent);
87
+ pointer-events: none;
88
+ }
89
+ }
90
+
91
+ // Paragon's `.overflow-auto` lives in the `paragon` cascade layer, where its `!important`
92
+ // outranks anything this layer can say, so the card carries its own class instead. The
93
+ // matrix is 432px at min-content: only the narrowest screens need the card to scroll, and
94
+ // the cap is what gives the sticky header something to stick to while it is the scroller.
95
+ @media (--pgn-size-breakpoint-max-width-xs) {
96
+ .permission-table-scroll {
97
+ overflow: auto;
98
+ max-height: 80vh;
99
+ }
100
+ }
101
+
102
+ // Where `.text-truncate` cuts; sized to the design's character budget.
103
+ .authz-cell-username { max-width: 15rem; } // ~24 characters
104
+ .authz-cell-email { max-width: 17rem; } // ~28 characters
105
+
106
+ .team-members-table {
107
+ // Every row is two lines tall: the assigned-roles cell stacks scope over org.
108
+ td {
109
+ padding-top: var(--pgn-spacing-spacer-3);
110
+ padding-bottom: var(--pgn-spacing-spacer-3);
111
+ }
112
+
113
+ /*
114
+ Auto-layout starves "Assigned roles" in favour of the short Username/Email values,
115
+ so widths are pinned. Below `md` these percentages would crush the toggle and action
116
+ columns, so the table falls back to content sizing and scrolls inside Paragon's
117
+ `.pgn__data-table-container`.
118
+
119
+ A fixed table takes its widths from the header cells, but Paragon puts a column's
120
+ `headerClassName` on a span inside the `th`, so `:has()` lifts it to the `th`.
121
+ */
122
+ @media (--pgn-size-breakpoint-min-width-md) {
123
+ .pgn__data-table {
124
+ table-layout: fixed;
125
+ }
126
+
127
+ th:has(> .authz-col-username) { width: 16%; }
128
+ th:has(> .authz-col-email) { width: 18%; }
129
+ th:has(> .authz-col-assigned-roles) { width: 46%; }
130
+ th:has(> .authz-col-more-roles) { width: 13%; }
131
+ th:has(> .authz-col-actions) { width: 7%; }
132
+
133
+ td {
134
+ overflow: hidden;
135
+ }
136
+
137
+ // The nested table sizes its own columns; it must not inherit the fixed layout above.
138
+ .team-members-table__subtable .pgn__data-table {
139
+ table-layout: auto;
140
+ }
141
+ }
142
+
143
+ // One line per row, so it keeps tighter padding.
144
+ .team-members-table__subtable {
145
+ th,
146
+ td {
147
+ padding-top: var(--pgn-spacing-spacer-2);
148
+ padding-bottom: var(--pgn-spacing-spacer-2);
149
+ }
150
+ }
151
+ }
152
+
153
+ .team-members-table__subtable {
154
+ // The module turns `hr` horizontal below `sm`; this footer divider stays vertical.
155
+ hr {
156
+ border-right: var(--pgn-size-border-width) solid var(--pgn-color-border);
157
+ border-top: none;
158
+ height: 1rem;
159
+ width: 0;
160
+ }
161
+
162
+ // The Card already pads; the module's blanket 1rem would double it up.
163
+ .pgn__data-table-wrapper {
164
+ padding: 0;
165
+ }
166
+
167
+ // Matches PermissionTable's `bg-info-100 text-primary` band. Paragon renders its own
168
+ // `thead`, so the tokens are used rather than the utility classes.
169
+ thead th {
170
+ background-color: var(--pgn-color-info-100);
171
+ color: var(--pgn-color-primary-base);
172
+ }
173
+
174
+ /*
175
+ Paragon stripes with `.pgn__data-table.is-striped tr:nth-child(2n)` — a descendant
176
+ selector, so the striped outer table reaches in and `isStriped={false}` on the inner
177
+ one cannot override it. The `:not()` keeps a nested table that wants stripes.
178
+ */
179
+ .pgn__data-table:not(.is-striped) tr {
180
+ background-color: transparent;
181
+
182
+ // With the stripes gone, rows need an explicit divider to stay readable.
183
+ &:not(:last-child) td {
184
+ border-bottom: var(--pgn-size-border-width) solid var(--pgn-color-border);
185
+ }
186
+ }
187
+ }
188
+
189
+ // Floor the badge to the widest label, so "in" and the scope align down the column.
190
+ .authz-assigned-roles .authz-role-badge { min-width: 11rem; }
191
+
192
+ .authz-scope-cell {
193
+ min-width: 0; // Lets the flex child shrink far enough for `.text-truncate` to cut.
194
+ max-width: 25rem; // org subline, ~40 characters
195
+
196
+ &__name {
197
+ max-width: 22rem; // ~35 characters
198
+ }
199
+
200
+ &__org {
201
+ line-height: 1.2;
202
+ }
68
203
  }
69
204
 
70
205
  @media(--pgn-size-breakpoint-max-width-sm){
71
206
  .flex-column-sm {
72
207
  flex-direction: column;
73
208
  }
74
- hr {
209
+ .authz-action-divider {
75
210
  border-top: var(--pgn-size-border-width) solid var(--pgn-color-border);
76
211
  border-right: none;
77
212
  width: 100%;
78
213
  }
79
214
  }
215
+
216
+ @media (--pgn-size-breakpoint-min-width-md) {
217
+ .authz-action-divider {
218
+ height: var(--height-action-divider);
219
+ }
220
+ }
80
221
  }
81
222
 
82
223
  .highlighted-users-input {
@@ -125,7 +266,3 @@
125
266
  .scope-list {
126
267
  max-height: 500px;
127
268
  }
128
-
129
- .scope-search-input {
130
- width: 18.75rem; // 300px
131
- }
@@ -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"]}
@@ -138,7 +138,7 @@ const AssignRoleWizard = ({ onClose, initialUsers = '', roles = [], }) => {
138
138
  const parsedUsers = parseUsers(users);
139
139
  const canProceed = parsedUsers.length > 0 && !!selectedRole;
140
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: {
141
+ return (_jsxs(Stepper, { activeKey: activeStep, children: [_jsx(Stepper.Header, { className: "bg-info-100" }), _jsxs("div", { className: "page-band py-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: "page-band py-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
142
  default: intl.formatMessage(messages['wizard.button.next']),
143
143
  pending: intl.formatMessage(messages['wizard.button.next.pending']),
144
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: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"AssignRoleWizard.js","sourceRoot":"","sources":["../../../src/authz-module/role-assignation-wizard/AssignRoleWizard.tsx"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EACL,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,GACzC,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,OAAO,sBAAsB,MAAM,qCAAqC,CAAC;AACzE,OAAO,0BAA0B,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAEpD,MAAM,KAAK,GAAG;IACZ,qBAAqB,EAAE,uBAAuB;IAC9C,wBAAwB,EAAE,0BAA0B;CAC5C,CAAC;AAUX,MAAM,UAAU,GAAG,CAAC,KAAa,EAAY,EAAE,CAAC,KAAK;KAClD,KAAK,CAAC,GAAG,CAAC;KACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;KACpB,MAAM,CAAC,OAAO,CAAC,CAAC;AAEnB,MAAM,eAAe,GAAG,CAAC,YAAoB,EAAE,EAAE,CAAC,CAAC;IACjD,UAAU,EAAE,KAAK,CAAC,qBAAgC;IAClD,KAAK,EAAE,YAAY;IACnB,YAAY,EAAE,IAAqB;IACnC,cAAc,EAAE,IAAI,GAAG,EAAU;IACjC,YAAY,EAAE,EAAc;IAC5B,cAAc,EAAE,EAAc;CAC/B,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,CAAC,EACxB,OAAO,EAAE,YAAY,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,GAChB,EAAE,EAAE;IAC1B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,eAAe,EAAE,CAAC;IACxD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACnF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAc,IAAI,GAAG,EAAE,CAAC,CAAC;IAE7E,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACnE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IAEvE,MAAM,aAAa,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IAExD,MAAM,qBAAqB,GAAG,gBAAgB,EAAE,CAAC;IACjD,MAAM,kBAAkB,GAAG,wBAAwB,EAAE,CAAC;IAEtD,MAAM,iBAAiB,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,EAAE;QACtD,eAAe,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzD,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;QACnD,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACvC,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7B,eAAe,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3C,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QAC/C,eAAe,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3C,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QAC/C,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,UAAU,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,MAAM,uBAAuB,GAAG,GAAS,EAAE;;QACzC,IAAI,qBAAqB,CAAC,SAAS;YAAE,OAAO;QAC5C,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,YAAY;YAAE,OAAO;QAEpD,eAAe,CAAC,EAAE,CAAC,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;YACvF,IAAI,CAAA,MAAA,MAAM,CAAC,YAAY,0CAAE,MAAM,IAAG,CAAC,EAAE,CAAC;gBACpC,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,iBAAiB,CAAC,SAAS,CAAC,CAAC;gBAC7B,aAAa,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,cAAc,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAA,CAAC;IAEF,MAAM,iBAAiB,GAAG,WAAW,CAAC,CAAC,OAAe,EAAE,EAAE;QACxD,iBAAiB,CAAC,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;;gBAErB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,UAAU,GAAG,GAAS,EAAE;;QAC5B,IAAI,CAAC,YAAY,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACtF,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAExB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC;gBAClD,IAAI,EAAE;oBACJ,KAAK,EAAE,cAAc;oBACrB,IAAI,EAAE,YAAY;oBAClB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC;iBACnC;aACF,CAAC,CAAC;YAEH,IAAI,CAAA,MAAA,MAAM,CAAC,MAAM,0CAAE,MAAM,IAAG,CAAC,EAAE,CAAC;gBAC9B,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClF,SAAS,CAAC;oBACR,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;oBACnE,IAAI,EAAE,OAAO;iBACd,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC;oBACR,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC;oBAC5D,IAAI,EAAE,SAAS;iBAChB,CAAC,CAAC;gBACH,UAAU,EAAE,CAAC;gBACb,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAA,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,CAAC,MAAM,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YACjD,aAAa,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC;IAC5D,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,GAAG,CAAC,CAAC;IAExC,OAAO,CACL,MAAC,OAAO,IAAC,SAAS,EAAE,UAAU,aAC5B,KAAC,OAAO,CAAC,MAAM,IAAC,SAAS,EAAC,aAAa,GAAG,EAE1C,eAAK,SAAS,EAAC,kBAAkB,aAC/B,KAAC,OAAO,CAAC,IAAI,IACX,QAAQ,EAAE,KAAK,CAAC,qBAAqB,EACrC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,sCAAsC,CAAC,CAAC,EAC3E,QAAQ,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,EACjC,WAAW,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,sCAAsC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAChH,KAAK,EAAE,CAAC,YAER,KAAC,sBAAsB,IACrB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,aAAa,GACvB,GACW,EAEf,KAAC,OAAO,CAAC,IAAI,IACX,QAAQ,EAAE,KAAK,CAAC,wBAAwB,EACxC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,EACpE,KAAK,EAAE,CAAC,YAER,KAAC,0BAA0B,IACzB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,iBAAiB,EAChC,gBAAgB,EAAE,gBAAgB,GAClC,GACW,IACX,EAEN,eAAK,SAAS,EAAC,KAAK,aAClB,MAAC,OAAO,CAAC,SAAS,IAAC,QAAQ,EAAE,KAAK,CAAC,qBAAqB,aACtD,KAAC,MAAM,IAAC,OAAO,EAAC,iBAAiB,EAAC,OAAO,EAAE,WAAW,YACnD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,GAC9C,EACT,KAAC,OAAO,CAAC,SAAS,CAAC,MAAM,KAAG,EAC5B,KAAC,cAAc,IACb,MAAM,EAAE;oCACN,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;oCAC3D,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;iCACpE,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,KAAC,IAAI,IAAC,GAAG,EAAE,aAAa,GAAI,EAAE,EAChD,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EACnD,KAAK,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC9D,OAAO,EAAE,uBAAuB,EAChC,QAAQ,EAAE,CAAC,UAAU,IAAI,qBAAqB,CAAC,SAAS,GACxD,IACgB,EAEpB,MAAC,OAAO,CAAC,SAAS,IAAC,QAAQ,EAAE,KAAK,CAAC,wBAAwB,aACzD,KAAC,MAAM,IAAC,OAAO,EAAC,iBAAiB,EAAC,OAAO,EAAE,WAAW,YACnD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,GAC9C,EACT,KAAC,MAAM,IACL,OAAO,EAAC,UAAU,EAClB,OAAO,EAAE,GAAG,EAAE;oCACZ,iBAAiB,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;oCAC7B,mBAAmB,CAAC,EAAE,CAAC,CAAC;oCACxB,aAAa,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;gCAC7C,CAAC,YAEA,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,GAC5C,EACT,KAAC,OAAO,CAAC,SAAS,CAAC,MAAM,KAAG,EAC5B,KAAC,cAAc,IACb,MAAM,EAAE;oCACN,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;oCAC3D,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;iCACpE,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,KAAC,IAAI,IAAC,GAAG,EAAE,aAAa,GAAI,EAAE,EAChD,KAAK,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC3D,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,OAAO,IAAI,kBAAkB,CAAC,SAAS,GAClD,IACgB,IAChB,IACE,CACX,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC","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"]}
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=\"page-band py-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=\"page-band py-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"]}
@@ -4,7 +4,7 @@ import { useIntl } from '@openedx/frontend-base';
4
4
  import { useValidateUserPermissionsNonSuspense } from '../../data/hooks';
5
5
  import AssignRoleWizard from './AssignRoleWizard';
6
6
  import AuthZLayout from '../components/AuthZLayout';
7
- import { ROUTES } from '../constants';
7
+ import { AUTHZ_HOME_PATH, buildAuditUserPath } from '../constants';
8
8
  import messages from './messages';
9
9
  import { CONTENT_COURSE_PERMISSIONS, CONTENT_LIBRARY_PERMISSIONS, courseRolesMetadata, libraryRolesMetadata, MANAGE_TEAM_PERMISSIONS, } from '../roles-permissions';
10
10
  import { useCourseAuthoringFlag } from '../hooks/useCourseAuthoringFlag';
@@ -15,10 +15,10 @@ const AssignRoleWizardPage = () => {
15
15
  const [searchParams] = useSearchParams();
16
16
  const initialUsers = searchParams.get('users') || '';
17
17
  const raw = (_a = searchParams.get('from')) !== null && _a !== void 0 ? _a : '';
18
- const returnTo = (raw.startsWith('/') && !raw.startsWith('//')) ? raw : ROUTES.HOME_PATH;
18
+ const returnTo = (raw.startsWith('/') && !raw.startsWith('//')) ? raw : AUTHZ_HOME_PATH;
19
19
  const presetUser = initialUsers.trim();
20
20
  const destination = (presetUser && !presetUser.includes(','))
21
- ? `${ROUTES.HOME_PATH}/user/${presetUser}`
21
+ ? buildAuditUserPath(presetUser)
22
22
  : returnTo;
23
23
  const { data: managePermissions } = useValidateUserPermissionsNonSuspense(MANAGE_TEAM_PERMISSIONS);
24
24
  const { isCourseAuthoringEnabled } = useCourseAuthoringFlag();
@@ -33,7 +33,7 @@ const AssignRoleWizardPage = () => {
33
33
  }
34
34
  return [];
35
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 }) }));
36
+ return (_jsx(AuthZLayout, { navLinks: [{ label: intl.formatMessage(messages['wizard.page.breadcrumb']), to: returnTo }], activeLabel: intl.formatMessage(messages['wizard.page.title']), pageTitle: intl.formatMessage(messages['wizard.page.title']), actions: [], children: _jsx(AssignRoleWizard, { onClose: () => navigate(destination), initialUsers: initialUsers, roles: rolesAssignable }) }));
37
37
  };
38
38
  export default AssignRoleWizardPage;
39
39
  //# sourceMappingURL=AssignRoleWizardPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssignRoleWizardPage.js","sourceRoot":"","sources":["../../../src/authz-module/role-assignation-wizard/AssignRoleWizardPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigate, useSearchParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { useValidateUserPermissionsNonSuspense } from '@src/data/hooks';\nimport AssignRoleWizard from './AssignRoleWizard';\nimport AuthZLayout from '@src/authz-module/components/AuthZLayout';\nimport { ROUTES } from '@src/authz-module/constants';\nimport messages from './messages';\nimport {\n CONTENT_COURSE_PERMISSIONS, CONTENT_LIBRARY_PERMISSIONS, courseRolesMetadata, libraryRolesMetadata,\n MANAGE_TEAM_PERMISSIONS,\n} from '@src/authz-module/roles-permissions';\nimport { useCourseAuthoringFlag } from '@src/authz-module/hooks/useCourseAuthoringFlag';\n\nconst AssignRoleWizardPage = () => {\n const intl = useIntl();\n const navigate = useNavigate();\n const [searchParams] = useSearchParams();\n const initialUsers = searchParams.get('users') || '';\n const raw = searchParams.get('from') ?? '';\n const returnTo = (raw.startsWith('/') && !raw.startsWith('//')) ? raw : ROUTES.HOME_PATH;\n\n const presetUser = initialUsers.trim();\n const destination = (presetUser && !presetUser.includes(','))\n ? `${ROUTES.HOME_PATH}/user/${presetUser}`\n : returnTo;\n\n const { data: managePermissions } = useValidateUserPermissionsNonSuspense(MANAGE_TEAM_PERMISSIONS);\n const { isCourseAuthoringEnabled } = useCourseAuthoringFlag();\n\n const rolesAssignable = managePermissions?.flatMap((p) => {\n if (!p.allowed) return [];\n if (p.action === CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM) return libraryRolesMetadata;\n if (p.action === CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TEAM) {\n // Course (authoring) roles are only assignable when the course-authoring flag is enabled.\n return isCourseAuthoringEnabled ? courseRolesMetadata : [];\n }\n return [];\n });\n\n return (\n <AuthZLayout\n context={{ id: '', title: '', org: '' }}\n navLinks={[{ label: intl.formatMessage(messages['wizard.page.breadcrumb']), to: returnTo }]}\n activeLabel={intl.formatMessage(messages['wizard.page.title'])}\n pageTitle={intl.formatMessage(messages['wizard.page.title'])}\n pageSubtitle=\"\"\n actions={[]}\n >\n <AssignRoleWizard\n onClose={() => navigate(destination)}\n initialUsers={initialUsers}\n roles={rolesAssignable}\n />\n </AuthZLayout>\n );\n};\n\nexport default AssignRoleWizardPage;\n"]}
1
+ {"version":3,"file":"AssignRoleWizardPage.js","sourceRoot":"","sources":["../../../src/authz-module/role-assignation-wizard/AssignRoleWizardPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigate, useSearchParams } from 'react-router-dom';\nimport { useIntl } from '@openedx/frontend-base';\nimport { useValidateUserPermissionsNonSuspense } from '@src/data/hooks';\nimport AssignRoleWizard from './AssignRoleWizard';\nimport AuthZLayout from '@src/authz-module/components/AuthZLayout';\nimport { AUTHZ_HOME_PATH, buildAuditUserPath } from '@src/authz-module/constants';\nimport messages from './messages';\nimport {\n CONTENT_COURSE_PERMISSIONS, CONTENT_LIBRARY_PERMISSIONS, courseRolesMetadata, libraryRolesMetadata,\n MANAGE_TEAM_PERMISSIONS,\n} from '@src/authz-module/roles-permissions';\nimport { useCourseAuthoringFlag } from '@src/authz-module/hooks/useCourseAuthoringFlag';\n\nconst AssignRoleWizardPage = () => {\n const intl = useIntl();\n const navigate = useNavigate();\n const [searchParams] = useSearchParams();\n const initialUsers = searchParams.get('users') || '';\n const raw = searchParams.get('from') ?? '';\n const returnTo = (raw.startsWith('/') && !raw.startsWith('//')) ? raw : AUTHZ_HOME_PATH;\n\n const presetUser = initialUsers.trim();\n const destination = (presetUser && !presetUser.includes(','))\n ? buildAuditUserPath(presetUser)\n : returnTo;\n\n const { data: managePermissions } = useValidateUserPermissionsNonSuspense(MANAGE_TEAM_PERMISSIONS);\n const { isCourseAuthoringEnabled } = useCourseAuthoringFlag();\n\n const rolesAssignable = managePermissions?.flatMap((p) => {\n if (!p.allowed) return [];\n if (p.action === CONTENT_LIBRARY_PERMISSIONS.MANAGE_LIBRARY_TEAM) return libraryRolesMetadata;\n if (p.action === CONTENT_COURSE_PERMISSIONS.MANAGE_COURSE_TEAM) {\n // Course (authoring) roles are only assignable when the course-authoring flag is enabled.\n return isCourseAuthoringEnabled ? courseRolesMetadata : [];\n }\n return [];\n });\n\n return (\n <AuthZLayout\n navLinks={[{ label: intl.formatMessage(messages['wizard.page.breadcrumb']), to: returnTo }]}\n activeLabel={intl.formatMessage(messages['wizard.page.title'])}\n pageTitle={intl.formatMessage(messages['wizard.page.title'])}\n actions={[]}\n >\n <AssignRoleWizard\n onClose={() => navigate(destination)}\n initialUsers={initialUsers}\n roles={rolesAssignable}\n />\n </AuthZLayout>\n );\n};\n\nexport default AssignRoleWizardPage;\n"]}
@@ -6,7 +6,7 @@ import OrgFilter from '../../components/TableControlBar/OrgFilter';
6
6
  import messages from '../messages';
7
7
  const ScopeFilterBar = ({ search, onSearchChange, selectedOrgs, onOrgsChange, contextType, contextLabel, allScopesCount, totalCount, }) => {
8
8
  const intl = useIntl();
9
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "d-flex align-items-center justify-content-between gap-3 mb-2 flex-wrap", children: [_jsxs("div", { className: "d-flex align-items-center gap-3", children: [_jsx("div", { className: "scope-search-input", children: _jsx(Form.Group, { controlId: "scope-search", className: "mb-0", children: _jsx(Form.Control, { type: "text", value: search, onChange: (e) => onSearchChange(e.target.value), placeholder: intl.formatMessage(messages['wizard.step2.search.placeholder']), trailingElement: _jsx(Icon, { src: Search }) }) }) }), _jsx(OrgFilter, { filterButtonText: intl.formatMessage(messages['wizard.step2.filter.org.label']), filterValue: selectedOrgs, setFilter: onOrgsChange })] }), _jsx("span", { className: "text-muted small text-nowrap", children: intl.formatMessage(messages['wizard.step2.count'], { shown: allScopesCount, total: totalCount }) })] }), contextType && (_jsxs(Stack, { direction: "horizontal", gap: 2, className: "align-items-center mt-3", children: [_jsx("span", { className: "text-muted small", children: intl.formatMessage(messages['wizard.step2.filter.applied']) }), _jsx(Badge, { className: "py-1 px-2", variant: "light", children: contextLabel })] }))] }));
9
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "d-flex align-items-center justify-content-between gap-3 mb-2 flex-wrap", children: [_jsxs("div", { className: "d-flex align-items-center gap-3 flex-wrap", children: [_jsx(Form.Group, { controlId: "scope-search", className: "mb-0", children: _jsx(Form.Control, { type: "text", value: search, onChange: (e) => onSearchChange(e.target.value), placeholder: intl.formatMessage(messages['wizard.step2.search.placeholder']), trailingElement: _jsx(Icon, { src: Search }) }) }), _jsx(OrgFilter, { filterButtonText: intl.formatMessage(messages['wizard.step2.filter.org.label']), filterValue: selectedOrgs, setFilter: onOrgsChange })] }), _jsx("span", { className: "text-muted small text-nowrap", children: intl.formatMessage(messages['wizard.step2.count'], { shown: allScopesCount, total: totalCount }) })] }), contextType && (_jsxs(Stack, { direction: "horizontal", gap: 2, className: "align-items-center mt-3", children: [_jsx("span", { className: "text-muted small", children: intl.formatMessage(messages['wizard.step2.filter.applied']) }), _jsx(Badge, { className: "py-1 px-2", variant: "light", children: contextLabel })] }))] }));
10
10
  };
11
11
  export default ScopeFilterBar;
12
12
  //# sourceMappingURL=ScopeFilterBar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScopeFilterBar.js","sourceRoot":"","sources":["../../../../src/authz-module/role-assignation-wizard/components/ScopeFilterBar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,SAAS,MAAM,wDAAwD,CAAC;AAE/E,OAAO,QAAQ,MAAM,oDAAoD,CAAC;AAa1E,MAAM,cAAc,GAAG,CAAC,EACtB,MAAM,EACN,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,cAAc,EACd,UAAU,GACU,EAAE,EAAE;IACxB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,OAAO,CACL,8BACE,eAAK,SAAS,EAAC,wEAAwE,aACrF,eAAK,SAAS,EAAC,iCAAiC,aAC9C,cAAK,SAAS,EAAC,oBAAoB,YACjC,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,cAAc,EAAC,SAAS,EAAC,MAAM,YACnD,KAAC,IAAI,CAAC,OAAO,IACX,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAgC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC9E,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC,EAC5E,eAAe,EAAE,KAAC,IAAI,IAAC,GAAG,EAAE,MAAM,GAAI,GACtC,GACS,GACT,EAEN,KAAC,SAAS,IACR,gBAAgB,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,EAC/E,WAAW,EAAE,YAAY,EACzB,SAAS,EAAE,YAAY,GACvB,IACE,EAEN,eAAM,SAAS,EAAC,8BAA8B,YAC3C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,GAC5F,IACH,EAEL,WAAW,IAAI,CACd,MAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,GAAG,EAAE,CAAC,EAAE,SAAS,EAAC,yBAAyB,aACvE,eAAM,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC,GAAQ,EACvG,KAAC,KAAK,IAAC,SAAS,EAAC,WAAW,EAAC,OAAO,EAAC,OAAO,YACzC,YAAY,GACP,IACF,CACT,IACA,CACJ,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import { useIntl } from '@openedx/frontend-base';\nimport {\n Form, Icon, Badge, Stack,\n} from '@openedx/paragon';\nimport { Search } from '@openedx/paragon/icons';\nimport OrgFilter from '@src/authz-module/components/TableControlBar/OrgFilter';\nimport { ChangeEvent } from 'react';\nimport messages from '@src/authz-module/role-assignation-wizard/messages';\n\ninterface ScopeFilterBarProps {\n search: string;\n onSearchChange: (value: string) => void;\n selectedOrgs: string[];\n onOrgsChange: (value: string[]) => void;\n contextType: string | undefined;\n contextLabel: string;\n allScopesCount: number;\n totalCount: number;\n}\n\nconst ScopeFilterBar = ({\n search,\n onSearchChange,\n selectedOrgs,\n onOrgsChange,\n contextType,\n contextLabel,\n allScopesCount,\n totalCount,\n}: ScopeFilterBarProps) => {\n const intl = useIntl();\n\n return (\n <>\n <div className=\"d-flex align-items-center justify-content-between gap-3 mb-2 flex-wrap\">\n <div className=\"d-flex align-items-center gap-3\">\n <div className=\"scope-search-input\">\n <Form.Group controlId=\"scope-search\" className=\"mb-0\">\n <Form.Control\n type=\"text\"\n value={search}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onSearchChange(e.target.value)}\n placeholder={intl.formatMessage(messages['wizard.step2.search.placeholder'])}\n trailingElement={<Icon src={Search} />}\n />\n </Form.Group>\n </div>\n\n <OrgFilter\n filterButtonText={intl.formatMessage(messages['wizard.step2.filter.org.label'])}\n filterValue={selectedOrgs}\n setFilter={onOrgsChange}\n />\n </div>\n\n <span className=\"text-muted small text-nowrap\">\n {intl.formatMessage(messages['wizard.step2.count'], { shown: allScopesCount, total: totalCount })}\n </span>\n </div>\n\n {contextType && (\n <Stack direction=\"horizontal\" gap={2} className=\"align-items-center mt-3\">\n <span className=\"text-muted small\">{intl.formatMessage(messages['wizard.step2.filter.applied'])}</span>\n <Badge className=\"py-1 px-2\" variant=\"light\">\n {contextLabel}\n </Badge>\n </Stack>\n )}\n </>\n );\n};\n\nexport default ScopeFilterBar;\n"]}
1
+ {"version":3,"file":"ScopeFilterBar.js","sourceRoot":"","sources":["../../../../src/authz-module/role-assignation-wizard/components/ScopeFilterBar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,SAAS,MAAM,wDAAwD,CAAC;AAE/E,OAAO,QAAQ,MAAM,oDAAoD,CAAC;AAa1E,MAAM,cAAc,GAAG,CAAC,EACtB,MAAM,EACN,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,cAAc,EACd,UAAU,GACU,EAAE,EAAE;IACxB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,OAAO,CACL,8BACE,eAAK,SAAS,EAAC,wEAAwE,aACrF,eAAK,SAAS,EAAC,2CAA2C,aACxD,KAAC,IAAI,CAAC,KAAK,IAAC,SAAS,EAAC,cAAc,EAAC,SAAS,EAAC,MAAM,YACnD,KAAC,IAAI,CAAC,OAAO,IACX,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAgC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC9E,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC,EAC5E,eAAe,EAAE,KAAC,IAAI,IAAC,GAAG,EAAE,MAAM,GAAI,GACtC,GACS,EAEb,KAAC,SAAS,IACR,gBAAgB,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,EAC/E,WAAW,EAAE,YAAY,EACzB,SAAS,EAAE,YAAY,GACvB,IACE,EAEN,eAAM,SAAS,EAAC,8BAA8B,YAC3C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,GAC5F,IACH,EAEL,WAAW,IAAI,CACd,MAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,GAAG,EAAE,CAAC,EAAE,SAAS,EAAC,yBAAyB,aACvE,eAAM,SAAS,EAAC,kBAAkB,YAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC,GAAQ,EACvG,KAAC,KAAK,IAAC,SAAS,EAAC,WAAW,EAAC,OAAO,EAAC,OAAO,YACzC,YAAY,GACP,IACF,CACT,IACA,CACJ,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import { useIntl } from '@openedx/frontend-base';\nimport {\n Form, Icon, Badge, Stack,\n} from '@openedx/paragon';\nimport { Search } from '@openedx/paragon/icons';\nimport OrgFilter from '@src/authz-module/components/TableControlBar/OrgFilter';\nimport { ChangeEvent } from 'react';\nimport messages from '@src/authz-module/role-assignation-wizard/messages';\n\ninterface ScopeFilterBarProps {\n search: string;\n onSearchChange: (value: string) => void;\n selectedOrgs: string[];\n onOrgsChange: (value: string[]) => void;\n contextType: string | undefined;\n contextLabel: string;\n allScopesCount: number;\n totalCount: number;\n}\n\nconst ScopeFilterBar = ({\n search,\n onSearchChange,\n selectedOrgs,\n onOrgsChange,\n contextType,\n contextLabel,\n allScopesCount,\n totalCount,\n}: ScopeFilterBarProps) => {\n const intl = useIntl();\n\n return (\n <>\n <div className=\"d-flex align-items-center justify-content-between gap-3 mb-2 flex-wrap\">\n <div className=\"d-flex align-items-center gap-3 flex-wrap\">\n <Form.Group controlId=\"scope-search\" className=\"mb-0\">\n <Form.Control\n type=\"text\"\n value={search}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onSearchChange(e.target.value)}\n placeholder={intl.formatMessage(messages['wizard.step2.search.placeholder'])}\n trailingElement={<Icon src={Search} />}\n />\n </Form.Group>\n\n <OrgFilter\n filterButtonText={intl.formatMessage(messages['wizard.step2.filter.org.label'])}\n filterValue={selectedOrgs}\n setFilter={onOrgsChange}\n />\n </div>\n\n <span className=\"text-muted small text-nowrap\">\n {intl.formatMessage(messages['wizard.step2.count'], { shown: allScopesCount, total: totalCount })}\n </span>\n </div>\n\n {contextType && (\n <Stack direction=\"horizontal\" gap={2} className=\"align-items-center mt-3\">\n <span className=\"text-muted small\">{intl.formatMessage(messages['wizard.step2.filter.applied'])}</span>\n <Badge className=\"py-1 px-2\" variant=\"light\">\n {contextLabel}\n </Badge>\n </Stack>\n )}\n </>\n );\n};\n\nexport default ScopeFilterBar;\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"]}
@@ -1,7 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from 'react';
3
3
  import { useIntl } from '@openedx/frontend-base';
4
- import { Alert, Button, ButtonGroup, Container, Hyperlink, } from '@openedx/paragon';
4
+ import { Alert, Button, ButtonGroup, Card, Hyperlink, } from '@openedx/paragon';
5
5
  import { coursePermissions, courseResourceTypes, courseRolesWithPermissions, } from './course/constants';
6
6
  import { libraryRolesWithPermissions, libraryPermissions, libraryResourceTypes, } from './library/constants';
7
7
  import AnchorButton from '../components/AnchorButton';
@@ -29,7 +29,7 @@ const RolesPermissions = () => {
29
29
  });
30
30
  return permissionsByResource;
31
31
  }, [intl]);
32
- return (_jsxs(Container, { className: "p-5", children: [_jsx(Container, { className: "pb-5", children: _jsxs(ButtonGroup, { size: "lg", className: "mb-2", children: [_jsx(Button, { onClick: () => setActive('courses'), variant: `${active === 'courses' ? 'primary' : 'outline-primary'}`, children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.tab']) }), _jsx(Button, { onClick: () => setActive('libraries'), variant: `${active === 'libraries' ? 'primary' : 'outline-primary'}`, children: intl.formatMessage(messages['authz.tabs.permissionsRoles.libraries.tab']) })] }) }), active === 'courses' && (_jsxs("div", { className: "position-relative", children: [_jsx(PermissionTable, { permissionsTable: coursePermissionsByResource, roles: courseRolesWithPermissions, title: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.tab.title']) }), _jsx(Alert, { variant: "info", className: "mt-5", children: _jsxs("div", { className: "row align-items-center", children: [_jsxs("div", { className: "col col-7", children: [_jsx("p", { className: "text-primary font-weight-bold h4", children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.title']) }), _jsxs("span", { children: [_jsx("span", { className: "font-weight-bold", children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.note']) }), intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.description'])] })] }), _jsx("div", { className: "col col-5", children: _jsx(Hyperlink, { className: "d-block text-right h5 font-weight-normal", destination: "https://docs.openedx.org/en/latest/educators/references/course_development/course_team_roles.html", target: "_blank", showLaunchIcon: false, isInline: true, children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.link']) }) })] }) })] })), active === 'libraries' && (_jsx(PermissionTable, { permissionsTable: libraryPermissionsByResource, roles: libraryRolesWithPermissions, title: intl.formatMessage(messages['authz.tabs.permissionsRoles.libraries.tab.title']) })), _jsx(AnchorButton, {})] }));
32
+ return (_jsxs(_Fragment, { children: [_jsxs(Card, { className: "bg-light-200", children: [_jsx("div", { className: "px-3 py-4", children: _jsxs(ButtonGroup, { size: "md", children: [_jsx(Button, { onClick: () => setActive('courses'), variant: `${active === 'courses' ? 'primary' : 'outline-primary'}`, children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.tab']) }), _jsx(Button, { onClick: () => setActive('libraries'), variant: `${active === 'libraries' ? 'primary' : 'outline-primary'}`, children: intl.formatMessage(messages['authz.tabs.permissionsRoles.libraries.tab']) })] }) }), active === 'courses' && (_jsx("div", { className: "position-relative", children: _jsx(PermissionTable, { permissionsTable: coursePermissionsByResource, roles: courseRolesWithPermissions, title: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.tab.title']) }) })), active === 'libraries' && (_jsx(PermissionTable, { permissionsTable: libraryPermissionsByResource, roles: libraryRolesWithPermissions, title: intl.formatMessage(messages['authz.tabs.permissionsRoles.libraries.tab.title']) }))] }), active === 'courses' && (_jsx(Alert, { variant: "info", className: "mt-5", children: _jsxs("div", { className: "row align-items-center", children: [_jsxs("div", { className: "col-12 col-md-7", children: [_jsx("p", { className: "text-primary font-weight-bold h4", children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.title']) }), _jsxs("span", { children: [_jsx("span", { className: "font-weight-bold", children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.note']) }), intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.description'])] })] }), _jsx("div", { className: "col-12 col-md-5 mt-3 mt-md-0", children: _jsx(Hyperlink, { className: "d-block text-right h5 font-weight-normal", destination: "https://docs.openedx.org/en/latest/educators/references/course_development/course_team_roles.html", target: "_blank", showLaunchIcon: false, isInline: true, children: intl.formatMessage(messages['authz.tabs.permissionsRoles.courses.alert.link']) }) })] }) })), _jsx(AnchorButton, {})] }));
33
33
  };
34
34
  export default RolesPermissions;
35
35
  //# sourceMappingURL=RolesPermissions.js.map