@masterteam/permissions 0.0.1 → 0.0.3

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, input, output, signal, effect, Component, DestroyRef, linkedSignal, computed } from '@angular/core';
2
+ import { inject, Injectable, computed, input, output, signal, effect, Component, DestroyRef, linkedSignal } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i1 from '@angular/forms';
@@ -14,13 +14,26 @@ import * as i2 from '@jsverse/transloco';
14
14
  import { TranslocoModule, TranslocoService } from '@jsverse/transloco';
15
15
  import * as i2$1 from 'primeng/skeleton';
16
16
  import { SkeletonModule } from 'primeng/skeleton';
17
- import { Action, Selector, State, Store } from '@ngxs/store';
17
+ import { Action, Selector, State, Store, select } from '@ngxs/store';
18
18
  import { HttpClient } from '@angular/common/http';
19
- import { map, tap, catchError, finalize } from 'rxjs';
19
+ import { map } from 'rxjs';
20
+ import { CrudStateBase, handleApiRequest } from '@masterteam/components';
20
21
  import { ModalRef } from '@masterteam/components/dialog';
21
22
  import { Tabs } from '@masterteam/components/tabs';
22
23
  import { AccessibilitiesFacade } from '@masterteam/accessibilities';
23
24
 
25
+ var PermissionsActionKey;
26
+ (function (PermissionsActionKey) {
27
+ PermissionsActionKey["LoadRoles"] = "loadRoles";
28
+ PermissionsActionKey["SelectRole"] = "selectRole";
29
+ PermissionsActionKey["SelectGroup"] = "selectGroup";
30
+ PermissionsActionKey["LoadPermissions"] = "loadPermissions";
31
+ PermissionsActionKey["LoadGroupPermissions"] = "loadGroupPermissions";
32
+ PermissionsActionKey["UpdatePermission"] = "updatePermission";
33
+ PermissionsActionKey["UpdateGroupPermission"] = "updateGroupPermission";
34
+ PermissionsActionKey["ToggleAllLevelPermissions"] = "toggleAllLevelPermissions";
35
+ PermissionsActionKey["ToggleAllGroupPermissions"] = "toggleAllGroupPermissions";
36
+ })(PermissionsActionKey || (PermissionsActionKey = {}));
24
37
  var ModuleType;
25
38
  (function (ModuleType) {
26
39
  ModuleType["LEVEL"] = "level";
@@ -32,20 +45,6 @@ class LoadRoles {
32
45
  static type = '[Permissions] Load Roles';
33
46
  constructor() { }
34
47
  }
35
- class LoadRolesSuccess {
36
- roles;
37
- static type = '[Permissions] Load Roles Success';
38
- constructor(roles) {
39
- this.roles = roles;
40
- }
41
- }
42
- class LoadRolesFail {
43
- error;
44
- static type = '[Permissions] Load Roles Fail';
45
- constructor(error) {
46
- this.error = error;
47
- }
48
- }
49
48
  class SelectRole {
50
49
  roleValue;
51
50
  static type = '[Permissions] Select Role';
@@ -78,27 +77,6 @@ class LoadGroupPermissions {
78
77
  this.levelId = levelId;
79
78
  }
80
79
  }
81
- class LoadPermissionsSuccess {
82
- permissions;
83
- static type = '[Permissions] Load Permissions Success';
84
- constructor(permissions) {
85
- this.permissions = permissions;
86
- }
87
- }
88
- class LoadGroupPermissionsSuccess {
89
- permissions;
90
- static type = '[Permissions] Load Group Permissions Success';
91
- constructor(permissions) {
92
- this.permissions = permissions;
93
- }
94
- }
95
- class LoadPermissionsFail {
96
- error;
97
- static type = '[Permissions] Load Permissions Fail';
98
- constructor(error) {
99
- this.error = error;
100
- }
101
- }
102
80
  class UpdatePermissionLocally {
103
81
  roleValue;
104
82
  levelId;
@@ -112,19 +90,6 @@ class UpdatePermissionLocally {
112
90
  this.isSelected = isSelected;
113
91
  }
114
92
  }
115
- class UpdateGroupPermissionLocally {
116
- roleValue;
117
- levelId;
118
- actionId;
119
- isSelected;
120
- static type = '[Permissions] Update Group Permission Locally';
121
- constructor(roleValue, levelId, actionId, isSelected) {
122
- this.roleValue = roleValue;
123
- this.levelId = levelId;
124
- this.actionId = actionId;
125
- this.isSelected = isSelected;
126
- }
127
- }
128
93
  class UpdatePermission {
129
94
  roleValue;
130
95
  levelId;
@@ -136,25 +101,13 @@ class UpdatePermission {
136
101
  }
137
102
  class UpdateGroupPermission {
138
103
  groupId;
139
- permissionLogs;
140
104
  levelId;
141
105
  static type = '[Permissions] Update Group Permission';
142
- constructor(groupId, permissionLogs, levelId) {
106
+ constructor(groupId, levelId) {
143
107
  this.groupId = groupId;
144
- this.permissionLogs = permissionLogs;
145
108
  this.levelId = levelId;
146
109
  }
147
110
  }
148
- class UpdatePermissionSuccess {
149
- static type = '[Permissions] Update Permission Success';
150
- }
151
- class UpdatePermissionFail {
152
- error;
153
- static type = '[Permissions] Update Permission Fail';
154
- constructor(error) {
155
- this.error = error;
156
- }
157
- }
158
111
  class ToggleAllLevelPermissions {
159
112
  roleValue;
160
113
  levelId;
@@ -205,78 +158,75 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
205
158
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
206
159
  return c > 3 && r && Object.defineProperty(target, key, r), r;
207
160
  };
208
- let PermissionsState = class PermissionsState {
161
+ let PermissionsState = class PermissionsState extends CrudStateBase {
209
162
  http = inject(HttpClient);
210
- static roles(state) {
163
+ // ============================================================================
164
+ // Data Selectors - Individual for fine-grained reactivity
165
+ // ============================================================================
166
+ static getRoles(state) {
211
167
  return state.roles;
212
168
  }
213
- static selectedRoleValue(state) {
169
+ static getSelectedRoleValue(state) {
214
170
  return state.selectedRoleValue;
215
171
  }
216
- static selectedGroupValue(state) {
172
+ static getSelectedGroupValue(state) {
217
173
  return state.selectedGroupValue;
218
174
  }
219
- static permissions(state) {
175
+ static getPermissions(state) {
220
176
  return state.permissions;
221
177
  }
222
- static groupPermissions(state) {
178
+ static getGroupPermissions(state) {
223
179
  return state.groupPermissions;
224
180
  }
225
- static loading(state) {
226
- return state.loading;
227
- }
228
- static permissionsLoading(state) {
229
- return state.permissionsLoading;
230
- }
231
- static addPermissionsLoading(state) {
232
- return state.addPermissionsLoading;
233
- }
234
- static moduleType(state) {
181
+ static getModuleType(state) {
235
182
  return state.moduleType;
236
183
  }
237
- static moduleId(state) {
184
+ static getModuleId(state) {
238
185
  return state.moduleId;
239
186
  }
240
- static levelId(state) {
187
+ static getLevelId(state) {
241
188
  return state.moduleType === 'module'
242
189
  ? state.parentModuleId.toString()
243
190
  : state.moduleId.toString();
244
191
  }
245
- static error(state) {
246
- return state.error;
247
- }
192
+ // ============================================================================
193
+ // Loading/Error Slice Selectors - REQUIRED for optimal performance
194
+ // ============================================================================
195
+ static getLoadingActive(state) {
196
+ return state.loadingActive;
197
+ }
198
+ static getErrors(state) {
199
+ return state.errors;
200
+ }
201
+ // ============================================================================
202
+ // CRUD Actions
203
+ // ============================================================================
204
+ // ============================================================================
205
+ // CRUD Actions
206
+ // ============================================================================
248
207
  loadRoles(ctx) {
249
- ctx.patchState({
250
- loading: true,
251
- error: null,
252
- currentLevelId: ctx.getState().moduleId.toString() || '',
253
- });
254
- return this.http
255
- .get(`identity/roles/scopes/${ctx.getState().moduleType}/${ctx.getState().moduleId}?inherited=true`)
256
- .pipe(map((response) => response.data), tap((roles) => {
257
- ctx.dispatch(new LoadRolesSuccess(roles));
258
- }), catchError((error) => {
259
- ctx.dispatch(new LoadRolesFail(error.message || 'Failed to load roles'));
260
- throw error;
261
- }));
262
- }
263
- loadRolesSuccess(ctx, action) {
264
- ctx.patchState({
265
- roles: action.roles,
266
- loading: false,
267
- error: null,
268
- });
269
- }
270
- loadRolesFail(ctx, action) {
271
- ctx.patchState({
272
- loading: false,
273
- error: action.error,
208
+ const { moduleType, moduleId, parentPath } = ctx.getState();
209
+ const state = ctx.getState();
210
+ const req$ = this.http
211
+ .get(`identity/roles${parentPath ? '' : '/scopes'}${parentPath}/${moduleType}/${moduleId}${parentPath ? '' : '?inherited=true'}`)
212
+ .pipe(map((response) => response.data));
213
+ return handleApiRequest({
214
+ ctx,
215
+ key: PermissionsActionKey.LoadRoles,
216
+ request$: req$,
217
+ onSuccess: (roles) => ({
218
+ roles: state.moduleType === 'module' ? [{ roles: roles }] : roles,
219
+ currentLevelId: moduleId.toString() || '',
220
+ }),
274
221
  });
275
222
  }
223
+ // ============================================================================
224
+ // Simple State Updates (No HTTP)
225
+ // ============================================================================
276
226
  selectRole(ctx, action) {
277
227
  const state = ctx.getState();
278
228
  ctx.patchState({ selectedRoleValue: action.roleValue });
279
- if (state.currentLevelId) {
229
+ if (state.currentLevelId && action.roleValue) {
280
230
  ctx.dispatch(new LoadPermissions(action.roleValue, state.currentLevelId));
281
231
  }
282
232
  }
@@ -288,61 +238,35 @@ let PermissionsState = class PermissionsState {
288
238
  }
289
239
  }
290
240
  loadPermissions(ctx, action) {
291
- ctx.patchState({ permissionsLoading: true, error: null });
292
- // identity/roles/${action.roleValue}/permissions
293
- return this.http
294
- .get(`identity/roles/level/${ctx.getState().moduleType === 'module'
295
- ? ctx.getState().parentModuleId
296
- : ctx.getState().moduleId}/${ctx.getState().moduleType === 'module' ? 'module/' : ''}${ctx.getState().moduleType === 'module'
297
- ? `${ctx.getState().moduleId}/`
298
- : ''}${action.roleValue}/permissions`, {
299
- params: {
300
- scopeId: ctx.getState().moduleType === 'module'
301
- ? ctx.getState().parentModuleId
302
- : ctx.getState().moduleId,
303
- scopeType: ModuleType.LEVEL,
304
- },
305
- })
306
- .pipe(map((response) => response.data.permissions), tap((permissions) => {
307
- ctx.dispatch(new LoadPermissionsSuccess(permissions));
308
- }), catchError((error) => {
309
- ctx.dispatch(new LoadPermissionsFail(error.message || 'Failed to load permissions'));
310
- throw error;
311
- }));
312
- }
313
- loadGroupPermissions(ctx, action) {
314
- ctx.patchState({ permissionsLoading: true, error: null });
315
- return this.http
316
- .get(`identity/groups/level/${ctx.getState().moduleType === 'module'
317
- ? ctx.getState().parentModuleId
318
- : ctx.getState().moduleId}/${ctx.getState().moduleType === 'module' ? 'module/' : ''}${ctx.getState().moduleType === 'module'
319
- ? `${ctx.getState().moduleId}/`
320
- : ''}${action.groupId}/permissions`)
321
- .pipe(map((response) => response.data), tap((permissions) => {
322
- ctx.dispatch(new LoadGroupPermissionsSuccess(permissions));
323
- }), catchError((error) => {
324
- ctx.dispatch(new LoadPermissionsFail(error.message || 'Failed to load permissions'));
325
- throw error;
326
- }));
327
- }
328
- loadPermissionsSuccess(ctx, action) {
329
- ctx.patchState({
330
- permissions: action.permissions,
331
- permissionsLoading: false,
332
- error: null,
333
- });
334
- }
335
- loadGroupPermissionsSuccess(ctx, action) {
336
- ctx.patchState({
337
- groupPermissions: action.permissions,
338
- permissionsLoading: false,
339
- error: null,
241
+ const state = ctx.getState();
242
+ const modulePath = state.moduleType === 'module' ? `module/${state.moduleId}/` : '';
243
+ const levelId = state.moduleType === 'module' ? state.parentModuleId : state.moduleId;
244
+ const req$ = this.http
245
+ .get(`identity/roles/level/${levelId}/${modulePath}${action.roleValue}/permissions`)
246
+ .pipe(map((response) => response.data.modules));
247
+ return handleApiRequest({
248
+ ctx,
249
+ key: PermissionsActionKey.LoadPermissions,
250
+ request$: req$,
251
+ onSuccess: (permissions) => ({
252
+ permissions,
253
+ }),
340
254
  });
341
255
  }
342
- loadPermissionsFail(ctx, action) {
343
- ctx.patchState({
344
- permissionsLoading: false,
345
- error: action.error,
256
+ loadGroupPermissions(ctx, action) {
257
+ const state = ctx.getState();
258
+ const modulePath = state.moduleType === 'module' ? `module/${state.moduleId}/` : '';
259
+ const levelId = state.moduleType === 'module' ? state.parentModuleId : state.moduleId;
260
+ const req$ = this.http
261
+ .get(`identity/groups/level/${levelId}/${modulePath}${action.groupId}/permissions`)
262
+ .pipe(map((response) => response.data.modules));
263
+ return handleApiRequest({
264
+ ctx,
265
+ key: PermissionsActionKey.LoadPermissions,
266
+ request$: req$,
267
+ onSuccess: (permissions) => ({
268
+ permissions,
269
+ }),
346
270
  });
347
271
  }
348
272
  updatePermissionLocally(ctx, action) {
@@ -355,117 +279,104 @@ let PermissionsState = class PermissionsState {
355
279
  }));
356
280
  ctx.patchState({ permissions: updatedPermissions });
357
281
  }
358
- updateGroupPermissionLocally(ctx, action) {
359
- const state = ctx.getState();
360
- const updatedPermissions = state.groupPermissions.map((permission) => ({
361
- ...permission,
362
- logs: permission.logs.map((log) => ({
363
- ...log,
364
- actions: log.actions.map((act) => act.id === action.actionId
365
- ? { ...act, isSelected: action.isSelected }
366
- : act),
367
- })),
368
- }));
369
- ctx.patchState({ groupPermissions: updatedPermissions });
370
- }
282
+ // ============================================================================
283
+ // Complex Operations - use handleApiRequest for transformations
284
+ // ============================================================================
371
285
  updatePermission(ctx, action) {
372
286
  const state = ctx.getState();
373
- ctx.patchState({ addPermissionsLoading: true, error: null });
374
- const updatedPermissions = state.permissions;
375
- ctx.patchState({ permissions: updatedPermissions });
376
- return this.http
377
- .put(`identity/roles/${action.roleValue}/setAllPermissions`, { permissions: updatedPermissions }, {
287
+ const updatedPermissions = [];
288
+ state.permissions?.forEach((p) => {
289
+ p?.actions.forEach((a) => {
290
+ updatedPermissions.push({ id: a?.id, isSelected: a?.isSelected });
291
+ });
292
+ });
293
+ const scopeId = state.moduleType === 'module' ? state.parentModuleId : state.moduleId;
294
+ const req$ = this.http.put(`identity/roles/${action.roleValue}/setAllPermissions`, { permissions: updatedPermissions }, {
378
295
  params: {
379
- scopeId: ctx.getState().moduleType === 'module'
380
- ? ctx.getState().parentModuleId
381
- : ctx.getState().moduleId,
296
+ scopeId,
382
297
  scopeType: ModuleType.LEVEL,
383
298
  },
384
- })
385
- .pipe(tap(() => {
386
- ctx.dispatch(new UpdatePermissionSuccess());
387
- }), finalize(() => {
388
- ctx.patchState({ addPermissionsLoading: false });
389
- }), catchError((error) => {
390
- // Rollback on error
391
- ctx.patchState({
392
- permissions: state.permissions,
393
- addPermissionsLoading: false,
394
- });
395
- ctx.dispatch(new UpdatePermissionFail(error.message || 'Failed to update permission'));
396
- throw error;
397
- }));
299
+ });
300
+ return handleApiRequest({
301
+ ctx,
302
+ key: PermissionsActionKey.UpdatePermission,
303
+ request$: req$,
304
+ onSuccess: () => ({}),
305
+ onError: (error, currentState) => {
306
+ // Rollback on error
307
+ return { permissions: currentState.permissions };
308
+ },
309
+ errorMessage: 'Failed to update permission',
310
+ });
398
311
  }
399
312
  updateGroupPermission(ctx, action) {
400
313
  const state = ctx.getState();
401
- ctx.patchState({ addPermissionsLoading: true, error: null });
402
- const updatedPermissions = state.groupPermissions;
403
- ctx.patchState({ groupPermissions: updatedPermissions });
404
- return this.http
405
- .put(`identity/groups/${action.groupId}/setAllPermissions`, { permissions: updatedPermissions[0].logs || [] })
406
- .pipe(tap(() => {
407
- ctx.dispatch(new UpdatePermissionSuccess());
408
- }), finalize(() => {
409
- ctx.patchState({ addPermissionsLoading: false });
410
- }), catchError((error) => {
411
- // Rollback on error
412
- ctx.patchState({
413
- groupPermissions: state.groupPermissions,
414
- addPermissionsLoading: false,
314
+ const updatedPermissions = [];
315
+ state.permissions?.forEach((p) => {
316
+ p?.actions.forEach((a) => {
317
+ updatedPermissions.push({ id: a?.id, isSelected: a?.isSelected });
415
318
  });
416
- ctx.dispatch(new UpdatePermissionFail(error.message || 'Failed to update permission'));
417
- throw error;
418
- }));
319
+ });
320
+ const req$ = this.http.put(`identity/groups/${action.groupId}/setAllPermissions`, { permissions: updatedPermissions });
321
+ return handleApiRequest({
322
+ ctx,
323
+ key: PermissionsActionKey.UpdateGroupPermission,
324
+ request$: req$,
325
+ onSuccess: () => ({}),
326
+ onError: (error, currentState) => {
327
+ // Rollback on error
328
+ return { permissions: currentState.permissions };
329
+ },
330
+ errorMessage: 'Failed to update permission',
331
+ });
419
332
  }
420
333
  toggleAllLevelPermissions(ctx, action) {
421
334
  const state = ctx.getState();
422
- const updatedPermissions = state.permissions.map((log) => ({
423
- ...log,
424
- actions: log.actions.map((act) => ({
425
- ...act,
426
- isSelected: action.enabled,
427
- })),
428
- }));
429
- ctx.patchState({ permissions: updatedPermissions });
430
- return this.http
431
- .put(`identity/roles/${action.roleValue}/setAllPermissions`, { permissions: updatedPermissions }, {
335
+ const updatedPermissions = [];
336
+ state.permissions?.forEach((p) => {
337
+ p?.actions.forEach((a) => {
338
+ updatedPermissions.push({ id: a?.id, isSelected: action.enabled });
339
+ });
340
+ });
341
+ const scopeId = state.moduleType === 'module' ? state.parentModuleId : state.moduleId;
342
+ const req$ = this.http.put(`identity/roles/${action.roleValue}/setAllPermissions`, { permissions: updatedPermissions }, {
432
343
  params: {
433
- scopeId: ctx.getState().moduleType === 'module'
434
- ? ctx.getState().parentModuleId
435
- : ctx.getState().moduleId,
344
+ scopeId,
436
345
  scopeType: ModuleType.LEVEL,
437
346
  },
438
- })
439
- .pipe(tap(() => {
440
- ctx.dispatch(new UpdatePermissionSuccess());
441
- }), catchError((error) => {
442
- ctx.patchState({ permissions: state.permissions });
443
- ctx.dispatch(new UpdatePermissionFail(error.message || 'Failed to toggle all permissions'));
444
- throw error;
445
- }));
347
+ });
348
+ return handleApiRequest({
349
+ ctx,
350
+ key: PermissionsActionKey.ToggleAllLevelPermissions,
351
+ request$: req$,
352
+ onSuccess: () => ({}),
353
+ onError: () => ({
354
+ permissions: state.permissions,
355
+ }),
356
+ errorMessage: 'Failed to toggle all permissions',
357
+ });
446
358
  }
447
359
  toggleAllGroupPermissions(ctx, action) {
448
360
  const state = ctx.getState();
449
- const updatedPermissions = state.groupPermissions.map((permission) => ({
450
- ...permission,
451
- logs: permission.logs.map((log) => ({
452
- ...log,
453
- actions: log.actions.map((act) => ({
454
- ...act,
455
- isSelected: action.enabled,
456
- })),
457
- })),
458
- }));
459
- ctx.patchState({ groupPermissions: updatedPermissions });
460
- return this.http
461
- .put(`identity/groups/${action.groupId}/setAllPermissions`, { permissions: updatedPermissions[0].logs || [] })
462
- .pipe(tap(() => {
463
- ctx.dispatch(new UpdatePermissionSuccess());
464
- }), catchError((error) => {
465
- ctx.patchState({ groupPermissions: state.groupPermissions });
466
- ctx.dispatch(new UpdatePermissionFail(error.message || 'Failed to toggle all permissions'));
467
- throw error;
468
- }));
361
+ const updatedPermissions = [];
362
+ state.permissions?.forEach((p) => {
363
+ p?.actions.forEach((a) => {
364
+ updatedPermissions.push({ id: a?.id, isSelected: action.enabled });
365
+ });
366
+ });
367
+ const req$ = this.http.put(`identity/groups/${action.groupId}/setAllPermissions`, { permissions: updatedPermissions });
368
+ return handleApiRequest({
369
+ ctx,
370
+ key: PermissionsActionKey.ToggleAllGroupPermissions,
371
+ request$: req$,
372
+ onSuccess: () => ({
373
+ groupPermissions: updatedPermissions,
374
+ }),
375
+ onError: () => ({
376
+ groupPermissions: state.groupPermissions,
377
+ }),
378
+ errorMessage: 'Failed to toggle all permissions',
379
+ });
469
380
  }
470
381
  setModuleInfo(ctx, action) {
471
382
  let parentPath = '';
@@ -497,18 +408,12 @@ let PermissionsState = class PermissionsState {
497
408
  groupPermissions: [],
498
409
  });
499
410
  }
500
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
411
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsState, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
501
412
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsState });
502
413
  };
503
414
  __decorate([
504
415
  Action(LoadRoles)
505
416
  ], PermissionsState.prototype, "loadRoles", null);
506
- __decorate([
507
- Action(LoadRolesSuccess)
508
- ], PermissionsState.prototype, "loadRolesSuccess", null);
509
- __decorate([
510
- Action(LoadRolesFail)
511
- ], PermissionsState.prototype, "loadRolesFail", null);
512
417
  __decorate([
513
418
  Action(SelectRole)
514
419
  ], PermissionsState.prototype, "selectRole", null);
@@ -521,21 +426,9 @@ __decorate([
521
426
  __decorate([
522
427
  Action(LoadGroupPermissions)
523
428
  ], PermissionsState.prototype, "loadGroupPermissions", null);
524
- __decorate([
525
- Action(LoadPermissionsSuccess)
526
- ], PermissionsState.prototype, "loadPermissionsSuccess", null);
527
- __decorate([
528
- Action(LoadGroupPermissionsSuccess)
529
- ], PermissionsState.prototype, "loadGroupPermissionsSuccess", null);
530
- __decorate([
531
- Action(LoadPermissionsFail)
532
- ], PermissionsState.prototype, "loadPermissionsFail", null);
533
429
  __decorate([
534
430
  Action(UpdatePermissionLocally)
535
431
  ], PermissionsState.prototype, "updatePermissionLocally", null);
536
- __decorate([
537
- Action(UpdateGroupPermissionLocally)
538
- ], PermissionsState.prototype, "updateGroupPermissionLocally", null);
539
432
  __decorate([
540
433
  Action(UpdatePermission)
541
434
  ], PermissionsState.prototype, "updatePermission", null);
@@ -556,40 +449,34 @@ __decorate([
556
449
  ], PermissionsState.prototype, "reset", null);
557
450
  __decorate([
558
451
  Selector()
559
- ], PermissionsState, "roles", null);
560
- __decorate([
561
- Selector()
562
- ], PermissionsState, "selectedRoleValue", null);
563
- __decorate([
564
- Selector()
565
- ], PermissionsState, "selectedGroupValue", null);
452
+ ], PermissionsState, "getRoles", null);
566
453
  __decorate([
567
454
  Selector()
568
- ], PermissionsState, "permissions", null);
455
+ ], PermissionsState, "getSelectedRoleValue", null);
569
456
  __decorate([
570
457
  Selector()
571
- ], PermissionsState, "groupPermissions", null);
458
+ ], PermissionsState, "getSelectedGroupValue", null);
572
459
  __decorate([
573
460
  Selector()
574
- ], PermissionsState, "loading", null);
461
+ ], PermissionsState, "getPermissions", null);
575
462
  __decorate([
576
463
  Selector()
577
- ], PermissionsState, "permissionsLoading", null);
464
+ ], PermissionsState, "getGroupPermissions", null);
578
465
  __decorate([
579
466
  Selector()
580
- ], PermissionsState, "addPermissionsLoading", null);
467
+ ], PermissionsState, "getModuleType", null);
581
468
  __decorate([
582
469
  Selector()
583
- ], PermissionsState, "moduleType", null);
470
+ ], PermissionsState, "getModuleId", null);
584
471
  __decorate([
585
472
  Selector()
586
- ], PermissionsState, "moduleId", null);
473
+ ], PermissionsState, "getLevelId", null);
587
474
  __decorate([
588
475
  Selector()
589
- ], PermissionsState, "levelId", null);
476
+ ], PermissionsState, "getLoadingActive", null);
590
477
  __decorate([
591
478
  Selector()
592
- ], PermissionsState, "error", null);
479
+ ], PermissionsState, "getErrors", null);
593
480
  PermissionsState = __decorate([
594
481
  State({
595
482
  name: 'permissions',
@@ -600,36 +487,59 @@ PermissionsState = __decorate([
600
487
  permissions: [],
601
488
  groupPermissions: [],
602
489
  currentLevelId: null,
603
- loading: false,
604
- permissionsLoading: false,
605
- addPermissionsLoading: false,
606
- error: null,
607
490
  moduleType: '',
608
491
  moduleId: '',
609
- parentModuleType: '',
610
- parentModuleId: '',
492
+ parentModuleType: null,
493
+ parentModuleId: null,
611
494
  parentPath: '',
495
+ loadingActive: [], // Required by LoadingStateShape
496
+ errors: {}, // Required by LoadingStateShape
612
497
  },
613
498
  })
614
499
  ], PermissionsState);
615
500
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsState, decorators: [{
616
501
  type: Injectable
617
- }], propDecorators: { loadRoles: [], loadRolesSuccess: [], loadRolesFail: [], selectRole: [], selectGroup: [], loadPermissions: [], loadGroupPermissions: [], loadPermissionsSuccess: [], loadGroupPermissionsSuccess: [], loadPermissionsFail: [], updatePermissionLocally: [], updateGroupPermissionLocally: [], updatePermission: [], updateGroupPermission: [], toggleAllLevelPermissions: [], toggleAllGroupPermissions: [], setModuleInfo: [], reset: [] } });
502
+ }], propDecorators: { loadRoles: [], selectRole: [], selectGroup: [], loadPermissions: [], loadGroupPermissions: [], updatePermissionLocally: [], updatePermission: [], updateGroupPermission: [], toggleAllLevelPermissions: [], toggleAllGroupPermissions: [], setModuleInfo: [], reset: [] } });
618
503
 
619
504
  class PermissionsFacade {
620
505
  store = inject(Store);
621
- selectors = {
622
- roles: this.store.selectSignal(PermissionsState.roles),
623
- selectedRoleValue: this.store.selectSignal(PermissionsState.selectedRoleValue),
624
- selectedGroupValue: this.store.selectSignal(PermissionsState.selectedGroupValue),
625
- permissions: this.store.selectSignal(PermissionsState.permissions),
626
- groupPermissions: this.store.selectSignal(PermissionsState.groupPermissions),
627
- loading: this.store.selectSignal(PermissionsState.loading),
628
- permissionsLoading: this.store.selectSignal(PermissionsState.permissionsLoading),
629
- addPermissionsLoading: this.store.selectSignal(PermissionsState.addPermissionsLoading),
630
- error: this.store.selectSignal(PermissionsState.error),
631
- levelId: this.store.selectSignal(PermissionsState.levelId),
632
- };
506
+ // ============================================================================
507
+ // Data Selectors - Memoized by NGXS (fine-grained reactivity)
508
+ // ============================================================================
509
+ roles = select(PermissionsState.getRoles);
510
+ selectedRoleValue = select(PermissionsState.getSelectedRoleValue);
511
+ selectedGroupValue = select(PermissionsState.getSelectedGroupValue);
512
+ permissions = select(PermissionsState.getPermissions);
513
+ groupPermissions = select(PermissionsState.getGroupPermissions);
514
+ moduleType = select(PermissionsState.getModuleType);
515
+ moduleId = select(PermissionsState.getModuleId);
516
+ levelId = select(PermissionsState.getLevelId);
517
+ // ============================================================================
518
+ // Loading/Error Slices - Memoized by NGXS
519
+ // ============================================================================
520
+ loadingActive = select(PermissionsState.getLoadingActive);
521
+ errors = select(PermissionsState.getErrors);
522
+ // ============================================================================
523
+ // Loading Signals - Computed from slice (minimal reactivity)
524
+ // ============================================================================
525
+ isLoadingRoles = computed(() => this.loadingActive().includes(PermissionsActionKey.LoadRoles), ...(ngDevMode ? [{ debugName: "isLoadingRoles" }] : []));
526
+ isLoadingPermissions = computed(() => this.loadingActive().includes(PermissionsActionKey.LoadPermissions), ...(ngDevMode ? [{ debugName: "isLoadingPermissions" }] : []));
527
+ isLoadingGroupPermissions = computed(() => this.loadingActive().includes(PermissionsActionKey.LoadGroupPermissions), ...(ngDevMode ? [{ debugName: "isLoadingGroupPermissions" }] : []));
528
+ isUpdatingPermission = computed(() => this.loadingActive().includes(PermissionsActionKey.UpdatePermission), ...(ngDevMode ? [{ debugName: "isUpdatingPermission" }] : []));
529
+ isUpdatingGroupPermission = computed(() => this.loadingActive().includes(PermissionsActionKey.UpdateGroupPermission), ...(ngDevMode ? [{ debugName: "isUpdatingGroupPermission" }] : []));
530
+ isTogglingLevelPermissions = computed(() => this.loadingActive().includes(PermissionsActionKey.ToggleAllLevelPermissions), ...(ngDevMode ? [{ debugName: "isTogglingLevelPermissions" }] : []));
531
+ isTogglingGroupPermissions = computed(() => this.loadingActive().includes(PermissionsActionKey.ToggleAllGroupPermissions), ...(ngDevMode ? [{ debugName: "isTogglingGroupPermissions" }] : []));
532
+ // ============================================================================
533
+ // Error Signals - Computed from slice (minimal reactivity)
534
+ // ============================================================================
535
+ rolesError = computed(() => this.errors()[PermissionsActionKey.LoadRoles] ?? null, ...(ngDevMode ? [{ debugName: "rolesError" }] : []));
536
+ permissionsError = computed(() => this.errors()[PermissionsActionKey.LoadPermissions] ?? null, ...(ngDevMode ? [{ debugName: "permissionsError" }] : []));
537
+ groupPermissionsError = computed(() => this.errors()[PermissionsActionKey.LoadGroupPermissions] ?? null, ...(ngDevMode ? [{ debugName: "groupPermissionsError" }] : []));
538
+ updatePermissionError = computed(() => this.errors()[PermissionsActionKey.UpdatePermission] ?? null, ...(ngDevMode ? [{ debugName: "updatePermissionError" }] : []));
539
+ updateGroupPermissionError = computed(() => this.errors()[PermissionsActionKey.UpdateGroupPermission] ?? null, ...(ngDevMode ? [{ debugName: "updateGroupPermissionError" }] : []));
540
+ // ============================================================================
541
+ // Action Dispatchers
542
+ // ============================================================================
633
543
  loadRoles() {
634
544
  return this.store.dispatch(new LoadRoles());
635
545
  }
@@ -654,14 +564,11 @@ class PermissionsFacade {
654
564
  updatePermissionLocally(roleValue, levelId, actionId, isSelected) {
655
565
  return this.store.dispatch(new UpdatePermissionLocally(roleValue, levelId, actionId, isSelected));
656
566
  }
657
- updateGroupPermissionLocally(roleValue, levelId, actionId, isSelected) {
658
- return this.store.dispatch(new UpdateGroupPermissionLocally(roleValue, levelId, actionId, isSelected));
659
- }
660
567
  updatePermission(roleValue, levelId) {
661
568
  return this.store.dispatch(new UpdatePermission(roleValue, levelId));
662
569
  }
663
- updateGroupPermission(groupId, permissionLogs, levelId) {
664
- return this.store.dispatch(new UpdateGroupPermission(groupId, permissionLogs, levelId));
570
+ updateGroupPermission(groupId, levelId) {
571
+ return this.store.dispatch(new UpdateGroupPermission(groupId, levelId));
665
572
  }
666
573
  toggleAllLevelPermissions(roleValue, levelId, levelName, enabled) {
667
574
  return this.store.dispatch(new ToggleAllLevelPermissions(roleValue, levelId, levelName, enabled));
@@ -689,8 +596,9 @@ class PermissionsEditDialog {
689
596
  ref = inject(ModalRef);
690
597
  // permissionGroup = input.required<PermissionLog | null>();
691
598
  permissionGroup = input(null, ...(ngDevMode ? [{ debugName: "permissionGroup" }] : []));
692
- addPermissionsLoading = this.permissionsFacade.selectors.addPermissionsLoading;
693
- addPermissionsError = this.permissionsFacade.selectors.error;
599
+ // Use new facade pattern
600
+ addPermissionsLoading = this.permissionsFacade.isUpdatingPermission;
601
+ addPermissionsError = this.permissionsFacade.updatePermissionError;
694
602
  levelId = input.required(...(ngDevMode ? [{ debugName: "levelId" }] : []));
695
603
  roleValue = input.required(...(ngDevMode ? [{ debugName: "roleValue" }] : []));
696
604
  isGroup = input.required(...(ngDevMode ? [{ debugName: "isGroup" }] : []));
@@ -720,10 +628,6 @@ class PermissionsEditDialog {
720
628
  const levelId = this.levelId();
721
629
  const roleValue = this.roleValue();
722
630
  if (levelId && roleValue) {
723
- if (this.isGroup()) {
724
- this.permissionsFacade.updateGroupPermissionLocally(roleValue, levelId, actionId, isSelected);
725
- return;
726
- }
727
631
  this.permissionsFacade.updatePermissionLocally(roleValue, levelId, actionId, isSelected);
728
632
  }
729
633
  }
@@ -744,7 +648,7 @@ class PermissionsEditDialog {
744
648
  if (levelId && roleValue) {
745
649
  let subscription;
746
650
  if (isGroup) {
747
- subscription = this.permissionsFacade.updateGroupPermission(roleValue, [this.permissionGroup()], levelId);
651
+ subscription = this.permissionsFacade.updateGroupPermission(roleValue, levelId);
748
652
  }
749
653
  else {
750
654
  subscription = this.permissionsFacade.updatePermission(roleValue, levelId);
@@ -768,7 +672,7 @@ class PermissionsEditDialog {
768
672
  }
769
673
  }
770
674
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsEditDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
771
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PermissionsEditDialog, isStandalone: true, selector: "mt-permissions-edit-dialog", inputs: { permissionGroup: { classPropertyName: "permissionGroup", publicName: "permissionGroup", isSignal: true, isRequired: false, transformFunction: null }, levelId: { classPropertyName: "levelId", publicName: "levelId", isSignal: true, isRequired: true, transformFunction: null }, roleValue: { classPropertyName: "roleValue", publicName: "roleValue", isSignal: true, isRequired: true, transformFunction: null }, isGroup: { classPropertyName: "isGroup", publicName: "isGroup", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { closeDialog: "closeDialog" }, ngImport: i0, template: "<div [class]=\"'flex flex-col gap-3 p-4 ' + modal.contentClass\">\r\n @if (permissionGroup(); as group) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface mb-4\"\r\n >\r\n <span class=\"text-sm font-medium\">{{\r\n \"permissions.selectAll\" | transloco\r\n }}</span>\r\n <mt-toggle-field\r\n [(ngModel)]=\"toggleAll\"\r\n (onChange)=\"selectAll()\"\r\n ></mt-toggle-field>\r\n </div>\r\n @for (action of group.actions; track trackByActionId($index, action)) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface\"\r\n >\r\n <span class=\"text-sm font-medium\">{{ action.name }}</span>\r\n <mt-toggle-field\r\n [formControl]=\"getControl(action.id)\"\r\n ></mt-toggle-field>\r\n </div>\r\n }\r\n }\r\n</div>\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"'save'\"\r\n (click)=\"onSave()\"\r\n [loading]=\"addPermissionsLoading()\"\r\n />\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
675
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PermissionsEditDialog, isStandalone: true, selector: "mt-permissions-edit-dialog", inputs: { permissionGroup: { classPropertyName: "permissionGroup", publicName: "permissionGroup", isSignal: true, isRequired: false, transformFunction: null }, levelId: { classPropertyName: "levelId", publicName: "levelId", isSignal: true, isRequired: true, transformFunction: null }, roleValue: { classPropertyName: "roleValue", publicName: "roleValue", isSignal: true, isRequired: true, transformFunction: null }, isGroup: { classPropertyName: "isGroup", publicName: "isGroup", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { closeDialog: "closeDialog" }, ngImport: i0, template: "<div [class]=\"'flex flex-col gap-3 p-4 ' + modal.contentClass\">\r\n @if (permissionGroup(); as group) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface mb-4\"\r\n >\r\n <span class=\"text-sm font-medium\">{{\r\n \"permissions.selectAll\" | transloco\r\n }}</span>\r\n <mt-toggle-field\r\n [(ngModel)]=\"toggleAll\"\r\n (onChange)=\"selectAll()\"\r\n ></mt-toggle-field>\r\n </div>\r\n @for (action of group.actions; track trackByActionId($index, action)) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface\"\r\n >\r\n <span class=\"text-sm font-medium\">{{ action.name?.display }}</span>\r\n <mt-toggle-field\r\n [formControl]=\"getControl(action.id)\"\r\n ></mt-toggle-field>\r\n </div>\r\n }\r\n }\r\n</div>\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"'save'\"\r\n (click)=\"onSave()\"\r\n [loading]=\"addPermissionsLoading()\"\r\n />\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
772
676
  }
773
677
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsEditDialog, decorators: [{
774
678
  type: Component,
@@ -779,7 +683,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
779
683
  TranslocoModule,
780
684
  FormsModule,
781
685
  Button,
782
- ], template: "<div [class]=\"'flex flex-col gap-3 p-4 ' + modal.contentClass\">\r\n @if (permissionGroup(); as group) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface mb-4\"\r\n >\r\n <span class=\"text-sm font-medium\">{{\r\n \"permissions.selectAll\" | transloco\r\n }}</span>\r\n <mt-toggle-field\r\n [(ngModel)]=\"toggleAll\"\r\n (onChange)=\"selectAll()\"\r\n ></mt-toggle-field>\r\n </div>\r\n @for (action of group.actions; track trackByActionId($index, action)) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface\"\r\n >\r\n <span class=\"text-sm font-medium\">{{ action.name }}</span>\r\n <mt-toggle-field\r\n [formControl]=\"getControl(action.id)\"\r\n ></mt-toggle-field>\r\n </div>\r\n }\r\n }\r\n</div>\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"'save'\"\r\n (click)=\"onSave()\"\r\n [loading]=\"addPermissionsLoading()\"\r\n />\r\n</div>\r\n" }]
686
+ ], template: "<div [class]=\"'flex flex-col gap-3 p-4 ' + modal.contentClass\">\r\n @if (permissionGroup(); as group) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface mb-4\"\r\n >\r\n <span class=\"text-sm font-medium\">{{\r\n \"permissions.selectAll\" | transloco\r\n }}</span>\r\n <mt-toggle-field\r\n [(ngModel)]=\"toggleAll\"\r\n (onChange)=\"selectAll()\"\r\n ></mt-toggle-field>\r\n </div>\r\n @for (action of group.actions; track trackByActionId($index, action)) {\r\n <div\r\n class=\"flex items-center justify-between border rounded-lg p-3 border-surface\"\r\n >\r\n <span class=\"text-sm font-medium\">{{ action.name?.display }}</span>\r\n <mt-toggle-field\r\n [formControl]=\"getControl(action.id)\"\r\n ></mt-toggle-field>\r\n </div>\r\n }\r\n }\r\n</div>\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"'save'\"\r\n (click)=\"onSave()\"\r\n [loading]=\"addPermissionsLoading()\"\r\n />\r\n</div>\r\n" }]
783
687
  }], ctorParameters: () => [], propDecorators: { permissionGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissionGroup", required: false }] }], levelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelId", required: true }] }], roleValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleValue", required: true }] }], isGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "isGroup", required: true }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }] } });
784
688
 
785
689
  class PermissionsPage {
@@ -791,16 +695,16 @@ class PermissionsPage {
791
695
  modal = inject(ModalService);
792
696
  destroyRef = inject(DestroyRef);
793
697
  defaultLevelName = 'Project';
794
- levelRoles = this.permissionsFacade.selectors.roles;
795
- selectedRoleValue = this.permissionsFacade.selectors.selectedRoleValue;
698
+ // Use new facade pattern
699
+ levelRoles = this.permissionsFacade.roles;
700
+ selectedRoleValue = this.permissionsFacade.selectedRoleValue;
796
701
  selectedRole = linkedSignal(this.selectedRoleValue, ...(ngDevMode ? [{ debugName: "selectedRole" }] : []));
797
- selectedGroupValue = this.permissionsFacade.selectors.selectedGroupValue;
702
+ selectedGroupValue = this.permissionsFacade.selectedGroupValue;
798
703
  selectedGroup = linkedSignal(this.selectedGroupValue, ...(ngDevMode ? [{ debugName: "selectedGroup" }] : []));
799
- permissions = this.permissionsFacade.selectors.permissions;
800
- groupPermissions = this.permissionsFacade.selectors.groupPermissions;
801
- loading = this.permissionsFacade.selectors.loading;
802
- permissionsLoading = this.permissionsFacade.selectors.permissionsLoading;
803
- levelId = this.permissionsFacade.selectors.levelId;
704
+ permissions = this.permissionsFacade.permissions;
705
+ loading = this.permissionsFacade.isLoadingRoles;
706
+ permissionsLoading = this.permissionsFacade.isLoadingPermissions;
707
+ levelId = this.permissionsFacade.levelId;
804
708
  groups = this.accessibilitiesFacade.groups;
805
709
  allPermissionsToggle = new FormControl(false);
806
710
  groupOrRoleId = computed(() => {
@@ -838,10 +742,6 @@ class PermissionsPage {
838
742
  return;
839
743
  }
840
744
  }
841
- if (this.groupOrRoleId() && this.groupPermissions().length == 0) {
842
- this.selectedGroup.set(+this.groupOrRoleId());
843
- this.permissionsFacade.selectGroup(+this.groupOrRoleId());
844
- }
845
745
  if (this.permissions().length == 0 && this.selectedTab() == 'roles') {
846
746
  if (this.groupOrRoleId() && this.levelRoles().length > 0) {
847
747
  const role = this.levelRoles()
@@ -921,30 +821,48 @@ class PermissionsPage {
921
821
  }
922
822
  }
923
823
  isAllPermissionsEnabled() {
924
- const groupsLogs = this.groupPermissions()
925
- .map((group) => group.logs)
926
- .flat();
927
- const perms = (this.selectedTab() == 'roles' ? this.permissions() : groupsLogs) || [];
928
- if (perms.length === 0)
824
+ if (this.permissions().length === 0)
929
825
  return false;
930
- return perms.every((log) => log.actions.every((action) => action.isSelected));
826
+ return this.permissions().every((log) => log?.actions.every((action) => action?.isSelected));
931
827
  }
932
828
  trackByRoleValue(_index, role) {
933
829
  return role.value;
934
830
  }
935
831
  onTabChange($event) {
936
832
  if ($event == 'roles') {
937
- this.router.navigate(['roles'], { relativeTo: this.route });
833
+ // Navigate to first role if available
834
+ const firstRole = this.levelRoles()
835
+ .map((levelRoles) => levelRoles.roles)
836
+ .flat()[0];
837
+ if (firstRole?.value) {
838
+ this.router.navigate(['roles', firstRole.value], {
839
+ relativeTo: this.route,
840
+ });
841
+ this.permissionsFacade.selectRole(firstRole.value);
842
+ }
843
+ else {
844
+ this.router.navigate(['roles'], { relativeTo: this.route });
845
+ }
938
846
  }
939
847
  else if ($event == 'groups') {
940
- this.router.navigate(['groups'], { relativeTo: this.route });
848
+ // Navigate to first group if available
849
+ const firstGroup = this.groups()[0];
850
+ if (firstGroup?.id) {
851
+ this.router.navigate(['groups', firstGroup.id], {
852
+ relativeTo: this.route,
853
+ });
854
+ this.permissionsFacade.selectGroup(firstGroup.id);
855
+ }
856
+ else {
857
+ this.router.navigate(['groups'], { relativeTo: this.route });
858
+ }
941
859
  }
942
860
  }
943
861
  ngOnDestroy() {
944
862
  this.permissionsFacade.reset();
945
863
  }
946
864
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
947
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PermissionsPage, isStandalone: true, selector: "mt-permissions-page", ngImport: i0, template: "<div id=\"permissions-page-card\" class=\"flex gap-4 p-1\">\r\n <div class=\"w-1/5 flex-shrink-0\">\r\n <mt-card class=\"h-full flex flex-col\">\r\n <ng-template #headless>\r\n <div class=\"flex flex-col h-full\">\r\n <div\r\n class=\"p-4 pb-0 bg-surface-50 rounded-t-2xl border-b border-surface\"\r\n >\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{ \"permissions.rolesAndGroups\" | transloco }}\r\n </h2>\r\n\r\n <mt-tabs\r\n [(active)]=\"selectedTab\"\r\n [options]=\"tabsList()\"\r\n size=\"large\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"flex-1 overflow-y-auto p-4\">\r\n @if (loading()) {\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n } @else {\r\n @if (selectedTab() === \"roles\") {\r\n @for (level of levelRoles(); track level.levelKey) {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n <h2 class=\"font-semibold\">{{ level.level }}</h2>\r\n @for (role of level.roles; track role.value) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedRole() === role.value\"\r\n [class.hover:bg-surface]=\"selectedRole() !== role.value\"\r\n [class.border-primary-400]=\"\r\n selectedRole() === role.value\r\n \"\r\n [style.--p-avatar-background]=\"\r\n selectedRole() === role.value\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedRole() === role.value ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectRole(role.value)\"\r\n >\r\n <mt-avatar [icon]=\"'user.user-check-01'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">\r\n {{ role.name }}\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noRolesFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noLevelRolesFound\" | transloco }}\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n @for (group of groups(); track group.name) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedGroup() === group.id\"\r\n [class.hover:bg-surface]=\"selectedGroup() !== group.id\"\r\n [class.border-primary-400]=\"selectedGroup() === group.id\"\r\n [style.--p-avatar-background]=\"\r\n selectedGroup() === group.id\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedGroup() === group.id ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectGroup(group.id)\"\r\n >\r\n <mt-avatar [icon]=\"'user.users-check'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">{{ group.name }}</div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noGroupsFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n </div>\r\n\r\n <div class=\"min-w-0 w-1/2\">\r\n @if (!selectedRole() && !selectedGroup()) {\r\n <mt-card class=\"h-full\">\r\n <ng-template #headless>\r\n <div class=\"flex items-center justify-center h-full text-muted-color\">\r\n {{ \"permissions.selectRoleToViewPermissions\" | transloco }}\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n } @else {\r\n <mt-card class=\"h-full\">\r\n <div class=\"flex flex-col h-full\">\r\n <ng-template #headless>\r\n <div class=\"p-4 pb-2 mb-5 border-b border-surface\">\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{\r\n (selectedTab() === \"roles\"\r\n ? \"permissions.levelPermissions\"\r\n : \"permissions.groupsPermissions\"\r\n ) | transloco\r\n }}\r\n </h2>\r\n </div>\r\n @if (permissionsLoading()) {\r\n <div class=\"mx-4\">\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"mb-5 p-3 mx-4 rounded-lg border-1 border-surface flex items-center justify-between\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'security.lock-unlocked-01'\"\r\n shape=\"square\"\r\n size=\"large\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"'var(--p-' + 'primary' + '-600)'\"\r\n >\r\n </mt-avatar>\r\n <div>\r\n <div class=\"text-sm font-semibold\">\r\n {{\r\n (selectedTab() === \"roles\"\r\n ? \"permissions.setAllProjectPermissions\"\r\n : \"permissions.setAllGroupPermissions\"\r\n ) | transloco\r\n }}\r\n </div>\r\n <div class=\"text-xs text-muted-color\">\r\n {{ \"permissions.recommendedForSimpleForms\" | transloco }}\r\n </div>\r\n </div>\r\n </div>\r\n <mt-toggle-field\r\n [formControl]=\"allPermissionsToggle\"\r\n ></mt-toggle-field>\r\n </div>\r\n\r\n <div class=\"flex-1 px-4 overflow-y-auto border-t border-surface\">\r\n <div class=\"space-y-3 my-5\">\r\n @if (selectedTab() === \"roles\") {\r\n @for (group of permissions(); track group.name) {\r\n <div\r\n class=\"p-2 border-1 border-surface rounded-lg flex items-center justify-between hover:bg-surface-100 transition-colors\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'editor.dotpoints-02'\"\r\n shape=\"square\"\r\n size=\"normal\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n 'var(--p-' + 'primary' + '-600)'\r\n \"\r\n >\r\n </mt-avatar>\r\n <span class=\"text-sm\">{{ group.name }}</span>\r\n </div>\r\n <mt-button\r\n [text]=\"true\"\r\n icon=\"custom.pencil\"\r\n severity=\"primary\"\r\n (click)=\"openPermissionDialog(group)\"\r\n >\r\n </mt-button>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noPermissionsFound\" | transloco }}\r\n </div>\r\n }\r\n } @else {\r\n @for (group of groupPermissions(); track group.levelName) {\r\n <div class=\"flex flex-col justify-between gap-3\">\r\n @for (log of group.logs; track log.name) {\r\n <div\r\n class=\"p-2 border-1 border-surface rounded-lg flex items-center justify-between hover:bg-surface-100 transition-colors\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'editor.dotpoints-02'\"\r\n shape=\"square\"\r\n size=\"normal\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n 'var(--p-' + 'primary' + '-600)'\r\n \"\r\n >\r\n </mt-avatar>\r\n <span class=\"text-sm\">{{ log.name }}</span>\r\n </div>\r\n <mt-button\r\n [text]=\"true\"\r\n icon=\"custom.pencil\"\r\n severity=\"primary\"\r\n (click)=\"openPermissionDialog(log)\"\r\n >\r\n </mt-button>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{\r\n \"permissions.noPermissionsFoundForSelectedGroup\"\r\n | transloco\r\n }}\r\n </div>\r\n }\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noPermissionsFound\" | transloco }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
865
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PermissionsPage, isStandalone: true, selector: "mt-permissions-page", ngImport: i0, template: "<div id=\"permissions-page-card\" class=\"flex gap-4 p-1\">\r\n <div class=\"w-1/5 flex-shrink-0\">\r\n <mt-card class=\"h-full flex flex-col\">\r\n <ng-template #headless>\r\n <div class=\"flex flex-col h-full\">\r\n <div\r\n class=\"p-4 pb-0 bg-surface-50 rounded-t-2xl border-b border-surface\"\r\n >\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{ \"permissions.rolesAndGroups\" | transloco }}\r\n </h2>\r\n\r\n <mt-tabs\r\n [(active)]=\"selectedTab\"\r\n [options]=\"tabsList()\"\r\n size=\"large\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"flex-1 overflow-y-auto p-4\">\r\n @if (loading()) {\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n } @else {\r\n @if (selectedTab() === \"roles\") {\r\n @for (level of levelRoles(); track level) {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n <h2 class=\"font-semibold\">{{ level?.level?.display }}</h2>\r\n @for (role of level.roles; track role.value) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedRole() === role.value\"\r\n [class.hover:bg-surface]=\"selectedRole() !== role.value\"\r\n [class.border-primary-400]=\"\r\n selectedRole() === role.value\r\n \"\r\n [style.--p-avatar-background]=\"\r\n selectedRole() === role.value\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedRole() === role.value ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectRole(role.value)\"\r\n >\r\n <mt-avatar [icon]=\"'user.user-check-01'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">\r\n {{ role.name?.display }}\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noRolesFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noLevelRolesFound\" | transloco }}\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n @for (group of groups(); track group.name) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedGroup() === group.id\"\r\n [class.hover:bg-surface]=\"selectedGroup() !== group.id\"\r\n [class.border-primary-400]=\"selectedGroup() === group.id\"\r\n [style.--p-avatar-background]=\"\r\n selectedGroup() === group.id\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedGroup() === group.id ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectGroup(group.id)\"\r\n >\r\n <mt-avatar [icon]=\"'user.users-check'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">\r\n {{ group.name?.display }}\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noGroupsFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n </div>\r\n\r\n <div class=\"min-w-0 w-1/2\">\r\n @if (!selectedRole() && !selectedGroup()) {\r\n <mt-card class=\"h-full\">\r\n <ng-template #headless>\r\n <div class=\"flex items-center justify-center h-full text-muted-color\">\r\n {{ \"permissions.selectRoleOrGroupToViewPermissions\" | transloco }}\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n } @else {\r\n <mt-card class=\"h-full\">\r\n <div class=\"flex flex-col h-full\">\r\n <ng-template #headless>\r\n <div class=\"p-4 pb-2 mb-5 border-b border-surface\">\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{ \"permissions.permissions\" | transloco }}\r\n </h2>\r\n </div>\r\n @if (permissionsLoading()) {\r\n <div class=\"mx-4\">\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"mb-5 p-3 mx-4 rounded-lg border-1 border-surface flex items-center justify-between\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'security.lock-unlocked-01'\"\r\n shape=\"square\"\r\n size=\"large\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"'var(--p-' + 'primary' + '-600)'\"\r\n >\r\n </mt-avatar>\r\n <div>\r\n <div class=\"text-sm font-semibold\">\r\n {{ \"permissions.setAllPermissions\" | transloco }}\r\n </div>\r\n <div class=\"text-xs text-muted-color\">\r\n {{ \"permissions.recommendedForSimpleForms\" | transloco }}\r\n </div>\r\n </div>\r\n </div>\r\n <mt-toggle-field\r\n [formControl]=\"allPermissionsToggle\"\r\n ></mt-toggle-field>\r\n </div>\r\n\r\n <div class=\"flex-1 px-4 overflow-y-auto border-t border-surface\">\r\n <div class=\"space-y-3 my-5\">\r\n @for (group of permissions(); track group.name) {\r\n <div\r\n class=\"p-2 border-1 border-surface rounded-lg flex items-center justify-between hover:bg-surface-100 transition-colors\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'editor.dotpoints-02'\"\r\n shape=\"square\"\r\n size=\"normal\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n 'var(--p-' + 'primary' + '-600)'\r\n \"\r\n >\r\n </mt-avatar>\r\n <span class=\"text-sm\">{{ group.name?.display }}</span>\r\n </div>\r\n <mt-button\r\n [text]=\"true\"\r\n icon=\"custom.pencil\"\r\n severity=\"primary\"\r\n (click)=\"openPermissionDialog(group)\"\r\n >\r\n </mt-button>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noPermissionsFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
948
866
  }
949
867
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PermissionsPage, decorators: [{
950
868
  type: Component,
@@ -958,7 +876,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
958
876
  Avatar,
959
877
  SkeletonModule,
960
878
  Tabs,
961
- ], template: "<div id=\"permissions-page-card\" class=\"flex gap-4 p-1\">\r\n <div class=\"w-1/5 flex-shrink-0\">\r\n <mt-card class=\"h-full flex flex-col\">\r\n <ng-template #headless>\r\n <div class=\"flex flex-col h-full\">\r\n <div\r\n class=\"p-4 pb-0 bg-surface-50 rounded-t-2xl border-b border-surface\"\r\n >\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{ \"permissions.rolesAndGroups\" | transloco }}\r\n </h2>\r\n\r\n <mt-tabs\r\n [(active)]=\"selectedTab\"\r\n [options]=\"tabsList()\"\r\n size=\"large\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"flex-1 overflow-y-auto p-4\">\r\n @if (loading()) {\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n } @else {\r\n @if (selectedTab() === \"roles\") {\r\n @for (level of levelRoles(); track level.levelKey) {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n <h2 class=\"font-semibold\">{{ level.level }}</h2>\r\n @for (role of level.roles; track role.value) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedRole() === role.value\"\r\n [class.hover:bg-surface]=\"selectedRole() !== role.value\"\r\n [class.border-primary-400]=\"\r\n selectedRole() === role.value\r\n \"\r\n [style.--p-avatar-background]=\"\r\n selectedRole() === role.value\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedRole() === role.value ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectRole(role.value)\"\r\n >\r\n <mt-avatar [icon]=\"'user.user-check-01'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">\r\n {{ role.name }}\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noRolesFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noLevelRolesFound\" | transloco }}\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n @for (group of groups(); track group.name) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedGroup() === group.id\"\r\n [class.hover:bg-surface]=\"selectedGroup() !== group.id\"\r\n [class.border-primary-400]=\"selectedGroup() === group.id\"\r\n [style.--p-avatar-background]=\"\r\n selectedGroup() === group.id\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedGroup() === group.id ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectGroup(group.id)\"\r\n >\r\n <mt-avatar [icon]=\"'user.users-check'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">{{ group.name }}</div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noGroupsFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n </div>\r\n\r\n <div class=\"min-w-0 w-1/2\">\r\n @if (!selectedRole() && !selectedGroup()) {\r\n <mt-card class=\"h-full\">\r\n <ng-template #headless>\r\n <div class=\"flex items-center justify-center h-full text-muted-color\">\r\n {{ \"permissions.selectRoleToViewPermissions\" | transloco }}\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n } @else {\r\n <mt-card class=\"h-full\">\r\n <div class=\"flex flex-col h-full\">\r\n <ng-template #headless>\r\n <div class=\"p-4 pb-2 mb-5 border-b border-surface\">\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{\r\n (selectedTab() === \"roles\"\r\n ? \"permissions.levelPermissions\"\r\n : \"permissions.groupsPermissions\"\r\n ) | transloco\r\n }}\r\n </h2>\r\n </div>\r\n @if (permissionsLoading()) {\r\n <div class=\"mx-4\">\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"mb-5 p-3 mx-4 rounded-lg border-1 border-surface flex items-center justify-between\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'security.lock-unlocked-01'\"\r\n shape=\"square\"\r\n size=\"large\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"'var(--p-' + 'primary' + '-600)'\"\r\n >\r\n </mt-avatar>\r\n <div>\r\n <div class=\"text-sm font-semibold\">\r\n {{\r\n (selectedTab() === \"roles\"\r\n ? \"permissions.setAllProjectPermissions\"\r\n : \"permissions.setAllGroupPermissions\"\r\n ) | transloco\r\n }}\r\n </div>\r\n <div class=\"text-xs text-muted-color\">\r\n {{ \"permissions.recommendedForSimpleForms\" | transloco }}\r\n </div>\r\n </div>\r\n </div>\r\n <mt-toggle-field\r\n [formControl]=\"allPermissionsToggle\"\r\n ></mt-toggle-field>\r\n </div>\r\n\r\n <div class=\"flex-1 px-4 overflow-y-auto border-t border-surface\">\r\n <div class=\"space-y-3 my-5\">\r\n @if (selectedTab() === \"roles\") {\r\n @for (group of permissions(); track group.name) {\r\n <div\r\n class=\"p-2 border-1 border-surface rounded-lg flex items-center justify-between hover:bg-surface-100 transition-colors\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'editor.dotpoints-02'\"\r\n shape=\"square\"\r\n size=\"normal\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n 'var(--p-' + 'primary' + '-600)'\r\n \"\r\n >\r\n </mt-avatar>\r\n <span class=\"text-sm\">{{ group.name }}</span>\r\n </div>\r\n <mt-button\r\n [text]=\"true\"\r\n icon=\"custom.pencil\"\r\n severity=\"primary\"\r\n (click)=\"openPermissionDialog(group)\"\r\n >\r\n </mt-button>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noPermissionsFound\" | transloco }}\r\n </div>\r\n }\r\n } @else {\r\n @for (group of groupPermissions(); track group.levelName) {\r\n <div class=\"flex flex-col justify-between gap-3\">\r\n @for (log of group.logs; track log.name) {\r\n <div\r\n class=\"p-2 border-1 border-surface rounded-lg flex items-center justify-between hover:bg-surface-100 transition-colors\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'editor.dotpoints-02'\"\r\n shape=\"square\"\r\n size=\"normal\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n 'var(--p-' + 'primary' + '-600)'\r\n \"\r\n >\r\n </mt-avatar>\r\n <span class=\"text-sm\">{{ log.name }}</span>\r\n </div>\r\n <mt-button\r\n [text]=\"true\"\r\n icon=\"custom.pencil\"\r\n severity=\"primary\"\r\n (click)=\"openPermissionDialog(log)\"\r\n >\r\n </mt-button>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{\r\n \"permissions.noPermissionsFoundForSelectedGroup\"\r\n | transloco\r\n }}\r\n </div>\r\n }\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noPermissionsFound\" | transloco }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n</div>\r\n" }]
879
+ ], template: "<div id=\"permissions-page-card\" class=\"flex gap-4 p-1\">\r\n <div class=\"w-1/5 flex-shrink-0\">\r\n <mt-card class=\"h-full flex flex-col\">\r\n <ng-template #headless>\r\n <div class=\"flex flex-col h-full\">\r\n <div\r\n class=\"p-4 pb-0 bg-surface-50 rounded-t-2xl border-b border-surface\"\r\n >\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{ \"permissions.rolesAndGroups\" | transloco }}\r\n </h2>\r\n\r\n <mt-tabs\r\n [(active)]=\"selectedTab\"\r\n [options]=\"tabsList()\"\r\n size=\"large\"\r\n (onChange)=\"onTabChange($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"flex-1 overflow-y-auto p-4\">\r\n @if (loading()) {\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n } @else {\r\n @if (selectedTab() === \"roles\") {\r\n @for (level of levelRoles(); track level) {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n <h2 class=\"font-semibold\">{{ level?.level?.display }}</h2>\r\n @for (role of level.roles; track role.value) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedRole() === role.value\"\r\n [class.hover:bg-surface]=\"selectedRole() !== role.value\"\r\n [class.border-primary-400]=\"\r\n selectedRole() === role.value\r\n \"\r\n [style.--p-avatar-background]=\"\r\n selectedRole() === role.value\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedRole() === role.value ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectRole(role.value)\"\r\n >\r\n <mt-avatar [icon]=\"'user.user-check-01'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">\r\n {{ role.name?.display }}\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noRolesFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noLevelRolesFound\" | transloco }}\r\n </div>\r\n }\r\n } @else {\r\n <div class=\"flex flex-col gap-2 mb-4\">\r\n @for (group of groups(); track group.name) {\r\n <div\r\n class=\"p-3 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer transition-colors flex items-center gap-3\"\r\n [class.bg-primary-50]=\"selectedGroup() === group.id\"\r\n [class.hover:bg-surface]=\"selectedGroup() !== group.id\"\r\n [class.border-primary-400]=\"selectedGroup() === group.id\"\r\n [style.--p-avatar-background]=\"\r\n selectedGroup() === group.id\r\n ? 'var(--p-primary-color)'\r\n : 'var(--p-surface-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n selectedGroup() === group.id ? '#ffffff' : ''\r\n \"\r\n (click)=\"selectGroup(group.id)\"\r\n >\r\n <mt-avatar [icon]=\"'user.users-check'\" shape=\"square\">\r\n </mt-avatar>\r\n <div class=\"flex-1 min-w-0\">\r\n <div class=\"font-medium truncate\">\r\n {{ group.name?.display }}\r\n </div>\r\n </div>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noGroupsFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n </div>\r\n\r\n <div class=\"min-w-0 w-1/2\">\r\n @if (!selectedRole() && !selectedGroup()) {\r\n <mt-card class=\"h-full\">\r\n <ng-template #headless>\r\n <div class=\"flex items-center justify-center h-full text-muted-color\">\r\n {{ \"permissions.selectRoleOrGroupToViewPermissions\" | transloco }}\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n } @else {\r\n <mt-card class=\"h-full\">\r\n <div class=\"flex flex-col h-full\">\r\n <ng-template #headless>\r\n <div class=\"p-4 pb-2 mb-5 border-b border-surface\">\r\n <h2 class=\"text-lg font-semibold mb-3\">\r\n {{ \"permissions.permissions\" | transloco }}\r\n </h2>\r\n </div>\r\n @if (permissionsLoading()) {\r\n <div class=\"mx-4\">\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n <p-skeleton class=\"my-4\" height=\"4rem\" />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"mb-5 p-3 mx-4 rounded-lg border-1 border-surface flex items-center justify-between\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'security.lock-unlocked-01'\"\r\n shape=\"square\"\r\n size=\"large\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"'var(--p-' + 'primary' + '-600)'\"\r\n >\r\n </mt-avatar>\r\n <div>\r\n <div class=\"text-sm font-semibold\">\r\n {{ \"permissions.setAllPermissions\" | transloco }}\r\n </div>\r\n <div class=\"text-xs text-muted-color\">\r\n {{ \"permissions.recommendedForSimpleForms\" | transloco }}\r\n </div>\r\n </div>\r\n </div>\r\n <mt-toggle-field\r\n [formControl]=\"allPermissionsToggle\"\r\n ></mt-toggle-field>\r\n </div>\r\n\r\n <div class=\"flex-1 px-4 overflow-y-auto border-t border-surface\">\r\n <div class=\"space-y-3 my-5\">\r\n @for (group of permissions(); track group.name) {\r\n <div\r\n class=\"p-2 border-1 border-surface rounded-lg flex items-center justify-between hover:bg-surface-100 transition-colors\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-avatar\r\n [icon]=\"'editor.dotpoints-02'\"\r\n shape=\"square\"\r\n size=\"normal\"\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + 'surface' + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"\r\n 'var(--p-' + 'primary' + '-600)'\r\n \"\r\n >\r\n </mt-avatar>\r\n <span class=\"text-sm\">{{ group.name?.display }}</span>\r\n </div>\r\n <mt-button\r\n [text]=\"true\"\r\n icon=\"custom.pencil\"\r\n severity=\"primary\"\r\n (click)=\"openPermissionDialog(group)\"\r\n >\r\n </mt-button>\r\n </div>\r\n } @empty {\r\n <div\r\n class=\"flex items-center justify-center h-full text-muted-color\"\r\n >\r\n {{ \"permissions.noPermissionsFound\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n</div>\r\n" }]
962
880
  }], ctorParameters: () => [] });
963
881
 
964
882
  // store/index.ts
@@ -967,5 +885,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
967
885
  * Generated bundle index. Do not edit.
968
886
  */
969
887
 
970
- export { LoadGroupPermissions, LoadGroupPermissionsSuccess, LoadPermissions, LoadPermissionsFail, LoadPermissionsSuccess, LoadRoles, LoadRolesFail, LoadRolesSuccess, ModuleType, PermissionsEditDialog, PermissionsFacade, PermissionsPage, PermissionsState, Reset, SelectGroup, SelectRole, SetModuleInfo, ToggleAllGroupPermissions, ToggleAllLevelPermissions, UpdateGroupPermission, UpdateGroupPermissionLocally, UpdatePermission, UpdatePermissionFail, UpdatePermissionLocally, UpdatePermissionSuccess };
888
+ export { LoadGroupPermissions, LoadPermissions, LoadRoles, ModuleType, PermissionsActionKey, PermissionsEditDialog, PermissionsFacade, PermissionsPage, PermissionsState, Reset, SelectGroup, SelectRole, SetModuleInfo, ToggleAllGroupPermissions, ToggleAllLevelPermissions, UpdateGroupPermission, UpdatePermission, UpdatePermissionLocally };
971
889
  //# sourceMappingURL=masterteam-permissions.mjs.map