@memberjunction/ng-explorer-settings 2.49.0 → 2.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +89 -1
  2. package/dist/lib/application-management/application-management.component.d.ts +59 -0
  3. package/dist/lib/application-management/application-management.component.d.ts.map +1 -0
  4. package/dist/lib/application-management/application-management.component.js +540 -0
  5. package/dist/lib/application-management/application-management.component.js.map +1 -0
  6. package/dist/lib/entity-permissions/entity-permissions.component.d.ts +71 -0
  7. package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -0
  8. package/dist/lib/entity-permissions/entity-permissions.component.js +667 -0
  9. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -0
  10. package/dist/lib/module.d.ts +19 -23
  11. package/dist/lib/module.d.ts.map +1 -1
  12. package/dist/lib/module.js +13 -38
  13. package/dist/lib/module.js.map +1 -1
  14. package/dist/lib/role-management/role-management.component.d.ts +56 -0
  15. package/dist/lib/role-management/role-management.component.d.ts.map +1 -0
  16. package/dist/lib/role-management/role-management.component.js +464 -0
  17. package/dist/lib/role-management/role-management.component.js.map +1 -0
  18. package/dist/lib/settings/settings.component.d.ts +42 -51
  19. package/dist/lib/settings/settings.component.d.ts.map +1 -1
  20. package/dist/lib/settings/settings.component.js +432 -198
  21. package/dist/lib/settings/settings.component.js.map +1 -1
  22. package/dist/lib/shared/components/settings-card/settings-card.component.d.ts +27 -0
  23. package/dist/lib/shared/components/settings-card/settings-card.component.d.ts.map +1 -0
  24. package/dist/lib/shared/components/settings-card/settings-card.component.js +167 -0
  25. package/dist/lib/shared/components/settings-card/settings-card.component.js.map +1 -0
  26. package/dist/lib/shared/settings-card.component.d.ts +11 -0
  27. package/dist/lib/shared/settings-card.component.d.ts.map +1 -0
  28. package/dist/lib/shared/settings-card.component.js +73 -0
  29. package/dist/lib/shared/settings-card.component.js.map +1 -0
  30. package/dist/lib/shared/shared-settings.module.d.ts +9 -0
  31. package/dist/lib/shared/shared-settings.module.d.ts.map +1 -0
  32. package/dist/lib/shared/shared-settings.module.js +25 -0
  33. package/dist/lib/shared/shared-settings.module.js.map +1 -0
  34. package/dist/lib/sql-logging/sql-logging.component.d.ts +176 -0
  35. package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -0
  36. package/dist/lib/sql-logging/sql-logging.component.js +946 -0
  37. package/dist/lib/sql-logging/sql-logging.component.js.map +1 -0
  38. package/dist/lib/user-management/user-management.component.d.ts +65 -0
  39. package/dist/lib/user-management/user-management.component.d.ts.map +1 -0
  40. package/dist/lib/user-management/user-management.component.js +643 -0
  41. package/dist/lib/user-management/user-management.component.js.map +1 -0
  42. package/dist/public-api.d.ts +1 -5
  43. package/dist/public-api.d.ts.map +1 -1
  44. package/dist/public-api.js +1 -5
  45. package/dist/public-api.js.map +1 -1
  46. package/package.json +13 -13
  47. package/dist/lib/application-entities-grid/application-entities-grid.component.d.ts +0 -50
  48. package/dist/lib/application-entities-grid/application-entities-grid.component.d.ts.map +0 -1
  49. package/dist/lib/application-entities-grid/application-entities-grid.component.js +0 -342
  50. package/dist/lib/application-entities-grid/application-entities-grid.component.js.map +0 -1
  51. package/dist/lib/single-application/single-application.component.d.ts +0 -22
  52. package/dist/lib/single-application/single-application.component.d.ts.map +0 -1
  53. package/dist/lib/single-application/single-application.component.js +0 -130
  54. package/dist/lib/single-application/single-application.component.js.map +0 -1
  55. package/dist/lib/single-role/single-role.component.d.ts +0 -36
  56. package/dist/lib/single-role/single-role.component.d.ts.map +0 -1
  57. package/dist/lib/single-role/single-role.component.js +0 -188
  58. package/dist/lib/single-role/single-role.component.js.map +0 -1
  59. package/dist/lib/single-user/single-user.component.d.ts +0 -24
  60. package/dist/lib/single-user/single-user.component.d.ts.map +0 -1
  61. package/dist/lib/single-user/single-user.component.js +0 -176
  62. package/dist/lib/single-user/single-user.component.js.map +0 -1
  63. package/dist/lib/user-roles-grid/user-roles-grid.component.d.ts +0 -42
  64. package/dist/lib/user-roles-grid/user-roles-grid.component.d.ts.map +0 -1
  65. package/dist/lib/user-roles-grid/user-roles-grid.component.js +0 -326
  66. package/dist/lib/user-roles-grid/user-roles-grid.component.js.map +0 -1
@@ -0,0 +1,667 @@
1
+ import { Component } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { Subject, BehaviorSubject } from 'rxjs';
5
+ import { takeUntil, debounceTime, distinctUntilChanged } from 'rxjs/operators';
6
+ import { RunView, Metadata } from '@memberjunction/core';
7
+ import { SharedSettingsModule } from '../shared/shared-settings.module';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/forms";
10
+ const _forTrack0 = ($index, $item) => $item.ID;
11
+ const _forTrack1 = ($index, $item) => $item.entity.ID;
12
+ function EntityPermissionsComponent_For_67_Template(rf, ctx) { if (rf & 1) {
13
+ i0.ɵɵelementStart(0, "option", 33);
14
+ i0.ɵɵtext(1);
15
+ i0.ɵɵelementEnd();
16
+ } if (rf & 2) {
17
+ const role_r1 = ctx.$implicit;
18
+ i0.ɵɵproperty("value", role_r1.ID);
19
+ i0.ɵɵadvance();
20
+ i0.ɵɵtextInterpolate(role_r1.Name);
21
+ } }
22
+ function EntityPermissionsComponent_Conditional_68_Template(rf, ctx) { if (rf & 1) {
23
+ i0.ɵɵelementStart(0, "div", 34)(1, "div", 38);
24
+ i0.ɵɵelement(2, "div", 39)(3, "div", 39)(4, "div", 39);
25
+ i0.ɵɵelementEnd();
26
+ i0.ɵɵelementStart(5, "div", 40);
27
+ i0.ɵɵtext(6, "Loading entity permissions...");
28
+ i0.ɵɵelementEnd()();
29
+ } }
30
+ function EntityPermissionsComponent_Conditional_69_Template(rf, ctx) { if (rf & 1) {
31
+ const _r2 = i0.ɵɵgetCurrentView();
32
+ i0.ɵɵelementStart(0, "div", 35)(1, "div", 41);
33
+ i0.ɵɵelement(2, "i", 42);
34
+ i0.ɵɵelementStart(3, "p", 43);
35
+ i0.ɵɵtext(4);
36
+ i0.ɵɵelementEnd();
37
+ i0.ɵɵelementStart(5, "button", 44);
38
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_69_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.loadInitialData()); });
39
+ i0.ɵɵelement(6, "i", 8);
40
+ i0.ɵɵtext(7, " Try Again ");
41
+ i0.ɵɵelementEnd()()();
42
+ } if (rf & 2) {
43
+ const ctx_r2 = i0.ɵɵnextContext();
44
+ i0.ɵɵadvance(4);
45
+ i0.ɵɵtextInterpolate(ctx_r2.error);
46
+ } }
47
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_1_For_13_Template(rf, ctx) { if (rf & 1) {
48
+ i0.ɵɵelementStart(0, "div", 69)(1, "span", 70);
49
+ i0.ɵɵtext(2);
50
+ i0.ɵɵelementEnd();
51
+ i0.ɵɵelementStart(3, "span", 71);
52
+ i0.ɵɵelement(4, "i");
53
+ i0.ɵɵelementEnd();
54
+ i0.ɵɵelementStart(5, "span", 71);
55
+ i0.ɵɵelement(6, "i");
56
+ i0.ɵɵelementEnd();
57
+ i0.ɵɵelementStart(7, "span", 71);
58
+ i0.ɵɵelement(8, "i");
59
+ i0.ɵɵelementEnd();
60
+ i0.ɵɵelementStart(9, "span", 71);
61
+ i0.ɵɵelement(10, "i");
62
+ i0.ɵɵelementEnd()();
63
+ } if (rf & 2) {
64
+ const roleId_r6 = ctx.$implicit;
65
+ const ea_r5 = i0.ɵɵnextContext(3).$implicit;
66
+ const ctx_r2 = i0.ɵɵnextContext(3);
67
+ i0.ɵɵadvance(2);
68
+ i0.ɵɵtextInterpolate(ctx_r2.getRoleName(roleId_r6));
69
+ i0.ɵɵadvance(2);
70
+ i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r6, "canCreate") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
71
+ i0.ɵɵadvance(2);
72
+ i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r6, "canRead") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
73
+ i0.ɵɵadvance(2);
74
+ i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r6, "canUpdate") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
75
+ i0.ɵɵadvance(2);
76
+ i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r6, "canDelete") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
77
+ } }
78
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_1_Template(rf, ctx) { if (rf & 1) {
79
+ i0.ɵɵelementStart(0, "div", 64)(1, "div", 66)(2, "span", 67);
80
+ i0.ɵɵtext(3, "Role");
81
+ i0.ɵɵelementEnd();
82
+ i0.ɵɵelementStart(4, "span", 68);
83
+ i0.ɵɵtext(5, "Create");
84
+ i0.ɵɵelementEnd();
85
+ i0.ɵɵelementStart(6, "span", 68);
86
+ i0.ɵɵtext(7, "Read");
87
+ i0.ɵɵelementEnd();
88
+ i0.ɵɵelementStart(8, "span", 68);
89
+ i0.ɵɵtext(9, "Update");
90
+ i0.ɵɵelementEnd();
91
+ i0.ɵɵelementStart(10, "span", 68);
92
+ i0.ɵɵtext(11, "Delete");
93
+ i0.ɵɵelementEnd()();
94
+ i0.ɵɵrepeaterCreate(12, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_1_For_13_Template, 11, 9, "div", 69, i0.ɵɵrepeaterTrackByIdentity);
95
+ i0.ɵɵelementEnd();
96
+ } if (rf & 2) {
97
+ const ea_r5 = i0.ɵɵnextContext(2).$implicit;
98
+ i0.ɵɵadvance(12);
99
+ i0.ɵɵrepeater(ea_r5.rolePermissions.keys());
100
+ } }
101
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
102
+ i0.ɵɵtext(0, " This entity is publicly accessible by all users. ");
103
+ } }
104
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
105
+ i0.ɵɵtext(0, " No specific role permissions configured. Access is restricted to system administrators. ");
106
+ } }
107
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_2_Template(rf, ctx) { if (rf & 1) {
108
+ i0.ɵɵelementStart(0, "p", 65);
109
+ i0.ɵɵtemplate(1, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_2_Conditional_1_Template, 1, 0)(2, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_2_Conditional_2_Template, 1, 0);
110
+ i0.ɵɵelementEnd();
111
+ } if (rf & 2) {
112
+ const ea_r5 = i0.ɵɵnextContext(2).$implicit;
113
+ i0.ɵɵadvance();
114
+ i0.ɵɵconditional(ea_r5.isPublic ? 1 : 2);
115
+ } }
116
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Template(rf, ctx) { if (rf & 1) {
117
+ i0.ɵɵelementStart(0, "div", 63);
118
+ i0.ɵɵtemplate(1, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_1_Template, 14, 0, "div", 64)(2, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_2_Template, 3, 1, "p", 65);
119
+ i0.ɵɵelementEnd();
120
+ } if (rf & 2) {
121
+ const ea_r5 = i0.ɵɵnextContext().$implicit;
122
+ i0.ɵɵadvance();
123
+ i0.ɵɵconditional(ea_r5.permissions.length > 0 ? 1 : 2);
124
+ } }
125
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
126
+ const _r4 = i0.ɵɵgetCurrentView();
127
+ i0.ɵɵelementStart(0, "div", 49)(1, "div", 50);
128
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Template_div_click_1_listener() { const ea_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.toggleEntityExpansion(ea_r5.entity.ID)); });
129
+ i0.ɵɵelementStart(2, "div", 51)(3, "div", 52);
130
+ i0.ɵɵelement(4, "i", 53);
131
+ i0.ɵɵelementEnd();
132
+ i0.ɵɵelementStart(5, "div", 54)(6, "h3", 55);
133
+ i0.ɵɵtext(7);
134
+ i0.ɵɵelementEnd();
135
+ i0.ɵɵelementStart(8, "p", 56);
136
+ i0.ɵɵtext(9);
137
+ i0.ɵɵelementEnd()()();
138
+ i0.ɵɵelementStart(10, "div", 57)(11, "span", 58);
139
+ i0.ɵɵelement(12, "i");
140
+ i0.ɵɵtext(13);
141
+ i0.ɵɵelementEnd();
142
+ i0.ɵɵelementStart(14, "button", 59);
143
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Template_button_click_14_listener($event) { const ea_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); ctx_r2.editEntityPermissions(ea_r5); return i0.ɵɵresetView($event.stopPropagation()); });
144
+ i0.ɵɵelement(15, "i", 60);
145
+ i0.ɵɵelementEnd();
146
+ i0.ɵɵelementStart(16, "button", 61);
147
+ i0.ɵɵelement(17, "i", 62);
148
+ i0.ɵɵelementEnd()()();
149
+ i0.ɵɵtemplate(18, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Template, 3, 1, "div", 63);
150
+ i0.ɵɵelementEnd();
151
+ } if (rf & 2) {
152
+ const ea_r5 = ctx.$implicit;
153
+ const ctx_r2 = i0.ɵɵnextContext(3);
154
+ i0.ɵɵclassProp("expanded", ctx_r2.isEntityExpanded(ea_r5.entity.ID));
155
+ i0.ɵɵadvance(7);
156
+ i0.ɵɵtextInterpolate(ea_r5.entity.Name);
157
+ i0.ɵɵadvance(2);
158
+ i0.ɵɵtextInterpolate(ea_r5.entity.Description || "No description available");
159
+ i0.ɵɵadvance(2);
160
+ i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r5));
161
+ i0.ɵɵadvance();
162
+ i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r5) === "access-public" ? "fa-solid fa-globe" : ctx_r2.getAccessLevelClass(ea_r5) === "access-restricted" ? "fa-solid fa-lock" : "fa-solid fa-key");
163
+ i0.ɵɵadvance();
164
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getAccessLevelLabel(ea_r5), " ");
165
+ i0.ɵɵadvance(5);
166
+ i0.ɵɵconditional(ctx_r2.isEntityExpanded(ea_r5.entity.ID) ? 18 : -1);
167
+ } }
168
+ function EntityPermissionsComponent_Conditional_70_Conditional_1_Template(rf, ctx) { if (rf & 1) {
169
+ i0.ɵɵelementStart(0, "div", 45);
170
+ i0.ɵɵrepeaterCreate(1, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Template, 19, 10, "div", 48, _forTrack1);
171
+ i0.ɵɵelementEnd();
172
+ } if (rf & 2) {
173
+ const ctx_r2 = i0.ɵɵnextContext(2);
174
+ i0.ɵɵadvance();
175
+ i0.ɵɵrepeater(ctx_r2.filteredEntityAccess);
176
+ } }
177
+ function EntityPermissionsComponent_Conditional_70_Conditional_2_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
178
+ i0.ɵɵelementStart(0, "span", 80);
179
+ i0.ɵɵtext(1);
180
+ i0.ɵɵelementEnd();
181
+ } if (rf & 2) {
182
+ const ea_r8 = i0.ɵɵnextContext().$implicit;
183
+ i0.ɵɵadvance();
184
+ i0.ɵɵtextInterpolate2(" ", ea_r8.permissions.length, " permission", ea_r8.permissions.length === 1 ? "" : "s", " ");
185
+ } }
186
+ function EntityPermissionsComponent_Conditional_70_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
187
+ const _r7 = i0.ɵɵgetCurrentView();
188
+ i0.ɵɵelementStart(0, "div", 73)(1, "div", 74);
189
+ i0.ɵɵelement(2, "i", 53);
190
+ i0.ɵɵelementStart(3, "button", 75);
191
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_70_Conditional_2_For_2_Template_button_click_3_listener() { const ea_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editEntityPermissions(ea_r8)); });
192
+ i0.ɵɵelement(4, "i", 60);
193
+ i0.ɵɵelementEnd()();
194
+ i0.ɵɵelementStart(5, "h4", 76);
195
+ i0.ɵɵtext(6);
196
+ i0.ɵɵelementEnd();
197
+ i0.ɵɵelementStart(7, "p", 77);
198
+ i0.ɵɵtext(8);
199
+ i0.ɵɵelementEnd();
200
+ i0.ɵɵelementStart(9, "div", 78)(10, "span", 79);
201
+ i0.ɵɵelement(11, "i");
202
+ i0.ɵɵtext(12);
203
+ i0.ɵɵelementEnd();
204
+ i0.ɵɵtemplate(13, EntityPermissionsComponent_Conditional_70_Conditional_2_For_2_Conditional_13_Template, 2, 2, "span", 80);
205
+ i0.ɵɵelementEnd()();
206
+ } if (rf & 2) {
207
+ const ea_r8 = ctx.$implicit;
208
+ const ctx_r2 = i0.ɵɵnextContext(3);
209
+ i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r8));
210
+ i0.ɵɵadvance(6);
211
+ i0.ɵɵtextInterpolate(ea_r8.entity.Name);
212
+ i0.ɵɵadvance(2);
213
+ i0.ɵɵtextInterpolate(ea_r8.entity.Description || "No description");
214
+ i0.ɵɵadvance(3);
215
+ i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r8) === "access-public" ? "fa-solid fa-globe" : ctx_r2.getAccessLevelClass(ea_r8) === "access-restricted" ? "fa-solid fa-lock" : "fa-solid fa-key");
216
+ i0.ɵɵadvance();
217
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getAccessLevelLabel(ea_r8), " ");
218
+ i0.ɵɵadvance();
219
+ i0.ɵɵconditional(ea_r8.permissions.length > 0 ? 13 : -1);
220
+ } }
221
+ function EntityPermissionsComponent_Conditional_70_Conditional_2_Template(rf, ctx) { if (rf & 1) {
222
+ i0.ɵɵelementStart(0, "div", 46);
223
+ i0.ɵɵrepeaterCreate(1, EntityPermissionsComponent_Conditional_70_Conditional_2_For_2_Template, 14, 8, "div", 72, _forTrack1);
224
+ i0.ɵɵelementEnd();
225
+ } if (rf & 2) {
226
+ const ctx_r2 = i0.ɵɵnextContext(2);
227
+ i0.ɵɵadvance();
228
+ i0.ɵɵrepeater(ctx_r2.filteredEntityAccess);
229
+ } }
230
+ function EntityPermissionsComponent_Conditional_70_Conditional_3_Template(rf, ctx) { if (rf & 1) {
231
+ i0.ɵɵelementStart(0, "div", 47);
232
+ i0.ɵɵelement(1, "i", 81);
233
+ i0.ɵɵelementStart(2, "p", 82);
234
+ i0.ɵɵtext(3, "No entities found");
235
+ i0.ɵɵelementEnd();
236
+ i0.ɵɵelementStart(4, "p", 83);
237
+ i0.ɵɵtext(5, "Try adjusting your filters to see more results");
238
+ i0.ɵɵelementEnd()();
239
+ } }
240
+ function EntityPermissionsComponent_Conditional_70_Template(rf, ctx) { if (rf & 1) {
241
+ i0.ɵɵelementStart(0, "div", 36);
242
+ i0.ɵɵtemplate(1, EntityPermissionsComponent_Conditional_70_Conditional_1_Template, 3, 0, "div", 45)(2, EntityPermissionsComponent_Conditional_70_Conditional_2_Template, 3, 0, "div", 46)(3, EntityPermissionsComponent_Conditional_70_Conditional_3_Template, 6, 0, "div", 47);
243
+ i0.ɵɵelementEnd();
244
+ } if (rf & 2) {
245
+ const ctx_r2 = i0.ɵɵnextContext();
246
+ i0.ɵɵadvance();
247
+ i0.ɵɵconditional(ctx_r2.viewMode === "list" ? 1 : 2);
248
+ i0.ɵɵadvance(2);
249
+ i0.ɵɵconditional(ctx_r2.filteredEntityAccess.length === 0 ? 3 : -1);
250
+ } }
251
+ function EntityPermissionsComponent_Conditional_71_Template(rf, ctx) { if (rf & 1) {
252
+ const _r9 = i0.ɵɵgetCurrentView();
253
+ i0.ɵɵelementStart(0, "div", 84);
254
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_71_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showPermissionDialog = false); });
255
+ i0.ɵɵelementStart(1, "div", 85);
256
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_71_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r9); return i0.ɵɵresetView($event.stopPropagation()); });
257
+ i0.ɵɵelementStart(2, "div", 86)(3, "h3", 87);
258
+ i0.ɵɵelement(4, "i", 21);
259
+ i0.ɵɵtext(5);
260
+ i0.ɵɵelementEnd();
261
+ i0.ɵɵelementStart(6, "button", 88);
262
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_71_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showPermissionDialog = false); });
263
+ i0.ɵɵelement(7, "i", 89);
264
+ i0.ɵɵelementEnd()();
265
+ i0.ɵɵelementStart(8, "div", 90)(9, "p", 91);
266
+ i0.ɵɵtext(10, " Configure role-based permissions for this entity. Changes will affect all users with the selected roles. ");
267
+ i0.ɵɵelementEnd();
268
+ i0.ɵɵelementStart(11, "div", 92)(12, "p", 93);
269
+ i0.ɵɵelement(13, "i", 94);
270
+ i0.ɵɵtext(14, " Permission editing interface coming soon... ");
271
+ i0.ɵɵelementEnd()()();
272
+ i0.ɵɵelementStart(15, "div", 95)(16, "button", 96);
273
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_71_Template_button_click_16_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showPermissionDialog = false); });
274
+ i0.ɵɵtext(17, "Cancel");
275
+ i0.ɵɵelementEnd();
276
+ i0.ɵɵelementStart(18, "button", 97);
277
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_71_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.savePermissions()); });
278
+ i0.ɵɵelement(19, "i", 98);
279
+ i0.ɵɵtext(20, " Save Permissions ");
280
+ i0.ɵɵelementEnd()()()();
281
+ } if (rf & 2) {
282
+ const ctx_r2 = i0.ɵɵnextContext();
283
+ i0.ɵɵadvance(5);
284
+ i0.ɵɵtextInterpolate1(" Edit Permissions - ", ctx_r2.selectedEntity.entity.Name, " ");
285
+ } }
286
+ export class EntityPermissionsComponent {
287
+ // State management
288
+ entityAccess = [];
289
+ filteredEntityAccess = [];
290
+ roles = [];
291
+ isLoading = false;
292
+ error = null;
293
+ // Selected entity for permission editing
294
+ selectedEntity = null;
295
+ showPermissionDialog = false;
296
+ // Stats
297
+ stats = {
298
+ totalEntities: 0,
299
+ publicEntities: 0,
300
+ restrictedEntities: 0,
301
+ totalPermissions: 0
302
+ };
303
+ // Filters
304
+ filters$ = new BehaviorSubject({
305
+ entitySearch: '',
306
+ accessLevel: 'all',
307
+ roleId: null
308
+ });
309
+ // UI State
310
+ expandedEntityId = null;
311
+ viewMode = 'list';
312
+ destroy$ = new Subject();
313
+ metadata = new Metadata();
314
+ constructor() { }
315
+ ngOnInit() {
316
+ this.loadInitialData();
317
+ this.setupFilterSubscription();
318
+ }
319
+ ngOnDestroy() {
320
+ this.destroy$.next();
321
+ this.destroy$.complete();
322
+ }
323
+ async loadInitialData() {
324
+ try {
325
+ this.isLoading = true;
326
+ this.error = null;
327
+ // Load all required data in parallel
328
+ const [entities, permissions, roles] = await Promise.all([
329
+ this.loadEntities(),
330
+ this.loadEntityPermissions(),
331
+ this.loadRoles()
332
+ ]);
333
+ // Process the data
334
+ this.roles = roles;
335
+ this.processEntityAccess(entities, permissions);
336
+ this.calculateStats();
337
+ this.applyFilters();
338
+ }
339
+ catch (error) {
340
+ console.error('Error loading permissions data:', error);
341
+ this.error = 'Failed to load permissions data. Please try again.';
342
+ }
343
+ finally {
344
+ this.isLoading = false;
345
+ }
346
+ }
347
+ async loadEntities() {
348
+ const rv = new RunView();
349
+ const result = await rv.RunView({
350
+ EntityName: 'Entities',
351
+ ResultType: 'entity_object',
352
+ OrderBy: 'Name ASC'
353
+ });
354
+ return result.Success ? result.Results : [];
355
+ }
356
+ async loadEntityPermissions() {
357
+ const rv = new RunView();
358
+ const result = await rv.RunView({
359
+ EntityName: 'Entity Permissions',
360
+ ResultType: 'entity_object',
361
+ OrderBy: 'EntityID, RoleID'
362
+ });
363
+ return result.Success ? result.Results : [];
364
+ }
365
+ async loadRoles() {
366
+ const rv = new RunView();
367
+ const result = await rv.RunView({
368
+ EntityName: 'Roles',
369
+ ResultType: 'entity_object',
370
+ OrderBy: 'Name ASC'
371
+ });
372
+ return result.Success ? result.Results : [];
373
+ }
374
+ processEntityAccess(entities, permissions) {
375
+ // Group permissions by entity
376
+ const permissionsByEntity = new Map();
377
+ for (const permission of permissions) {
378
+ const entityId = permission.EntityID;
379
+ if (!permissionsByEntity.has(entityId)) {
380
+ permissionsByEntity.set(entityId, []);
381
+ }
382
+ permissionsByEntity.get(entityId).push(permission);
383
+ }
384
+ // Create EntityAccess objects
385
+ this.entityAccess = entities.map(entity => {
386
+ const entityPermissions = permissionsByEntity.get(entity.ID) || [];
387
+ const rolePermissions = new Map();
388
+ // Process permissions by role
389
+ for (const permission of entityPermissions) {
390
+ if (permission.RoleID) {
391
+ rolePermissions.set(permission.RoleID, {
392
+ canCreate: permission.CanCreate || false,
393
+ canRead: permission.CanRead || false,
394
+ canUpdate: permission.CanUpdate || false,
395
+ canDelete: permission.CanDelete || false
396
+ });
397
+ }
398
+ }
399
+ return {
400
+ entity,
401
+ isPublic: entity.AllowAllRowsAPI || false,
402
+ permissions: entityPermissions,
403
+ rolePermissions
404
+ };
405
+ });
406
+ }
407
+ setupFilterSubscription() {
408
+ this.filters$
409
+ .pipe(debounceTime(300), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)), takeUntil(this.destroy$))
410
+ .subscribe(() => {
411
+ this.applyFilters();
412
+ });
413
+ }
414
+ applyFilters() {
415
+ const filters = this.filters$.value;
416
+ let filtered = [...this.entityAccess];
417
+ // Apply entity search
418
+ if (filters.entitySearch) {
419
+ const searchLower = filters.entitySearch.toLowerCase();
420
+ filtered = filtered.filter(ea => ea.entity.Name?.toLowerCase().includes(searchLower) ||
421
+ ea.entity.Description?.toLowerCase().includes(searchLower));
422
+ }
423
+ // Apply access level filter
424
+ switch (filters.accessLevel) {
425
+ case 'public':
426
+ filtered = filtered.filter(ea => ea.isPublic);
427
+ break;
428
+ case 'restricted':
429
+ filtered = filtered.filter(ea => !ea.isPublic && ea.permissions.length === 0);
430
+ break;
431
+ case 'custom':
432
+ filtered = filtered.filter(ea => !ea.isPublic && ea.permissions.length > 0);
433
+ break;
434
+ }
435
+ // Apply role filter
436
+ if (filters.roleId) {
437
+ filtered = filtered.filter(ea => ea.rolePermissions.has(filters.roleId));
438
+ }
439
+ this.filteredEntityAccess = filtered;
440
+ }
441
+ calculateStats() {
442
+ const publicEntities = this.entityAccess.filter(ea => ea.isPublic).length;
443
+ const customPermissions = this.entityAccess.filter(ea => !ea.isPublic && ea.permissions.length > 0).length;
444
+ const totalPermissions = this.entityAccess.reduce((sum, ea) => sum + ea.permissions.length, 0);
445
+ this.stats = {
446
+ totalEntities: this.entityAccess.length,
447
+ publicEntities,
448
+ restrictedEntities: this.entityAccess.length - publicEntities - customPermissions,
449
+ totalPermissions
450
+ };
451
+ }
452
+ // Public methods for template
453
+ onSearchChange(event) {
454
+ const value = event.target.value;
455
+ this.updateFilter({ entitySearch: value });
456
+ }
457
+ onAccessLevelChange(level) {
458
+ this.updateFilter({ accessLevel: level });
459
+ }
460
+ onRoleFilterChange(event) {
461
+ const value = event.target.value;
462
+ this.updateFilter({ roleId: value || null });
463
+ }
464
+ updateFilter(partial) {
465
+ this.filters$.next({
466
+ ...this.filters$.value,
467
+ ...partial
468
+ });
469
+ }
470
+ toggleEntityExpansion(entityId) {
471
+ this.expandedEntityId = this.expandedEntityId === entityId ? null : entityId;
472
+ }
473
+ isEntityExpanded(entityId) {
474
+ return this.expandedEntityId === entityId;
475
+ }
476
+ editEntityPermissions(entityAccess) {
477
+ this.selectedEntity = entityAccess;
478
+ this.showPermissionDialog = true;
479
+ }
480
+ async savePermissions() {
481
+ if (!this.selectedEntity)
482
+ return;
483
+ try {
484
+ // Implementation for saving permissions
485
+ // This would involve updating EntityPermission records
486
+ this.showPermissionDialog = false;
487
+ this.selectedEntity = null;
488
+ await this.loadInitialData();
489
+ }
490
+ catch (error) {
491
+ console.error('Error saving permissions:', error);
492
+ this.error = 'Failed to save permissions';
493
+ }
494
+ }
495
+ getAccessLevelClass(entityAccess) {
496
+ if (entityAccess.isPublic) {
497
+ return 'access-public';
498
+ }
499
+ else if (entityAccess.permissions.length === 0) {
500
+ return 'access-restricted';
501
+ }
502
+ else {
503
+ return 'access-custom';
504
+ }
505
+ }
506
+ getAccessLevelLabel(entityAccess) {
507
+ if (entityAccess.isPublic) {
508
+ return 'Public';
509
+ }
510
+ else if (entityAccess.permissions.length === 0) {
511
+ return 'Restricted';
512
+ }
513
+ else {
514
+ return 'Custom';
515
+ }
516
+ }
517
+ getRoleName(roleId) {
518
+ const role = this.roles.find(r => r.ID === roleId);
519
+ return role?.Name || 'Unknown Role';
520
+ }
521
+ hasPermission(entityAccess, roleId, permission) {
522
+ const rolePermission = entityAccess.rolePermissions.get(roleId);
523
+ return rolePermission ? rolePermission[permission] : false;
524
+ }
525
+ refreshData() {
526
+ this.loadInitialData();
527
+ }
528
+ setViewMode(mode) {
529
+ this.viewMode = mode;
530
+ }
531
+ static ɵfac = function EntityPermissionsComponent_Factory(t) { return new (t || EntityPermissionsComponent)(); };
532
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityPermissionsComponent, selectors: [["mj-entity-permissions"]], standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 72, vars: 24, consts: [[1, "entity-permissions-container"], [1, "action-buttons"], [1, "view-toggle"], ["title", "List View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["title", "Grid View", 1, "view-btn", 3, "click"], [1, "fa-solid", "fa-th"], [1, "btn-secondary", 3, "click", "disabled"], [1, "fa-solid", "fa-refresh"], [1, "stats-grid", 2, "display", "flex"], [1, "stat-card"], [1, "stat-icon", "stat-icon-total"], [1, "fa-solid", "fa-database"], [1, "stat-content"], [1, "stat-value"], [1, "stat-label"], [1, "stat-icon", "stat-icon-public"], [1, "fa-solid", "fa-globe"], [1, "stat-icon", "stat-icon-restricted"], [1, "fa-solid", "fa-lock"], [1, "stat-icon", "stat-icon-permissions"], [1, "fa-solid", "fa-key"], [1, "filters-section"], [1, "filters-row"], [1, "search-container"], [1, "fa-solid", "fa-search", "search-icon"], ["type", "text", "placeholder", "Search entities by name or description...", 1, "search-input", 3, "input", "value"], [1, "filter-group"], [1, "filter-label"], [1, "filter-buttons"], [1, "filter-btn", 3, "click"], [1, "filter-select", 3, "change"], ["value", ""], [3, "value"], [1, "loading-container"], [1, "error-container"], [1, "content-area"], [1, "modal-backdrop"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "error-content"], [1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], [1, "entities-list"], [1, "entities-grid"], [1, "empty-state"], [1, "entity-card", 3, "expanded"], [1, "entity-card"], [1, "entity-header", 3, "click"], [1, "entity-info"], [1, "entity-icon-wrapper"], [1, "fa-solid", "fa-table"], [1, "entity-details"], [1, "entity-name"], [1, "entity-description"], [1, "entity-meta"], [1, "access-badge"], ["title", "Edit Permissions", 1, "action-btn", 3, "click"], [1, "fa-solid", "fa-edit"], [1, "expand-btn"], [1, "fa-solid", "fa-chevron-down"], [1, "entity-content"], [1, "permissions-grid"], [1, "no-permissions"], [1, "permissions-header"], [1, "role-header"], [1, "permission-header"], [1, "permission-row"], [1, "role-name"], [1, "permission-cell"], [1, "entity-grid-card", 3, "class"], [1, "entity-grid-card"], [1, "grid-card-header"], ["title", "Edit Permissions", 1, "edit-btn", 3, "click"], [1, "grid-card-title"], [1, "grid-card-description"], [1, "grid-card-footer"], [1, "access-label"], [1, "permission-count"], [1, "fa-solid", "fa-key", "empty-icon"], [1, "empty-text"], [1, "empty-subtext"], [1, "modal-backdrop", 3, "click"], [1, "modal-dialog", "modal-large", 3, "click"], [1, "modal-header"], [1, "modal-title"], [1, "modal-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [1, "modal-description"], [1, "permission-editor"], [1, "coming-soon"], [1, "fa-solid", "fa-info-circle"], [1, "modal-footer"], [1, "btn-secondary", 3, "click"], [1, "btn-primary", 3, "click"], [1, "fa-solid", "fa-save"]], template: function EntityPermissionsComponent_Template(rf, ctx) { if (rf & 1) {
533
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "button", 3);
534
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_3_listener() { return ctx.setViewMode("list"); });
535
+ i0.ɵɵelement(4, "i", 4);
536
+ i0.ɵɵelementEnd();
537
+ i0.ɵɵelementStart(5, "button", 5);
538
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_5_listener() { return ctx.setViewMode("grid"); });
539
+ i0.ɵɵelement(6, "i", 6);
540
+ i0.ɵɵelementEnd()();
541
+ i0.ɵɵelementStart(7, "button", 7);
542
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_7_listener() { return ctx.refreshData(); });
543
+ i0.ɵɵelement(8, "i", 8);
544
+ i0.ɵɵtext(9, " Refresh ");
545
+ i0.ɵɵelementEnd()();
546
+ i0.ɵɵelementStart(10, "div", 9)(11, "div", 10)(12, "div", 11);
547
+ i0.ɵɵelement(13, "i", 12);
548
+ i0.ɵɵelementEnd();
549
+ i0.ɵɵelementStart(14, "div", 13)(15, "div", 14);
550
+ i0.ɵɵtext(16);
551
+ i0.ɵɵelementEnd();
552
+ i0.ɵɵelementStart(17, "div", 15);
553
+ i0.ɵɵtext(18, "Total Entities");
554
+ i0.ɵɵelementEnd()()();
555
+ i0.ɵɵelementStart(19, "div", 10)(20, "div", 16);
556
+ i0.ɵɵelement(21, "i", 17);
557
+ i0.ɵɵelementEnd();
558
+ i0.ɵɵelementStart(22, "div", 13)(23, "div", 14);
559
+ i0.ɵɵtext(24);
560
+ i0.ɵɵelementEnd();
561
+ i0.ɵɵelementStart(25, "div", 15);
562
+ i0.ɵɵtext(26, "Public Entities");
563
+ i0.ɵɵelementEnd()()();
564
+ i0.ɵɵelementStart(27, "div", 10)(28, "div", 18);
565
+ i0.ɵɵelement(29, "i", 19);
566
+ i0.ɵɵelementEnd();
567
+ i0.ɵɵelementStart(30, "div", 13)(31, "div", 14);
568
+ i0.ɵɵtext(32);
569
+ i0.ɵɵelementEnd();
570
+ i0.ɵɵelementStart(33, "div", 15);
571
+ i0.ɵɵtext(34, "Restricted Entities");
572
+ i0.ɵɵelementEnd()()();
573
+ i0.ɵɵelementStart(35, "div", 10)(36, "div", 20);
574
+ i0.ɵɵelement(37, "i", 21);
575
+ i0.ɵɵelementEnd();
576
+ i0.ɵɵelementStart(38, "div", 13)(39, "div", 14);
577
+ i0.ɵɵtext(40);
578
+ i0.ɵɵelementEnd();
579
+ i0.ɵɵelementStart(41, "div", 15);
580
+ i0.ɵɵtext(42, "Total Permissions");
581
+ i0.ɵɵelementEnd()()()();
582
+ i0.ɵɵelementStart(43, "div", 22)(44, "div", 23)(45, "div", 24);
583
+ i0.ɵɵelement(46, "i", 25);
584
+ i0.ɵɵelementStart(47, "input", 26);
585
+ i0.ɵɵlistener("input", function EntityPermissionsComponent_Template_input_input_47_listener($event) { return ctx.onSearchChange($event); });
586
+ i0.ɵɵelementEnd()();
587
+ i0.ɵɵelementStart(48, "div", 27)(49, "label", 28);
588
+ i0.ɵɵtext(50, "Access Level");
589
+ i0.ɵɵelementEnd();
590
+ i0.ɵɵelementStart(51, "div", 29)(52, "button", 30);
591
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_52_listener() { return ctx.onAccessLevelChange("all"); });
592
+ i0.ɵɵtext(53, " All ");
593
+ i0.ɵɵelementEnd();
594
+ i0.ɵɵelementStart(54, "button", 30);
595
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_54_listener() { return ctx.onAccessLevelChange("public"); });
596
+ i0.ɵɵtext(55, " Public ");
597
+ i0.ɵɵelementEnd();
598
+ i0.ɵɵelementStart(56, "button", 30);
599
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_56_listener() { return ctx.onAccessLevelChange("restricted"); });
600
+ i0.ɵɵtext(57, " Restricted ");
601
+ i0.ɵɵelementEnd();
602
+ i0.ɵɵelementStart(58, "button", 30);
603
+ i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_58_listener() { return ctx.onAccessLevelChange("custom"); });
604
+ i0.ɵɵtext(59, " Custom ");
605
+ i0.ɵɵelementEnd()()();
606
+ i0.ɵɵelementStart(60, "div", 27)(61, "label", 28);
607
+ i0.ɵɵtext(62, "Filter by Role");
608
+ i0.ɵɵelementEnd();
609
+ i0.ɵɵelementStart(63, "select", 31);
610
+ i0.ɵɵlistener("change", function EntityPermissionsComponent_Template_select_change_63_listener($event) { return ctx.onRoleFilterChange($event); });
611
+ i0.ɵɵelementStart(64, "option", 32);
612
+ i0.ɵɵtext(65, "All Roles");
613
+ i0.ɵɵelementEnd();
614
+ i0.ɵɵrepeaterCreate(66, EntityPermissionsComponent_For_67_Template, 2, 2, "option", 33, _forTrack0);
615
+ i0.ɵɵelementEnd()()()();
616
+ i0.ɵɵtemplate(68, EntityPermissionsComponent_Conditional_68_Template, 7, 0, "div", 34)(69, EntityPermissionsComponent_Conditional_69_Template, 8, 1, "div", 35)(70, EntityPermissionsComponent_Conditional_70_Template, 4, 2, "div", 36)(71, EntityPermissionsComponent_Conditional_71_Template, 21, 1, "div", 37);
617
+ i0.ɵɵelementEnd();
618
+ } if (rf & 2) {
619
+ i0.ɵɵadvance(3);
620
+ i0.ɵɵclassProp("active", ctx.viewMode === "list");
621
+ i0.ɵɵadvance(2);
622
+ i0.ɵɵclassProp("active", ctx.viewMode === "grid");
623
+ i0.ɵɵadvance(2);
624
+ i0.ɵɵproperty("disabled", ctx.isLoading);
625
+ i0.ɵɵadvance();
626
+ i0.ɵɵclassProp("fa-spin", ctx.isLoading);
627
+ i0.ɵɵadvance(8);
628
+ i0.ɵɵtextInterpolate(ctx.stats.totalEntities);
629
+ i0.ɵɵadvance(8);
630
+ i0.ɵɵtextInterpolate(ctx.stats.publicEntities);
631
+ i0.ɵɵadvance(8);
632
+ i0.ɵɵtextInterpolate(ctx.stats.restrictedEntities);
633
+ i0.ɵɵadvance(8);
634
+ i0.ɵɵtextInterpolate(ctx.stats.totalPermissions);
635
+ i0.ɵɵadvance(7);
636
+ i0.ɵɵproperty("value", ctx.filters$.value.entitySearch);
637
+ i0.ɵɵadvance(5);
638
+ i0.ɵɵclassProp("active", ctx.filters$.value.accessLevel === "all");
639
+ i0.ɵɵadvance(2);
640
+ i0.ɵɵclassProp("active", ctx.filters$.value.accessLevel === "public");
641
+ i0.ɵɵadvance(2);
642
+ i0.ɵɵclassProp("active", ctx.filters$.value.accessLevel === "restricted");
643
+ i0.ɵɵadvance(2);
644
+ i0.ɵɵclassProp("active", ctx.filters$.value.accessLevel === "custom");
645
+ i0.ɵɵadvance(8);
646
+ i0.ɵɵrepeater(ctx.roles);
647
+ i0.ɵɵadvance(2);
648
+ i0.ɵɵconditional(ctx.isLoading ? 68 : -1);
649
+ i0.ɵɵadvance();
650
+ i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 69 : -1);
651
+ i0.ɵɵadvance();
652
+ i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 70 : -1);
653
+ i0.ɵɵadvance();
654
+ i0.ɵɵconditional(ctx.showPermissionDialog && ctx.selectedEntity ? 71 : -1);
655
+ } }, dependencies: [CommonModule,
656
+ FormsModule, i1.NgSelectOption, i1.ɵNgSelectMultipleOption, SharedSettingsModule], styles: ["@import '../shared/styles/variables';\n@import '../shared/styles/mixins';\n\n.entity-permissions-container[_ngcontent-%COMP%] {\n @include scrollable-container;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n//[_ngcontent-%COMP%] Action[_ngcontent-%COMP%] Buttons\n.action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: space-between;\n margin-bottom: 1.5rem;\n\n @media (max-width: 768px) {\n flex-direction: column;\n }\n}\n\n.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n}\n\n.view-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n}\n\n//[_ngcontent-%COMP%] Buttons\n.btn-primary[_ngcontent-%COMP%] {\n @include button-base;\n background-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n }\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n @include button-base;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n \n &:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n }\n}\n\n//[_ngcontent-%COMP%] Stats[_ngcontent-%COMP%] Grid\n.stats-grid[_ngcontent-%COMP%] {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 2rem;\n width: 100%;\n\n @media (max-width: 768px) {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n margin-right: 10px;\n align-items: center;\n gap: 1rem;\n transition: all 0.3s ease;\n min-width: 0; // Prevent grid blowout\n\n &:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n }\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n\n &-total {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n &-public {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n &-restricted {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n }\n\n &-permissions {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n }\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n\n .stat-value {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n }\n\n .stat-label {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n }\n}\n\n//[_ngcontent-%COMP%] Filters[_ngcontent-%COMP%] Section\n.filters-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n}\n\n.filters-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n.search-container[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 250px;\n position: relative;\n\n .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n }\n\n .search-input {\n width: 100%;\n padding: 0.75rem 1rem 0.75rem 2.75rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n\n .filter-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: #374151;\n }\n\n .filter-buttons {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n }\n\n .filter-btn {\n padding: 0.5rem 1rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n }\n\n .filter-select {\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n background: white;\n cursor: pointer;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n//[_ngcontent-%COMP%] Content[_ngcontent-%COMP%] Area\n.content-area[_ngcontent-%COMP%] {\n @include scrollable-content;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n padding: 1.5rem;\n}\n\n//[_ngcontent-%COMP%] List[_ngcontent-%COMP%] View\n.entities-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n max-height: calc(100vh - 450px); // Dynamic height\n overflow-y: auto;\n padding-right: 0.5rem; // Space for scrollbar\n}\n\n.entity-card[_ngcontent-%COMP%] {\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.3s ease;\n\n &:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n &.expanded {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n \n .expand-btn i {\n transform: rotate(180deg);\n }\n }\n}\n\n.entity-header[_ngcontent-%COMP%] {\n padding: 1.5rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n background: #f9fafb;\n transition: background-color 0.2s;\n\n &:hover {\n background: #f3f4f6;\n }\n}\n\n.entity-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n}\n\n.entity-icon-wrapper[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n background: rgba(33, 150, 243, 0.1);\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2196f3;\n font-size: 1.25rem;\n}\n\n.entity-details[_ngcontent-%COMP%] {\n flex: 1;\n\n .entity-name {\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n }\n\n .entity-description {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0;\n }\n}\n\n.entity-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.access-badge[_ngcontent-%COMP%] {\n padding: 0.375rem 0.75rem;\n border-radius: 20px;\n font-size: 0.75rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n\n &.access-public {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n }\n\n &.access-restricted {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n }\n\n &.access-custom {\n background: rgba(156, 39, 176, 0.1);\n color: #7b1fa2;\n }\n}\n\n.action-btn[_ngcontent-%COMP%] {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s;\n\n i {\n transition: transform 0.3s ease;\n }\n}\n\n//[_ngcontent-%COMP%] Entity[_ngcontent-%COMP%] Content\n.entity-content[_ngcontent-%COMP%] {\n padding: 1.5rem;\n background: white;\n border-top: 1px solid #e5e7eb;\n animation: _ngcontent-%COMP%_slideDown 0.3s ease-out;\n}\n\n.permissions-grid[_ngcontent-%COMP%] {\n background: #f9fafb;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.permissions-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 1rem;\n padding: 1rem;\n background: #e5e7eb;\n font-weight: 600;\n color: #374151;\n font-size: 0.875rem;\n}\n\n.permission-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 1rem;\n padding: 1rem;\n border-bottom: 1px solid #e5e7eb;\n transition: background-color 0.2s;\n\n &:hover {\n background: white;\n }\n\n &:last-child {\n border-bottom: none;\n }\n}\n\n.role-header[_ngcontent-%COMP%], .permission-header[_ngcontent-%COMP%] {\n text-align: left;\n}\n\n.role-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: #1f2937;\n}\n\n.permission-cell[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.text-success[_ngcontent-%COMP%] {\n color: #4caf50;\n}\n\n.text-muted[_ngcontent-%COMP%] {\n color: #d1d5db;\n}\n\n.no-permissions[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.875rem;\n margin: 0;\n}\n\n//[_ngcontent-%COMP%] Grid[_ngcontent-%COMP%] View\n.entities-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n}\n\n.entity-grid-card[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n padding: 1.5rem;\n transition: all 0.3s ease;\n position: relative;\n\n &:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n }\n\n &.access-public {\n border-left: 4px solid #4caf50;\n }\n\n &.access-restricted {\n border-left: 4px solid #f44336;\n }\n\n &.access-custom {\n border-left: 4px solid #9c27b0;\n }\n}\n\n.grid-card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n font-size: 1.5rem;\n color: #2196f3;\n}\n\n.edit-btn[_ngcontent-%COMP%] {\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #2196f3;\n }\n}\n\n.grid-card-title[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.5rem 0;\n}\n\n.grid-card-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0 0 1rem 0;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.grid-card-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.875rem;\n}\n\n.access-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n font-weight: 500;\n}\n\n.permission-count[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n//[_ngcontent-%COMP%] Empty[_ngcontent-%COMP%] State\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n\n .empty-icon {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n }\n\n .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n }\n\n .empty-subtext {\n color: #6b7280;\n margin: 0;\n }\n}\n\n//[_ngcontent-%COMP%] Loading[_ngcontent-%COMP%] State\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n position: relative;\n width: 60px;\n height: 60px;\n margin-bottom: 1rem;\n\n .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n &:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n }\n\n &:nth-child(2) {\n border-color: transparent #9c27b0 transparent transparent;\n animation-delay: -0.3s;\n }\n\n &:nth-child(3) {\n border-color: transparent transparent #4caf50 transparent;\n animation-delay: -0.15s;\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.loading-text[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n//[_ngcontent-%COMP%] Error[_ngcontent-%COMP%] State\n.error-container[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n\n .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n }\n\n .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n }\n\n .retry-button {\n @include button-base;\n background-color: #2196f3;\n color: white;\n }\n}\n\n//[_ngcontent-%COMP%] Modal[_ngcontent-%COMP%] Styles\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUp 0.3s ease;\n\n &.modal-large {\n max-width: 800px;\n }\n}\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid #e5e7eb;\n\n .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0;\n }\n\n .modal-close {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #374151;\n }\n }\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n max-height: 60vh;\n overflow-y: auto;\n\n .modal-description {\n color: #374151;\n margin: 0 0 1.5rem 0;\n }\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n}\n\n.permission-editor[_ngcontent-%COMP%] {\n padding: 2rem;\n background: #f3f4f6;\n border-radius: 8px;\n text-align: center;\n\n .coming-soon {\n color: #6b7280;\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n }\n}\n\n//[_ngcontent-%COMP%] Animations\n@keyframes[_ngcontent-%COMP%] fadeIn[_ngcontent-%COMP%] {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes _ngcontent-%COMP%_slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n max-height: 0;\n }\n to {\n opacity: 1;\n max-height: 800px;\n }\n}"] });
657
+ }
658
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityPermissionsComponent, [{
659
+ type: Component,
660
+ args: [{ selector: 'mj-entity-permissions', standalone: true, imports: [
661
+ CommonModule,
662
+ FormsModule,
663
+ SharedSettingsModule
664
+ ], template: "<div class=\"entity-permissions-container\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\">\n <div class=\"view-toggle\">\n <button \n class=\"view-btn\"\n [class.active]=\"viewMode === 'list'\"\n (click)=\"setViewMode('list')\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\"></i>\n </button>\n <button \n class=\"view-btn\"\n [class.active]=\"viewMode === 'grid'\"\n (click)=\"setViewMode('grid')\"\n title=\"Grid View\"\n >\n <i class=\"fa-solid fa-th\"></i>\n </button>\n </div>\n <button class=\"btn-secondary\" (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <i class=\"fa-solid fa-refresh\" [class.fa-spin]=\"isLoading\"></i>\n Refresh\n </button>\n </div>\n\n <!-- Stats Cards -->\n <div class=\"stats-grid\" style=\"display: flex\">\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-total\">\n <i class=\"fa-solid fa-database\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.totalEntities }}</div>\n <div class=\"stat-label\">Total Entities</div>\n </div>\n </div>\n \n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-public\">\n <i class=\"fa-solid fa-globe\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.publicEntities }}</div>\n <div class=\"stat-label\">Public Entities</div>\n </div>\n </div>\n \n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-restricted\">\n <i class=\"fa-solid fa-lock\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.restrictedEntities }}</div>\n <div class=\"stat-label\">Restricted Entities</div>\n </div>\n </div>\n \n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-permissions\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.totalPermissions }}</div>\n <div class=\"stat-label\">Total Permissions</div>\n </div>\n </div>\n </div>\n\n <!-- Filters Section -->\n <div class=\"filters-section\">\n <div class=\"filters-row\">\n <!-- Entity Search -->\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input \n type=\"text\" \n class=\"search-input\" \n placeholder=\"Search entities by name or description...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"filters$.value.entitySearch\"\n />\n </div>\n \n <!-- Access Level Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">Access Level</label>\n <div class=\"filter-buttons\">\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.accessLevel === 'all'\"\n (click)=\"onAccessLevelChange('all')\"\n >\n All\n </button>\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.accessLevel === 'public'\"\n (click)=\"onAccessLevelChange('public')\"\n >\n Public\n </button>\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.accessLevel === 'restricted'\"\n (click)=\"onAccessLevelChange('restricted')\"\n >\n Restricted\n </button>\n <button \n class=\"filter-btn\"\n [class.active]=\"filters$.value.accessLevel === 'custom'\"\n (click)=\"onAccessLevelChange('custom')\"\n >\n Custom\n </button>\n </div>\n </div>\n \n <!-- Role Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">Filter by Role</label>\n <select class=\"filter-select\" (change)=\"onRoleFilterChange($event)\">\n <option value=\"\">All Roles</option>\n @for (role of roles; track role.ID) {\n <option [value]=\"role.ID\">{{ role.Name }}</option>\n }\n </select>\n </div>\n </div>\n </div>\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <div class=\"loading-spinner\">\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n </div>\n <div class=\"loading-text\">Loading entity permissions...</div>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button class=\"retry-button\" (click)=\"loadInitialData()\">\n <i class=\"fa-solid fa-refresh\"></i>\n Try Again\n </button>\n </div>\n </div>\n }\n\n <!-- Content Area -->\n @if (!isLoading && !error) {\n <div class=\"content-area\">\n @if (viewMode === 'list') {\n <!-- List View -->\n <div class=\"entities-list\">\n @for (ea of filteredEntityAccess; track ea.entity.ID) {\n <div class=\"entity-card\" [class.expanded]=\"isEntityExpanded(ea.entity.ID)\">\n <div class=\"entity-header\" (click)=\"toggleEntityExpansion(ea.entity.ID)\">\n <div class=\"entity-info\">\n <div class=\"entity-icon-wrapper\">\n <i class=\"fa-solid fa-table\"></i>\n </div>\n <div class=\"entity-details\">\n <h3 class=\"entity-name\">{{ ea.entity.Name }}</h3>\n <p class=\"entity-description\">{{ ea.entity.Description || 'No description available' }}</p>\n </div>\n </div>\n \n <div class=\"entity-meta\">\n <span class=\"access-badge\" [class]=\"getAccessLevelClass(ea)\">\n <i [class]=\"getAccessLevelClass(ea) === 'access-public' ? 'fa-solid fa-globe' : \n getAccessLevelClass(ea) === 'access-restricted' ? 'fa-solid fa-lock' : \n 'fa-solid fa-key'\"></i>\n {{ getAccessLevelLabel(ea) }}\n </span>\n <button class=\"action-btn\" (click)=\"editEntityPermissions(ea); $event.stopPropagation()\" title=\"Edit Permissions\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"expand-btn\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n </div>\n \n @if (isEntityExpanded(ea.entity.ID)) {\n <div class=\"entity-content\">\n @if (ea.permissions.length > 0) {\n <div class=\"permissions-grid\">\n <div class=\"permissions-header\">\n <span class=\"role-header\">Role</span>\n <span class=\"permission-header\">Create</span>\n <span class=\"permission-header\">Read</span>\n <span class=\"permission-header\">Update</span>\n <span class=\"permission-header\">Delete</span>\n </div>\n @for (roleId of ea.rolePermissions.keys(); track roleId) {\n <div class=\"permission-row\">\n <span class=\"role-name\">{{ getRoleName(roleId) }}</span>\n <span class=\"permission-cell\">\n <i [class]=\"hasPermission(ea, roleId, 'canCreate') ? \n 'fa-solid fa-check text-success' : \n 'fa-solid fa-times text-muted'\"></i>\n </span>\n <span class=\"permission-cell\">\n <i [class]=\"hasPermission(ea, roleId, 'canRead') ? \n 'fa-solid fa-check text-success' : \n 'fa-solid fa-times text-muted'\"></i>\n </span>\n <span class=\"permission-cell\">\n <i [class]=\"hasPermission(ea, roleId, 'canUpdate') ? \n 'fa-solid fa-check text-success' : \n 'fa-solid fa-times text-muted'\"></i>\n </span>\n <span class=\"permission-cell\">\n <i [class]=\"hasPermission(ea, roleId, 'canDelete') ? \n 'fa-solid fa-check text-success' : \n 'fa-solid fa-times text-muted'\"></i>\n </span>\n </div>\n }\n </div>\n } @else {\n <p class=\"no-permissions\">\n @if (ea.isPublic) {\n This entity is publicly accessible by all users.\n } @else {\n No specific role permissions configured. Access is restricted to system administrators.\n }\n </p>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <!-- Grid View -->\n <div class=\"entities-grid\">\n @for (ea of filteredEntityAccess; track ea.entity.ID) {\n <div class=\"entity-grid-card\" [class]=\"getAccessLevelClass(ea)\">\n <div class=\"grid-card-header\">\n <i class=\"fa-solid fa-table\"></i>\n <button class=\"edit-btn\" (click)=\"editEntityPermissions(ea)\" title=\"Edit Permissions\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n </div>\n <h4 class=\"grid-card-title\">{{ ea.entity.Name }}</h4>\n <p class=\"grid-card-description\">{{ ea.entity.Description || 'No description' }}</p>\n <div class=\"grid-card-footer\">\n <span class=\"access-label\">\n <i [class]=\"getAccessLevelClass(ea) === 'access-public' ? 'fa-solid fa-globe' : \n getAccessLevelClass(ea) === 'access-restricted' ? 'fa-solid fa-lock' : \n 'fa-solid fa-key'\"></i>\n {{ getAccessLevelLabel(ea) }}\n </span>\n @if (ea.permissions.length > 0) {\n <span class=\"permission-count\">\n {{ ea.permissions.length }} permission{{ ea.permissions.length === 1 ? '' : 's' }}\n </span>\n }\n </div>\n </div>\n }\n </div>\n }\n \n @if (filteredEntityAccess.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-key empty-icon\"></i>\n <p class=\"empty-text\">No entities found</p>\n <p class=\"empty-subtext\">Try adjusting your filters to see more results</p>\n </div>\n }\n </div>\n }\n\n <!-- Permission Edit Dialog -->\n @if (showPermissionDialog && selectedEntity) {\n <div class=\"modal-backdrop\" (click)=\"showPermissionDialog = false\">\n <div class=\"modal-dialog modal-large\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">\n <i class=\"fa-solid fa-key\"></i>\n Edit Permissions - {{ selectedEntity.entity.Name }}\n </h3>\n <button class=\"modal-close\" (click)=\"showPermissionDialog = false\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p class=\"modal-description\">\n Configure role-based permissions for this entity. Changes will affect all users with the selected roles.\n </p>\n \n <!-- Permission editing UI would go here -->\n <div class=\"permission-editor\">\n <p class=\"coming-soon\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Permission editing interface coming soon...\n </p>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button class=\"btn-secondary\" (click)=\"showPermissionDialog = false\">Cancel</button>\n <button class=\"btn-primary\" (click)=\"savePermissions()\">\n <i class=\"fa-solid fa-save\"></i>\n Save Permissions\n </button>\n </div>\n </div>\n </div>\n }\n</div>", styles: ["@import '../shared/styles/variables';\n@import '../shared/styles/mixins';\n\n.entity-permissions-container {\n @include scrollable-container;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n// Action Buttons\n.action-buttons {\n display: flex;\n gap: 0.75rem;\n justify-content: space-between;\n margin-bottom: 1.5rem;\n\n @media (max-width: 768px) {\n flex-direction: column;\n }\n}\n\n.view-toggle {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n}\n\n.view-btn {\n padding: 0.5rem 1rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n}\n\n// Buttons\n.btn-primary {\n @include button-base;\n background-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n }\n}\n\n.btn-secondary {\n @include button-base;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n \n &:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n }\n}\n\n// Stats Grid\n.stats-grid {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 2rem;\n width: 100%;\n\n @media (max-width: 768px) {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n margin-right: 10px;\n align-items: center;\n gap: 1rem;\n transition: all 0.3s ease;\n min-width: 0; // Prevent grid blowout\n\n &:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n }\n}\n\n.stat-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n\n &-total {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n &-public {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n &-restricted {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n }\n\n &-permissions {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n }\n}\n\n.stat-content {\n flex: 1;\n\n .stat-value {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n }\n\n .stat-label {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n }\n}\n\n// Filters Section\n.filters-section {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n}\n\n.filters-row {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n.search-container {\n flex: 1;\n min-width: 250px;\n position: relative;\n\n .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n }\n\n .search-input {\n width: 100%;\n padding: 0.75rem 1rem 0.75rem 2.75rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n\n .filter-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: #374151;\n }\n\n .filter-buttons {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n }\n\n .filter-btn {\n padding: 0.5rem 1rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n color: #374151;\n }\n\n &.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n }\n\n .filter-select {\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n background: white;\n cursor: pointer;\n transition: all 0.2s;\n\n &:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n }\n }\n}\n\n// Content Area\n.content-area {\n @include scrollable-content;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n padding: 1.5rem;\n}\n\n// List View\n.entities-list {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n max-height: calc(100vh - 450px); // Dynamic height\n overflow-y: auto;\n padding-right: 0.5rem; // Space for scrollbar\n}\n\n.entity-card {\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.3s ease;\n\n &:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n &.expanded {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n \n .expand-btn i {\n transform: rotate(180deg);\n }\n }\n}\n\n.entity-header {\n padding: 1.5rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n background: #f9fafb;\n transition: background-color 0.2s;\n\n &:hover {\n background: #f3f4f6;\n }\n}\n\n.entity-info {\n display: flex;\n align-items: center;\n gap: 1rem;\n flex: 1;\n}\n\n.entity-icon-wrapper {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n background: rgba(33, 150, 243, 0.1);\n display: flex;\n align-items: center;\n justify-content: center;\n color: #2196f3;\n font-size: 1.25rem;\n}\n\n.entity-details {\n flex: 1;\n\n .entity-name {\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n }\n\n .entity-description {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0;\n }\n}\n\n.entity-meta {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.access-badge {\n padding: 0.375rem 0.75rem;\n border-radius: 20px;\n font-size: 0.75rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n\n &.access-public {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n }\n\n &.access-restricted {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n }\n\n &.access-custom {\n background: rgba(156, 39, 176, 0.1);\n color: #7b1fa2;\n }\n}\n\n.action-btn {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n }\n}\n\n.expand-btn {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s;\n\n i {\n transition: transform 0.3s ease;\n }\n}\n\n// Entity Content\n.entity-content {\n padding: 1.5rem;\n background: white;\n border-top: 1px solid #e5e7eb;\n animation: slideDown 0.3s ease-out;\n}\n\n.permissions-grid {\n background: #f9fafb;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.permissions-header {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 1rem;\n padding: 1rem;\n background: #e5e7eb;\n font-weight: 600;\n color: #374151;\n font-size: 0.875rem;\n}\n\n.permission-row {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 1rem;\n padding: 1rem;\n border-bottom: 1px solid #e5e7eb;\n transition: background-color 0.2s;\n\n &:hover {\n background: white;\n }\n\n &:last-child {\n border-bottom: none;\n }\n}\n\n.role-header, .permission-header {\n text-align: left;\n}\n\n.role-name {\n font-weight: 500;\n color: #1f2937;\n}\n\n.permission-cell {\n text-align: center;\n}\n\n.text-success {\n color: #4caf50;\n}\n\n.text-muted {\n color: #d1d5db;\n}\n\n.no-permissions {\n color: #6b7280;\n font-size: 0.875rem;\n margin: 0;\n}\n\n// Grid View\n.entities-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n}\n\n.entity-grid-card {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n padding: 1.5rem;\n transition: all 0.3s ease;\n position: relative;\n\n &:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n }\n\n &.access-public {\n border-left: 4px solid #4caf50;\n }\n\n &.access-restricted {\n border-left: 4px solid #f44336;\n }\n\n &.access-custom {\n border-left: 4px solid #9c27b0;\n }\n}\n\n.grid-card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n font-size: 1.5rem;\n color: #2196f3;\n}\n\n.edit-btn {\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #2196f3;\n }\n}\n\n.grid-card-title {\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.5rem 0;\n}\n\n.grid-card-description {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0 0 1rem 0;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.grid-card-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.875rem;\n}\n\n.access-label {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n font-weight: 500;\n}\n\n.permission-count {\n color: #6b7280;\n}\n\n// Empty State\n.empty-state {\n text-align: center;\n padding: 4rem 2rem;\n\n .empty-icon {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n }\n\n .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n }\n\n .empty-subtext {\n color: #6b7280;\n margin: 0;\n }\n}\n\n// Loading State\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n}\n\n.loading-spinner {\n position: relative;\n width: 60px;\n height: 60px;\n margin-bottom: 1rem;\n\n .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n\n &:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n }\n\n &:nth-child(2) {\n border-color: transparent #9c27b0 transparent transparent;\n animation-delay: -0.3s;\n }\n\n &:nth-child(3) {\n border-color: transparent transparent #4caf50 transparent;\n animation-delay: -0.15s;\n }\n }\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.loading-text {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n// Error State\n.error-container {\n text-align: center;\n padding: 4rem 2rem;\n\n .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n }\n\n .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n }\n\n .retry-button {\n @include button-base;\n background-color: #2196f3;\n color: white;\n }\n}\n\n// Modal Styles\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n.modal-dialog {\n background: white;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n animation: slideUp 0.3s ease;\n\n &.modal-large {\n max-width: 800px;\n }\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid #e5e7eb;\n\n .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0;\n }\n\n .modal-close {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n\n &:hover {\n background: #f3f4f6;\n color: #374151;\n }\n }\n}\n\n.modal-body {\n padding: 1.5rem;\n max-height: 60vh;\n overflow-y: auto;\n\n .modal-description {\n color: #374151;\n margin: 0 0 1.5rem 0;\n }\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n}\n\n.permission-editor {\n padding: 2rem;\n background: #f3f4f6;\n border-radius: 8px;\n text-align: center;\n\n .coming-soon {\n color: #6b7280;\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n }\n}\n\n// Animations\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n max-height: 0;\n }\n to {\n opacity: 1;\n max-height: 800px;\n }\n}"] }]
665
+ }], () => [], null); })();
666
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityPermissionsComponent, { className: "EntityPermissionsComponent", filePath: "src/lib/entity-permissions/entity-permissions.component.ts", lineNumber: 53 }); })();
667
+ //# sourceMappingURL=entity-permissions.component.js.map