@memberjunction/ng-explorer-settings 3.2.0 → 3.4.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.
- package/dist/lib/account-info/account-info.component.d.ts +23 -0
- package/dist/lib/account-info/account-info.component.d.ts.map +1 -0
- package/dist/lib/account-info/account-info.component.js +155 -0
- package/dist/lib/account-info/account-info.component.js.map +1 -0
- package/dist/lib/appearance-settings/appearance-settings.component.d.ts +15 -0
- package/dist/lib/appearance-settings/appearance-settings.component.d.ts.map +1 -0
- package/dist/lib/appearance-settings/appearance-settings.component.js +79 -0
- package/dist/lib/appearance-settings/appearance-settings.component.js.map +1 -0
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +15 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.js +329 -190
- package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
- package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-management.component.js +265 -184
- package/dist/lib/application-management/application-management.component.js.map +1 -1
- package/dist/lib/application-settings/application-settings.component.d.ts +113 -0
- package/dist/lib/application-settings/application-settings.component.d.ts.map +1 -0
- package/dist/lib/application-settings/application-settings.component.js +520 -0
- package/dist/lib/application-settings/application-settings.component.js.map +1 -0
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts +1 -0
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.js +369 -192
- package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +160 -143
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
- package/dist/lib/general-settings/general-settings.component.d.ts +14 -0
- package/dist/lib/general-settings/general-settings.component.d.ts.map +1 -0
- package/dist/lib/general-settings/general-settings.component.js +50 -0
- package/dist/lib/general-settings/general-settings.component.js.map +1 -0
- package/dist/lib/module.d.ts +28 -30
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/module.js +75 -68
- package/dist/lib/module.js.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts +77 -0
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.js +153 -77
- package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.js +93 -89
- package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
- package/dist/lib/role-management/role-management.component.d.ts +1 -0
- package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-management.component.js +275 -158
- package/dist/lib/role-management/role-management.component.js.map +1 -1
- package/dist/lib/settings/settings.component.d.ts +47 -3
- package/dist/lib/settings/settings.component.d.ts.map +1 -1
- package/dist/lib/settings/settings.component.js +339 -269
- package/dist/lib/settings/settings.component.js.map +1 -1
- package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
- package/dist/lib/shared/settings-card.component.js +21 -18
- package/dist/lib/shared/settings-card.component.js.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.d.ts +11 -2
- package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.js +318 -245
- package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config.component.d.ts +21 -3
- package/dist/lib/user-app-config/user-app-config.component.d.ts.map +1 -1
- package/dist/lib/user-app-config/user-app-config.component.js +202 -147
- package/dist/lib/user-app-config/user-app-config.component.js.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.js +120 -116
- package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
- package/dist/lib/user-management/user-management.component.d.ts +32 -2
- package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-management.component.js +822 -297
- package/dist/lib/user-management/user-management.component.js.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +31 -2
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.js +213 -80
- package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
- package/package.json +20 -20
|
@@ -12,11 +12,12 @@ import { BaseDashboard } from '@memberjunction/ng-shared';
|
|
|
12
12
|
import { RegisterClass } from '@memberjunction/global';
|
|
13
13
|
import * as i0 from "@angular/core";
|
|
14
14
|
import * as i1 from "@angular/forms";
|
|
15
|
-
import * as i2 from "
|
|
15
|
+
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
16
|
+
import * as i3 from "./permission-dialog/permission-dialog.component";
|
|
16
17
|
const _forTrack0 = ($index, $item) => $item.ID;
|
|
17
18
|
const _forTrack1 = ($index, $item) => $item.entity.ID;
|
|
18
|
-
function
|
|
19
|
-
i0.ɵɵelementStart(0, "option",
|
|
19
|
+
function EntityPermissionsComponent_For_74_Template(rf, ctx) { if (rf & 1) {
|
|
20
|
+
i0.ɵɵelementStart(0, "option", 48);
|
|
20
21
|
i0.ɵɵtext(1);
|
|
21
22
|
i0.ɵɵelementEnd();
|
|
22
23
|
} if (rf & 2) {
|
|
@@ -25,24 +26,21 @@ function EntityPermissionsComponent_For_67_Template(rf, ctx) { if (rf & 1) {
|
|
|
25
26
|
i0.ɵɵadvance();
|
|
26
27
|
i0.ɵɵtextInterpolate(role_r1.Name);
|
|
27
28
|
} }
|
|
28
|
-
function
|
|
29
|
-
i0.ɵɵelementStart(0, "div",
|
|
30
|
-
i0.ɵɵelement(
|
|
29
|
+
function EntityPermissionsComponent_Conditional_76_Template(rf, ctx) { if (rf & 1) {
|
|
30
|
+
i0.ɵɵelementStart(0, "div", 50);
|
|
31
|
+
i0.ɵɵelement(1, "mj-loading", 55);
|
|
31
32
|
i0.ɵɵelementEnd();
|
|
32
|
-
i0.ɵɵelementStart(5, "div", 40);
|
|
33
|
-
i0.ɵɵtext(6, "Loading entity permissions...");
|
|
34
|
-
i0.ɵɵelementEnd()();
|
|
35
33
|
} }
|
|
36
|
-
function
|
|
34
|
+
function EntityPermissionsComponent_Conditional_77_Template(rf, ctx) { if (rf & 1) {
|
|
37
35
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
38
|
-
i0.ɵɵelementStart(0, "div",
|
|
39
|
-
i0.ɵɵelement(2, "i",
|
|
40
|
-
i0.ɵɵelementStart(3, "p",
|
|
36
|
+
i0.ɵɵelementStart(0, "div", 51)(1, "div", 56);
|
|
37
|
+
i0.ɵɵelement(2, "i", 57);
|
|
38
|
+
i0.ɵɵelementStart(3, "p", 58);
|
|
41
39
|
i0.ɵɵtext(4);
|
|
42
40
|
i0.ɵɵelementEnd();
|
|
43
|
-
i0.ɵɵelementStart(5, "button",
|
|
44
|
-
i0.ɵɵlistener("click", function
|
|
45
|
-
i0.ɵɵelement(6, "i",
|
|
41
|
+
i0.ɵɵelementStart(5, "button", 59);
|
|
42
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_77_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.loadInitialData()); });
|
|
43
|
+
i0.ɵɵelement(6, "i", 9);
|
|
46
44
|
i0.ɵɵtext(7, " Try Again ");
|
|
47
45
|
i0.ɵɵelementEnd()()();
|
|
48
46
|
} if (rf & 2) {
|
|
@@ -50,202 +48,259 @@ function EntityPermissionsComponent_Conditional_69_Template(rf, ctx) { if (rf &
|
|
|
50
48
|
i0.ɵɵadvance(4);
|
|
51
49
|
i0.ɵɵtextInterpolate(ctx_r2.error);
|
|
52
50
|
} }
|
|
53
|
-
function
|
|
54
|
-
i0.ɵɵelementStart(0, "
|
|
51
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_10_For_15_Template(rf, ctx) { if (rf & 1) {
|
|
52
|
+
i0.ɵɵelementStart(0, "tr", 91)(1, "td", 92);
|
|
55
53
|
i0.ɵɵtext(2);
|
|
56
54
|
i0.ɵɵelementEnd();
|
|
57
|
-
i0.ɵɵelementStart(3, "
|
|
55
|
+
i0.ɵɵelementStart(3, "td", 93);
|
|
58
56
|
i0.ɵɵelement(4, "i");
|
|
59
57
|
i0.ɵɵelementEnd();
|
|
60
|
-
i0.ɵɵelementStart(5, "
|
|
58
|
+
i0.ɵɵelementStart(5, "td", 93);
|
|
61
59
|
i0.ɵɵelement(6, "i");
|
|
62
60
|
i0.ɵɵelementEnd();
|
|
63
|
-
i0.ɵɵelementStart(7, "
|
|
61
|
+
i0.ɵɵelementStart(7, "td", 93);
|
|
64
62
|
i0.ɵɵelement(8, "i");
|
|
65
63
|
i0.ɵɵelementEnd();
|
|
66
|
-
i0.ɵɵelementStart(9, "
|
|
64
|
+
i0.ɵɵelementStart(9, "td", 93);
|
|
67
65
|
i0.ɵɵelement(10, "i");
|
|
68
66
|
i0.ɵɵelementEnd()();
|
|
69
67
|
} if (rf & 2) {
|
|
70
|
-
const
|
|
68
|
+
const roleId_r7 = ctx.$implicit;
|
|
71
69
|
const ea_r5 = i0.ɵɵnextContext(3).$implicit;
|
|
72
70
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
73
71
|
i0.ɵɵadvance(2);
|
|
74
|
-
i0.ɵɵtextInterpolate(ctx_r2.getRoleName(
|
|
75
|
-
i0.ɵɵadvance(
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵadvance(
|
|
78
|
-
i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5,
|
|
79
|
-
i0.ɵɵ
|
|
80
|
-
i0.ɵɵ
|
|
81
|
-
i0.ɵɵ
|
|
82
|
-
i0.ɵɵ
|
|
72
|
+
i0.ɵɵtextInterpolate(ctx_r2.getRoleName(roleId_r7));
|
|
73
|
+
i0.ɵɵadvance();
|
|
74
|
+
i0.ɵɵattribute("aria-label", "Create: " + (ctx_r2.hasPermission(ea_r5, roleId_r7, "canCreate") ? "allowed" : "denied"));
|
|
75
|
+
i0.ɵɵadvance();
|
|
76
|
+
i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r7, "canCreate") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
|
|
77
|
+
i0.ɵɵattribute("aria-hidden", true);
|
|
78
|
+
i0.ɵɵadvance();
|
|
79
|
+
i0.ɵɵattribute("aria-label", "Read: " + (ctx_r2.hasPermission(ea_r5, roleId_r7, "canRead") ? "allowed" : "denied"));
|
|
80
|
+
i0.ɵɵadvance();
|
|
81
|
+
i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r7, "canRead") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
|
|
82
|
+
i0.ɵɵattribute("aria-hidden", true);
|
|
83
|
+
i0.ɵɵadvance();
|
|
84
|
+
i0.ɵɵattribute("aria-label", "Update: " + (ctx_r2.hasPermission(ea_r5, roleId_r7, "canUpdate") ? "allowed" : "denied"));
|
|
85
|
+
i0.ɵɵadvance();
|
|
86
|
+
i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r7, "canUpdate") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
|
|
87
|
+
i0.ɵɵattribute("aria-hidden", true);
|
|
88
|
+
i0.ɵɵadvance();
|
|
89
|
+
i0.ɵɵattribute("aria-label", "Delete: " + (ctx_r2.hasPermission(ea_r5, roleId_r7, "canDelete") ? "allowed" : "denied"));
|
|
90
|
+
i0.ɵɵadvance();
|
|
91
|
+
i0.ɵɵclassMap(ctx_r2.hasPermission(ea_r5, roleId_r7, "canDelete") ? "fa-solid fa-check text-success" : "fa-solid fa-times text-muted");
|
|
92
|
+
i0.ɵɵattribute("aria-hidden", true);
|
|
83
93
|
} }
|
|
84
|
-
function
|
|
85
|
-
i0.ɵɵelementStart(0, "
|
|
86
|
-
i0.ɵɵtext(
|
|
94
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
95
|
+
i0.ɵɵelementStart(0, "table", 84)(1, "thead", 86)(2, "tr", 87)(3, "th", 88);
|
|
96
|
+
i0.ɵɵtext(4, "Role");
|
|
87
97
|
i0.ɵɵelementEnd();
|
|
88
|
-
i0.ɵɵelementStart(
|
|
89
|
-
i0.ɵɵtext(
|
|
98
|
+
i0.ɵɵelementStart(5, "th", 89);
|
|
99
|
+
i0.ɵɵtext(6, "Create");
|
|
90
100
|
i0.ɵɵelementEnd();
|
|
91
|
-
i0.ɵɵelementStart(
|
|
92
|
-
i0.ɵɵtext(
|
|
101
|
+
i0.ɵɵelementStart(7, "th", 89);
|
|
102
|
+
i0.ɵɵtext(8, "Read");
|
|
93
103
|
i0.ɵɵelementEnd();
|
|
94
|
-
i0.ɵɵelementStart(
|
|
95
|
-
i0.ɵɵtext(
|
|
104
|
+
i0.ɵɵelementStart(9, "th", 89);
|
|
105
|
+
i0.ɵɵtext(10, "Update");
|
|
96
106
|
i0.ɵɵelementEnd();
|
|
97
|
-
i0.ɵɵelementStart(
|
|
98
|
-
i0.ɵɵtext(
|
|
107
|
+
i0.ɵɵelementStart(11, "th", 89);
|
|
108
|
+
i0.ɵɵtext(12, "Delete");
|
|
109
|
+
i0.ɵɵelementEnd()()();
|
|
110
|
+
i0.ɵɵelementStart(13, "tbody", 90);
|
|
111
|
+
i0.ɵɵrepeaterCreate(14, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_10_For_15_Template, 11, 17, "tr", 91, i0.ɵɵrepeaterTrackByIdentity);
|
|
99
112
|
i0.ɵɵelementEnd()();
|
|
100
|
-
i0.ɵɵrepeaterCreate(12, EntityPermissionsComponent_Conditional_70_Conditional_1_For_2_Conditional_18_Conditional_1_For_13_Template, 11, 9, "div", 69, i0.ɵɵrepeaterTrackByIdentity);
|
|
101
|
-
i0.ɵɵelementEnd();
|
|
102
113
|
} if (rf & 2) {
|
|
103
114
|
const ea_r5 = i0.ɵɵnextContext(2).$implicit;
|
|
104
|
-
i0.ɵɵadvance(
|
|
115
|
+
i0.ɵɵadvance(14);
|
|
105
116
|
i0.ɵɵrepeater(ea_r5.rolePermissions.keys());
|
|
106
117
|
} }
|
|
107
|
-
function
|
|
118
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_11_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
108
119
|
i0.ɵɵtext(0, " This entity is publicly accessible by all users. ");
|
|
109
120
|
} }
|
|
110
|
-
function
|
|
121
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_11_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
111
122
|
i0.ɵɵtext(0, " No specific role permissions configured. Access is restricted to system administrators. ");
|
|
112
123
|
} }
|
|
113
|
-
function
|
|
114
|
-
i0.ɵɵelementStart(0, "p",
|
|
115
|
-
i0.ɵɵtemplate(1,
|
|
124
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
125
|
+
i0.ɵɵelementStart(0, "p", 85);
|
|
126
|
+
i0.ɵɵtemplate(1, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_11_Conditional_1_Template, 1, 0)(2, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_11_Conditional_2_Template, 1, 0);
|
|
116
127
|
i0.ɵɵelementEnd();
|
|
117
128
|
} if (rf & 2) {
|
|
118
129
|
const ea_r5 = i0.ɵɵnextContext(2).$implicit;
|
|
119
130
|
i0.ɵɵadvance();
|
|
120
131
|
i0.ɵɵconditional(ea_r5.isPublic ? 1 : 2);
|
|
121
132
|
} }
|
|
122
|
-
function
|
|
123
|
-
i0.ɵɵ
|
|
124
|
-
i0.ɵɵ
|
|
133
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
134
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
135
|
+
i0.ɵɵelementStart(0, "div", 80)(1, "div", 81);
|
|
136
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r6); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
137
|
+
i0.ɵɵelementStart(2, "span", 73);
|
|
138
|
+
i0.ɵɵelement(3, "i", 74);
|
|
139
|
+
i0.ɵɵtext(4);
|
|
140
|
+
i0.ɵɵelementEnd();
|
|
141
|
+
i0.ɵɵelementStart(5, "div", 82)(6, "button", 76);
|
|
142
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r6); const ea_r5 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editEntityPermissions(ea_r5)); });
|
|
143
|
+
i0.ɵɵelement(7, "i", 77);
|
|
144
|
+
i0.ɵɵelementStart(8, "span", 83);
|
|
145
|
+
i0.ɵɵtext(9, "Edit");
|
|
146
|
+
i0.ɵɵelementEnd()()()();
|
|
147
|
+
i0.ɵɵtemplate(10, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_10_Template, 16, 0, "table", 84)(11, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Conditional_11_Template, 3, 1, "p", 85);
|
|
125
148
|
i0.ɵɵelementEnd();
|
|
126
149
|
} if (rf & 2) {
|
|
127
150
|
const ea_r5 = i0.ɵɵnextContext().$implicit;
|
|
151
|
+
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
152
|
+
i0.ɵɵattribute("aria-label", "Permissions for " + ea_r5.entity.Name);
|
|
153
|
+
i0.ɵɵadvance(2);
|
|
154
|
+
i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r5));
|
|
128
155
|
i0.ɵɵadvance();
|
|
129
|
-
i0.ɵɵ
|
|
156
|
+
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");
|
|
157
|
+
i0.ɵɵadvance();
|
|
158
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.getAccessLevelLabel(ea_r5), " ");
|
|
159
|
+
i0.ɵɵadvance(2);
|
|
160
|
+
i0.ɵɵattribute("aria-label", "Edit permissions for " + ea_r5.entity.Name);
|
|
161
|
+
i0.ɵɵadvance(4);
|
|
162
|
+
i0.ɵɵconditional(ea_r5.permissions.length > 0 ? 10 : 11);
|
|
130
163
|
} }
|
|
131
|
-
function
|
|
164
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
132
165
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
133
|
-
i0.ɵɵelementStart(0, "div",
|
|
134
|
-
i0.ɵɵlistener("click", function
|
|
135
|
-
i0.ɵɵelementStart(2, "div",
|
|
136
|
-
i0.ɵɵelement(4, "i",
|
|
166
|
+
i0.ɵɵelementStart(0, "div", 64)(1, "div", 65);
|
|
167
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_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)); })("keydown.enter", function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Template_div_keydown_enter_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)); })("keydown.space", function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Template_div_keydown_space_1_listener($event) { const ea_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); ctx_r2.toggleEntityExpansion(ea_r5.entity.ID); return i0.ɵɵresetView($event.preventDefault()); });
|
|
168
|
+
i0.ɵɵelementStart(2, "div", 66)(3, "div", 67);
|
|
169
|
+
i0.ɵɵelement(4, "i", 68);
|
|
137
170
|
i0.ɵɵelementEnd();
|
|
138
|
-
i0.ɵɵelementStart(5, "div",
|
|
171
|
+
i0.ɵɵelementStart(5, "div", 69)(6, "h3", 70);
|
|
139
172
|
i0.ɵɵtext(7);
|
|
140
173
|
i0.ɵɵelementEnd();
|
|
141
|
-
i0.ɵɵelementStart(8, "p",
|
|
174
|
+
i0.ɵɵelementStart(8, "p", 71);
|
|
142
175
|
i0.ɵɵtext(9);
|
|
143
176
|
i0.ɵɵelementEnd()()();
|
|
144
|
-
i0.ɵɵelementStart(10, "div",
|
|
145
|
-
i0.ɵɵelement(12, "i");
|
|
177
|
+
i0.ɵɵelementStart(10, "div", 72)(11, "span", 73);
|
|
178
|
+
i0.ɵɵelement(12, "i", 74);
|
|
146
179
|
i0.ɵɵtext(13);
|
|
147
180
|
i0.ɵɵelementEnd();
|
|
148
|
-
i0.ɵɵelementStart(14, "
|
|
149
|
-
i0.ɵɵlistener("click", function
|
|
150
|
-
i0.ɵɵ
|
|
151
|
-
i0.ɵɵ
|
|
152
|
-
i0.ɵɵ
|
|
153
|
-
i0.ɵɵ
|
|
181
|
+
i0.ɵɵelementStart(14, "div", 75);
|
|
182
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Template_div_click_14_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
183
|
+
i0.ɵɵelementStart(15, "button", 76);
|
|
184
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Template_button_click_15_listener() { const ea_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editEntityPermissions(ea_r5)); });
|
|
185
|
+
i0.ɵɵelement(16, "i", 77);
|
|
186
|
+
i0.ɵɵelementEnd()();
|
|
187
|
+
i0.ɵɵelementStart(17, "button", 78);
|
|
188
|
+
i0.ɵɵelement(18, "i", 79);
|
|
154
189
|
i0.ɵɵelementEnd()()();
|
|
155
|
-
i0.ɵɵtemplate(
|
|
190
|
+
i0.ɵɵtemplate(19, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Conditional_19_Template, 12, 8, "div", 80);
|
|
156
191
|
i0.ɵɵelementEnd();
|
|
157
192
|
} if (rf & 2) {
|
|
158
193
|
const ea_r5 = ctx.$implicit;
|
|
159
194
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
160
195
|
i0.ɵɵclassProp("expanded", ctx_r2.isEntityExpanded(ea_r5.entity.ID));
|
|
161
|
-
i0.ɵɵ
|
|
196
|
+
i0.ɵɵattribute("aria-expanded", ctx_r2.isEntityExpanded(ea_r5.entity.ID));
|
|
197
|
+
i0.ɵɵadvance();
|
|
198
|
+
i0.ɵɵattribute("aria-label", "Expand permissions for " + ea_r5.entity.Name);
|
|
199
|
+
i0.ɵɵadvance(6);
|
|
162
200
|
i0.ɵɵtextInterpolate(ea_r5.entity.Name);
|
|
163
201
|
i0.ɵɵadvance(2);
|
|
164
202
|
i0.ɵɵtextInterpolate(ea_r5.entity.Description || "No description available");
|
|
165
203
|
i0.ɵɵadvance(2);
|
|
166
204
|
i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r5));
|
|
205
|
+
i0.ɵɵattribute("aria-label", "Access level: " + ctx_r2.getAccessLevelLabel(ea_r5));
|
|
167
206
|
i0.ɵɵadvance();
|
|
168
207
|
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");
|
|
169
208
|
i0.ɵɵadvance();
|
|
170
209
|
i0.ɵɵtextInterpolate1(" ", ctx_r2.getAccessLevelLabel(ea_r5), " ");
|
|
171
|
-
i0.ɵɵadvance(
|
|
172
|
-
i0.ɵɵ
|
|
210
|
+
i0.ɵɵadvance(2);
|
|
211
|
+
i0.ɵɵattribute("aria-label", "Edit permissions for " + ea_r5.entity.Name);
|
|
212
|
+
i0.ɵɵadvance(2);
|
|
213
|
+
i0.ɵɵattribute("aria-label", (ctx_r2.isEntityExpanded(ea_r5.entity.ID) ? "Collapse" : "Expand") + " permissions for " + ea_r5.entity.Name);
|
|
214
|
+
i0.ɵɵadvance(2);
|
|
215
|
+
i0.ɵɵconditional(ctx_r2.isEntityExpanded(ea_r5.entity.ID) ? 19 : -1);
|
|
173
216
|
} }
|
|
174
|
-
function
|
|
175
|
-
i0.ɵɵelementStart(0, "div",
|
|
176
|
-
i0.ɵɵrepeaterCreate(1,
|
|
217
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
218
|
+
i0.ɵɵelementStart(0, "div", 60);
|
|
219
|
+
i0.ɵɵrepeaterCreate(1, EntityPermissionsComponent_Conditional_78_Conditional_1_For_2_Template, 20, 15, "div", 63, _forTrack1);
|
|
177
220
|
i0.ɵɵelementEnd();
|
|
178
221
|
} if (rf & 2) {
|
|
179
222
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
180
223
|
i0.ɵɵadvance();
|
|
181
224
|
i0.ɵɵrepeater(ctx_r2.filteredEntityAccess);
|
|
182
225
|
} }
|
|
183
|
-
function
|
|
184
|
-
i0.ɵɵelementStart(0, "span",
|
|
226
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_2_For_2_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
227
|
+
i0.ɵɵelementStart(0, "span", 102);
|
|
185
228
|
i0.ɵɵtext(1);
|
|
186
229
|
i0.ɵɵelementEnd();
|
|
187
230
|
} if (rf & 2) {
|
|
188
|
-
const
|
|
231
|
+
const ea_r9 = i0.ɵɵnextContext().$implicit;
|
|
232
|
+
i0.ɵɵattribute("aria-label", ea_r9.permissions.length + " permission" + (ea_r9.permissions.length === 1 ? "" : "s"));
|
|
189
233
|
i0.ɵɵadvance();
|
|
190
|
-
i0.ɵɵtextInterpolate2(" ",
|
|
234
|
+
i0.ɵɵtextInterpolate2(" ", ea_r9.permissions.length, " permission", ea_r9.permissions.length === 1 ? "" : "s", " ");
|
|
191
235
|
} }
|
|
192
|
-
function
|
|
193
|
-
const
|
|
194
|
-
i0.ɵɵelementStart(0, "
|
|
195
|
-
i0.ɵɵelement(2, "i",
|
|
196
|
-
i0.ɵɵelementStart(3, "button",
|
|
197
|
-
i0.ɵɵlistener("click", function
|
|
198
|
-
i0.ɵɵelement(4, "i",
|
|
236
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
237
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
238
|
+
i0.ɵɵelementStart(0, "article", 95)(1, "div", 96);
|
|
239
|
+
i0.ɵɵelement(2, "i", 97);
|
|
240
|
+
i0.ɵɵelementStart(3, "button", 76);
|
|
241
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_Conditional_2_For_2_Template_button_click_3_listener() { const ea_r9 = i0.ɵɵrestoreView(_r8).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editEntityPermissions(ea_r9)); });
|
|
242
|
+
i0.ɵɵelement(4, "i", 77);
|
|
199
243
|
i0.ɵɵelementEnd()();
|
|
200
|
-
i0.ɵɵelementStart(5, "h4",
|
|
244
|
+
i0.ɵɵelementStart(5, "h4", 98);
|
|
201
245
|
i0.ɵɵtext(6);
|
|
202
246
|
i0.ɵɵelementEnd();
|
|
203
|
-
i0.ɵɵelementStart(7, "p",
|
|
247
|
+
i0.ɵɵelementStart(7, "p", 99);
|
|
204
248
|
i0.ɵɵtext(8);
|
|
205
249
|
i0.ɵɵelementEnd();
|
|
206
|
-
i0.ɵɵelementStart(9, "div",
|
|
207
|
-
i0.ɵɵelement(11, "i");
|
|
250
|
+
i0.ɵɵelementStart(9, "div", 100)(10, "span", 101);
|
|
251
|
+
i0.ɵɵelement(11, "i", 74);
|
|
208
252
|
i0.ɵɵtext(12);
|
|
209
253
|
i0.ɵɵelementEnd();
|
|
210
|
-
i0.ɵɵtemplate(13,
|
|
254
|
+
i0.ɵɵtemplate(13, EntityPermissionsComponent_Conditional_78_Conditional_2_For_2_Conditional_13_Template, 2, 3, "span", 102);
|
|
211
255
|
i0.ɵɵelementEnd()();
|
|
212
256
|
} if (rf & 2) {
|
|
213
|
-
const
|
|
257
|
+
const ea_r9 = ctx.$implicit;
|
|
214
258
|
const ctx_r2 = i0.ɵɵnextContext(3);
|
|
215
|
-
i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(
|
|
216
|
-
i0.ɵɵ
|
|
217
|
-
i0.ɵɵ
|
|
218
|
-
i0.ɵɵ
|
|
219
|
-
i0.ɵɵtextInterpolate(ea_r8.entity.Description || "No description");
|
|
259
|
+
i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r9));
|
|
260
|
+
i0.ɵɵattribute("aria-label", "Entity: " + ea_r9.entity.Name);
|
|
261
|
+
i0.ɵɵadvance(3);
|
|
262
|
+
i0.ɵɵattribute("aria-label", "Edit permissions for " + ea_r9.entity.Name);
|
|
220
263
|
i0.ɵɵadvance(3);
|
|
221
|
-
i0.ɵɵ
|
|
264
|
+
i0.ɵɵtextInterpolate(ea_r9.entity.Name);
|
|
265
|
+
i0.ɵɵadvance(2);
|
|
266
|
+
i0.ɵɵtextInterpolate(ea_r9.entity.Description || "No description");
|
|
267
|
+
i0.ɵɵadvance(2);
|
|
268
|
+
i0.ɵɵattribute("aria-label", "Access level: " + ctx_r2.getAccessLevelLabel(ea_r9));
|
|
269
|
+
i0.ɵɵadvance();
|
|
270
|
+
i0.ɵɵclassMap(ctx_r2.getAccessLevelClass(ea_r9) === "access-public" ? "fa-solid fa-globe" : ctx_r2.getAccessLevelClass(ea_r9) === "access-restricted" ? "fa-solid fa-lock" : "fa-solid fa-key");
|
|
222
271
|
i0.ɵɵadvance();
|
|
223
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r2.getAccessLevelLabel(
|
|
272
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r2.getAccessLevelLabel(ea_r9), " ");
|
|
224
273
|
i0.ɵɵadvance();
|
|
225
|
-
i0.ɵɵconditional(
|
|
274
|
+
i0.ɵɵconditional(ea_r9.permissions.length > 0 ? 13 : -1);
|
|
226
275
|
} }
|
|
227
|
-
function
|
|
228
|
-
i0.ɵɵelementStart(0, "div",
|
|
229
|
-
i0.ɵɵrepeaterCreate(1,
|
|
276
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
277
|
+
i0.ɵɵelementStart(0, "div", 61);
|
|
278
|
+
i0.ɵɵrepeaterCreate(1, EntityPermissionsComponent_Conditional_78_Conditional_2_For_2_Template, 14, 11, "article", 94, _forTrack1);
|
|
230
279
|
i0.ɵɵelementEnd();
|
|
231
280
|
} if (rf & 2) {
|
|
232
281
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
233
282
|
i0.ɵɵadvance();
|
|
234
283
|
i0.ɵɵrepeater(ctx_r2.filteredEntityAccess);
|
|
235
284
|
} }
|
|
236
|
-
function
|
|
237
|
-
i0.ɵɵ
|
|
238
|
-
i0.ɵɵ
|
|
239
|
-
i0.ɵɵ
|
|
240
|
-
i0.ɵɵ
|
|
241
|
-
i0.ɵɵ
|
|
242
|
-
i0.ɵɵ
|
|
243
|
-
i0.ɵɵ
|
|
285
|
+
function EntityPermissionsComponent_Conditional_78_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
286
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
287
|
+
i0.ɵɵelementStart(0, "div", 62);
|
|
288
|
+
i0.ɵɵelement(1, "i", 103);
|
|
289
|
+
i0.ɵɵelementStart(2, "h3", 104);
|
|
290
|
+
i0.ɵɵtext(3, "No Permissions Found");
|
|
291
|
+
i0.ɵɵelementEnd();
|
|
292
|
+
i0.ɵɵelementStart(4, "p", 105);
|
|
293
|
+
i0.ɵɵtext(5, "Try adjusting your filters or refresh the data.");
|
|
294
|
+
i0.ɵɵelementEnd();
|
|
295
|
+
i0.ɵɵelementStart(6, "button", 106);
|
|
296
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_78_Conditional_3_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.refreshData()); });
|
|
297
|
+
i0.ɵɵelement(7, "i", 9);
|
|
298
|
+
i0.ɵɵtext(8, " Refresh ");
|
|
244
299
|
i0.ɵɵelementEnd()();
|
|
245
300
|
} }
|
|
246
|
-
function
|
|
247
|
-
i0.ɵɵelementStart(0, "div",
|
|
248
|
-
i0.ɵɵtemplate(1,
|
|
301
|
+
function EntityPermissionsComponent_Conditional_78_Template(rf, ctx) { if (rf & 1) {
|
|
302
|
+
i0.ɵɵelementStart(0, "div", 52);
|
|
303
|
+
i0.ɵɵtemplate(1, EntityPermissionsComponent_Conditional_78_Conditional_1_Template, 3, 0, "div", 60)(2, EntityPermissionsComponent_Conditional_78_Conditional_2_Template, 3, 0, "div", 61)(3, EntityPermissionsComponent_Conditional_78_Conditional_3_Template, 9, 0, "div", 62);
|
|
249
304
|
i0.ɵɵelementEnd();
|
|
250
305
|
} if (rf & 2) {
|
|
251
306
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -254,6 +309,108 @@ function EntityPermissionsComponent_Conditional_70_Template(rf, ctx) { if (rf &
|
|
|
254
309
|
i0.ɵɵadvance(2);
|
|
255
310
|
i0.ɵɵconditional(ctx_r2.filteredEntityAccess.length === 0 ? 3 : -1);
|
|
256
311
|
} }
|
|
312
|
+
function EntityPermissionsComponent_Conditional_80_For_39_Template(rf, ctx) { if (rf & 1) {
|
|
313
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
314
|
+
i0.ɵɵelementStart(0, "label", 118)(1, "input", 129);
|
|
315
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Conditional_80_For_39_Template_input_change_1_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onRoleFilterChange($event)); });
|
|
316
|
+
i0.ɵɵelementEnd();
|
|
317
|
+
i0.ɵɵelementStart(2, "span", 120);
|
|
318
|
+
i0.ɵɵtext(3);
|
|
319
|
+
i0.ɵɵelementEnd()();
|
|
320
|
+
} if (rf & 2) {
|
|
321
|
+
const role_r13 = ctx.$implicit;
|
|
322
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
323
|
+
i0.ɵɵclassProp("selected", ctx_r2.filters$.value.roleId === role_r13.ID);
|
|
324
|
+
i0.ɵɵadvance();
|
|
325
|
+
i0.ɵɵproperty("value", role_r13.ID)("checked", ctx_r2.filters$.value.roleId === role_r13.ID);
|
|
326
|
+
i0.ɵɵadvance(2);
|
|
327
|
+
i0.ɵɵtextInterpolate(role_r13.Name);
|
|
328
|
+
} }
|
|
329
|
+
function EntityPermissionsComponent_Conditional_80_Template(rf, ctx) { if (rf & 1) {
|
|
330
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
331
|
+
i0.ɵɵelementStart(0, "div", 107);
|
|
332
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_80_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showMobileFilters = false); });
|
|
333
|
+
i0.ɵɵelementStart(1, "div", 108);
|
|
334
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_80_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
335
|
+
i0.ɵɵelementStart(2, "div", 109)(3, "h3", 110);
|
|
336
|
+
i0.ɵɵelement(4, "i", 37);
|
|
337
|
+
i0.ɵɵtext(5, " Filters ");
|
|
338
|
+
i0.ɵɵelementEnd();
|
|
339
|
+
i0.ɵɵelementStart(6, "button", 111);
|
|
340
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_80_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showMobileFilters = false); });
|
|
341
|
+
i0.ɵɵelement(7, "i", 112);
|
|
342
|
+
i0.ɵɵelementEnd()();
|
|
343
|
+
i0.ɵɵelementStart(8, "div", 113)(9, "div", 114)(10, "div", 115)(11, "h4", 116);
|
|
344
|
+
i0.ɵɵtext(12, "Access Level");
|
|
345
|
+
i0.ɵɵelementEnd();
|
|
346
|
+
i0.ɵɵelementStart(13, "div", 117)(14, "label", 118)(15, "input", 119);
|
|
347
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Conditional_80_Template_input_change_15_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onAccessLevelChange("all")); });
|
|
348
|
+
i0.ɵɵelementEnd();
|
|
349
|
+
i0.ɵɵelementStart(16, "span", 120);
|
|
350
|
+
i0.ɵɵtext(17, "All Levels");
|
|
351
|
+
i0.ɵɵelementEnd()();
|
|
352
|
+
i0.ɵɵelementStart(18, "label", 118)(19, "input", 121);
|
|
353
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Conditional_80_Template_input_change_19_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onAccessLevelChange("public")); });
|
|
354
|
+
i0.ɵɵelementEnd();
|
|
355
|
+
i0.ɵɵelementStart(20, "span", 120);
|
|
356
|
+
i0.ɵɵtext(21, "Public Entities");
|
|
357
|
+
i0.ɵɵelementEnd()();
|
|
358
|
+
i0.ɵɵelementStart(22, "label", 118)(23, "input", 122);
|
|
359
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Conditional_80_Template_input_change_23_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onAccessLevelChange("restricted")); });
|
|
360
|
+
i0.ɵɵelementEnd();
|
|
361
|
+
i0.ɵɵelementStart(24, "span", 120);
|
|
362
|
+
i0.ɵɵtext(25, "Restricted Entities");
|
|
363
|
+
i0.ɵɵelementEnd()();
|
|
364
|
+
i0.ɵɵelementStart(26, "label", 118)(27, "input", 123);
|
|
365
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Conditional_80_Template_input_change_27_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onAccessLevelChange("custom")); });
|
|
366
|
+
i0.ɵɵelementEnd();
|
|
367
|
+
i0.ɵɵelementStart(28, "span", 120);
|
|
368
|
+
i0.ɵɵtext(29, "Custom Access Entities");
|
|
369
|
+
i0.ɵɵelementEnd()()()();
|
|
370
|
+
i0.ɵɵelementStart(30, "div", 115)(31, "h4", 116);
|
|
371
|
+
i0.ɵɵtext(32, "Filter by Role");
|
|
372
|
+
i0.ɵɵelementEnd();
|
|
373
|
+
i0.ɵɵelementStart(33, "div", 117)(34, "label", 118)(35, "input", 124);
|
|
374
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Conditional_80_Template_input_change_35_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onRoleFilterChange($event)); });
|
|
375
|
+
i0.ɵɵelementEnd();
|
|
376
|
+
i0.ɵɵelementStart(36, "span", 120);
|
|
377
|
+
i0.ɵɵtext(37, "All Roles");
|
|
378
|
+
i0.ɵɵelementEnd()();
|
|
379
|
+
i0.ɵɵrepeaterCreate(38, EntityPermissionsComponent_Conditional_80_For_39_Template, 4, 5, "label", 125, _forTrack0);
|
|
380
|
+
i0.ɵɵelementEnd()()()();
|
|
381
|
+
i0.ɵɵelementStart(40, "div", 126)(41, "button", 127);
|
|
382
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_80_Template_button_click_41_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showMobileFilters = false); });
|
|
383
|
+
i0.ɵɵtext(42, " Apply Filters ");
|
|
384
|
+
i0.ɵɵelementEnd();
|
|
385
|
+
i0.ɵɵelementStart(43, "button", 128);
|
|
386
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Conditional_80_Template_button_click_43_listener() { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.showMobileFilters = false); });
|
|
387
|
+
i0.ɵɵtext(44, " Cancel ");
|
|
388
|
+
i0.ɵɵelementEnd()()()();
|
|
389
|
+
} if (rf & 2) {
|
|
390
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
391
|
+
i0.ɵɵadvance(14);
|
|
392
|
+
i0.ɵɵclassProp("selected", ctx_r2.filters$.value.accessLevel === "all");
|
|
393
|
+
i0.ɵɵadvance();
|
|
394
|
+
i0.ɵɵproperty("checked", ctx_r2.filters$.value.accessLevel === "all");
|
|
395
|
+
i0.ɵɵadvance(3);
|
|
396
|
+
i0.ɵɵclassProp("selected", ctx_r2.filters$.value.accessLevel === "public");
|
|
397
|
+
i0.ɵɵadvance();
|
|
398
|
+
i0.ɵɵproperty("checked", ctx_r2.filters$.value.accessLevel === "public");
|
|
399
|
+
i0.ɵɵadvance(3);
|
|
400
|
+
i0.ɵɵclassProp("selected", ctx_r2.filters$.value.accessLevel === "restricted");
|
|
401
|
+
i0.ɵɵadvance();
|
|
402
|
+
i0.ɵɵproperty("checked", ctx_r2.filters$.value.accessLevel === "restricted");
|
|
403
|
+
i0.ɵɵadvance(3);
|
|
404
|
+
i0.ɵɵclassProp("selected", ctx_r2.filters$.value.accessLevel === "custom");
|
|
405
|
+
i0.ɵɵadvance();
|
|
406
|
+
i0.ɵɵproperty("checked", ctx_r2.filters$.value.accessLevel === "custom");
|
|
407
|
+
i0.ɵɵadvance(7);
|
|
408
|
+
i0.ɵɵclassProp("selected", !ctx_r2.filters$.value.roleId);
|
|
409
|
+
i0.ɵɵadvance();
|
|
410
|
+
i0.ɵɵproperty("checked", !ctx_r2.filters$.value.roleId);
|
|
411
|
+
i0.ɵɵadvance(3);
|
|
412
|
+
i0.ɵɵrepeater(ctx_r2.roles);
|
|
413
|
+
} }
|
|
257
414
|
let EntityPermissionsComponent = class EntityPermissionsComponent extends BaseDashboard {
|
|
258
415
|
// State management
|
|
259
416
|
entityAccess = [];
|
|
@@ -280,6 +437,7 @@ let EntityPermissionsComponent = class EntityPermissionsComponent extends BaseDa
|
|
|
280
437
|
// UI State
|
|
281
438
|
expandedEntityId = null;
|
|
282
439
|
viewMode = 'list';
|
|
440
|
+
showMobileFilters = false;
|
|
283
441
|
destroy$ = new Subject();
|
|
284
442
|
metadata = new Metadata();
|
|
285
443
|
constructor() {
|
|
@@ -515,104 +673,117 @@ let EntityPermissionsComponent = class EntityPermissionsComponent extends BaseDa
|
|
|
515
673
|
this.viewMode = mode;
|
|
516
674
|
}
|
|
517
675
|
static ɵfac = function EntityPermissionsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EntityPermissionsComponent)(); };
|
|
518
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityPermissionsComponent, selectors: [["mj-entity-permissions"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
519
|
-
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "
|
|
520
|
-
i0.ɵɵlistener("click", function
|
|
521
|
-
i0.ɵɵelement(
|
|
676
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityPermissionsComponent, selectors: [["mj-entity-permissions"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 81, vars: 34, consts: [[1, "entity-permissions-container"], [1, "sticky-header"], ["role", "toolbar", "aria-label", "Entity permissions actions", 1, "action-buttons"], [1, "mj-view-toggle"], ["role", "button", "tabindex", "0", "title", "List View", 1, "mj-btn", "mj-btn-ghost", 3, "click", "keydown.enter", "keydown.space"], ["aria-hidden", "true", 1, "fa-solid", "fa-list"], ["role", "button", "tabindex", "0", "title", "Grid View", 1, "mj-btn", "mj-btn-ghost", 3, "click", "keydown.enter", "keydown.space"], ["aria-hidden", "true", 1, "fa-solid", "fa-th"], ["aria-label", "Refresh entity permissions data", "title", "Refresh", 1, "mj-btn", "mj-btn-secondary", "mj-btn-icon-mobile", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "btn-text"], ["role", "region", "aria-label", "Permission statistics", 1, "mj-grid-4"], ["role", "article", "aria-label", "Total entities statistic", 1, "mj-card"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-total"], [1, "fa-solid", "fa-database"], [1, "stat-content"], ["aria-label", "Total entities count", 1, "stat-value"], [1, "stat-label"], ["role", "article", "aria-label", "Public entities statistic", 1, "mj-card"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-public"], [1, "fa-solid", "fa-globe"], ["aria-label", "Public entities count", 1, "stat-value"], ["role", "article", "aria-label", "Restricted entities statistic", 1, "mj-card"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-restricted"], [1, "fa-solid", "fa-lock"], ["aria-label", "Restricted entities count", 1, "stat-value"], ["role", "article", "aria-label", "Total permissions statistic", 1, "mj-card"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-permissions"], [1, "fa-solid", "fa-key"], ["aria-label", "Total permissions count", 1, "stat-value"], ["role", "search", "aria-label", "Entity filters", 1, "filters-section"], [1, "filters-row"], [1, "mobile-search-container"], [1, "mj-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "mj-search-icon"], ["type", "text", "placeholder", "Search entities by name or description...", "aria-label", "Search entities", 1, "mj-search-input", 3, "input", "value"], ["aria-label", "Open filters", 1, "filter-button", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "mj-filter-group"], ["id", "access-level-label", 1, "mj-filter-label"], ["role", "group", "aria-labelledby", "access-level-label", 1, "mj-filter-buttons"], ["aria-label", "Show all access levels", 1, "mj-btn", "mj-btn-ghost", 3, "click"], ["aria-label", "Show only public entities", 1, "mj-btn", "mj-btn-ghost", 3, "click"], ["aria-label", "Show only restricted entities", 1, "mj-btn", "mj-btn-ghost", 3, "click"], ["aria-label", "Show only custom access entities", 1, "mj-btn", "mj-btn-ghost", 3, "click"], ["for", "role-filter", 1, "mj-filter-label"], ["id", "role-filter", "aria-label", "Filter entities by role", 1, "mj-filter-select", 3, "change"], ["value", ""], [3, "value"], [1, "scrollable-content"], ["role", "status", "aria-live", "polite", "aria-busy", "true", 1, "loading-container"], ["role", "alert", "aria-live", "assertive", 1, "error-container"], [1, "content-area"], [3, "result", "visible", "data"], ["role", "presentation", 1, "filter-modal-backdrop"], ["text", "Loading entity permissions...", "size", "medium"], [1, "error-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], ["aria-label", "Retry loading entity permissions", 1, "mj-btn", "mj-btn-primary", 3, "click"], ["role", "list", "aria-label", "Entity permissions list", 1, "entities-list"], ["role", "list", "aria-label", "Entity permissions grid", 1, "entities-grid"], ["role", "status", 1, "empty-state"], ["role", "listitem", 1, "entity-card", 3, "expanded"], ["role", "listitem", 1, "entity-card"], ["tabindex", "0", "role", "button", 1, "entity-header", 3, "click", "keydown.enter", "keydown.space"], [1, "entity-info"], ["aria-hidden", "true", 1, "entity-icon-wrapper"], [1, "fa-solid", "fa-table"], [1, "entity-details"], [1, "entity-name"], [1, "entity-description"], [1, "entity-meta"], [1, "access-badge"], ["aria-hidden", "true"], [1, "entity-actions", 3, "click"], ["title", "Edit Permissions", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-edit"], [1, "expand-btn"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down"], ["role", "region", 1, "entity-content"], [1, "mobile-actions-bar", 3, "click"], [1, "mobile-action-buttons"], [1, "btn-label"], ["role", "table", "aria-label", "Role permissions", 1, "permissions-grid"], [1, "no-permissions"], ["role", "rowgroup", 1, "permissions-header"], ["role", "row"], ["scope", "col", "role", "columnheader", 1, "role-header"], ["scope", "col", "role", "columnheader", 1, "permission-header"], ["role", "rowgroup"], ["role", "row", 1, "permission-row"], ["role", "cell", 1, "role-name"], ["role", "cell", 1, "permission-cell"], [1, "entity-grid-card", 3, "class"], [1, "entity-grid-card"], [1, "grid-card-header"], ["aria-hidden", "true", 1, "fa-solid", "fa-table"], [1, "grid-card-title"], [1, "grid-card-description"], [1, "grid-card-footer"], [1, "access-label"], [1, "permission-count"], ["aria-hidden", "true", 1, "fa-solid", "fa-shield-alt", "empty-state-icon"], [1, "empty-text"], [1, "empty-subtext"], ["aria-label", "Refresh permissions data", 1, "mj-btn", "mj-btn-primary", 3, "click"], ["role", "presentation", 1, "filter-modal-backdrop", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "filter-modal-title", 1, "filter-modal", 3, "click"], [1, "filter-modal-header"], ["id", "filter-modal-title", 1, "filter-modal-title"], ["aria-label", "Close filters", 1, "filter-modal-close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], [1, "filter-modal-body"], [1, "filter-options-container"], [1, "filter-group"], [1, "filter-group-label"], [1, "filter-group-options"], [1, "filter-option"], ["type", "radio", "name", "accessLevel", "value", "all", 3, "change", "checked"], [1, "filter-option-label"], ["type", "radio", "name", "accessLevel", "value", "public", 3, "change", "checked"], ["type", "radio", "name", "accessLevel", "value", "restricted", 3, "change", "checked"], ["type", "radio", "name", "accessLevel", "value", "custom", 3, "change", "checked"], ["type", "radio", "name", "role", "value", "", 3, "change", "checked"], [1, "filter-option", 3, "selected"], [1, "filter-modal-footer"], [1, "mj-btn", "mj-btn-primary", 3, "click"], [1, "mj-btn", "mj-btn-secondary", 3, "click"], ["type", "radio", "name", "role", 3, "change", "value", "checked"]], template: function EntityPermissionsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
677
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "div", 3)(4, "button", 4);
|
|
678
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_4_listener() { return ctx.setViewMode("list"); })("keydown.enter", function EntityPermissionsComponent_Template_button_keydown_enter_4_listener() { return ctx.setViewMode("list"); })("keydown.space", function EntityPermissionsComponent_Template_button_keydown_space_4_listener($event) { ctx.setViewMode("list"); return $event.preventDefault(); });
|
|
679
|
+
i0.ɵɵelement(5, "i", 5);
|
|
522
680
|
i0.ɵɵelementEnd();
|
|
523
|
-
i0.ɵɵelementStart(
|
|
524
|
-
i0.ɵɵlistener("click", function
|
|
525
|
-
i0.ɵɵelement(
|
|
526
|
-
i0.ɵɵelementEnd()();
|
|
527
|
-
i0.ɵɵelementStart(7, "button", 7);
|
|
528
|
-
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_7_listener() { return ctx.refreshData(); });
|
|
529
|
-
i0.ɵɵelement(8, "i", 8);
|
|
530
|
-
i0.ɵɵtext(9, " Refresh ");
|
|
681
|
+
i0.ɵɵelementStart(6, "button", 6);
|
|
682
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_6_listener() { return ctx.setViewMode("grid"); })("keydown.enter", function EntityPermissionsComponent_Template_button_keydown_enter_6_listener() { return ctx.setViewMode("grid"); })("keydown.space", function EntityPermissionsComponent_Template_button_keydown_space_6_listener($event) { ctx.setViewMode("grid"); return $event.preventDefault(); });
|
|
683
|
+
i0.ɵɵelement(7, "i", 7);
|
|
531
684
|
i0.ɵɵelementEnd()();
|
|
532
|
-
i0.ɵɵelementStart(
|
|
533
|
-
i0.ɵɵ
|
|
685
|
+
i0.ɵɵelementStart(8, "button", 8);
|
|
686
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_8_listener() { return ctx.refreshData(); });
|
|
687
|
+
i0.ɵɵelement(9, "i", 9);
|
|
688
|
+
i0.ɵɵelementStart(10, "span", 10);
|
|
689
|
+
i0.ɵɵtext(11, "Refresh");
|
|
690
|
+
i0.ɵɵelementEnd()()();
|
|
691
|
+
i0.ɵɵelementStart(12, "div", 11)(13, "div", 12)(14, "div", 13);
|
|
692
|
+
i0.ɵɵelement(15, "i", 14);
|
|
534
693
|
i0.ɵɵelementEnd();
|
|
535
|
-
i0.ɵɵelementStart(
|
|
536
|
-
i0.ɵɵtext(
|
|
694
|
+
i0.ɵɵelementStart(16, "div", 15)(17, "div", 16);
|
|
695
|
+
i0.ɵɵtext(18);
|
|
537
696
|
i0.ɵɵelementEnd();
|
|
538
|
-
i0.ɵɵelementStart(
|
|
539
|
-
i0.ɵɵtext(
|
|
697
|
+
i0.ɵɵelementStart(19, "div", 17);
|
|
698
|
+
i0.ɵɵtext(20, "Total Entities");
|
|
540
699
|
i0.ɵɵelementEnd()()();
|
|
541
|
-
i0.ɵɵelementStart(
|
|
542
|
-
i0.ɵɵelement(
|
|
700
|
+
i0.ɵɵelementStart(21, "div", 18)(22, "div", 19);
|
|
701
|
+
i0.ɵɵelement(23, "i", 20);
|
|
543
702
|
i0.ɵɵelementEnd();
|
|
544
|
-
i0.ɵɵelementStart(
|
|
545
|
-
i0.ɵɵtext(
|
|
703
|
+
i0.ɵɵelementStart(24, "div", 15)(25, "div", 21);
|
|
704
|
+
i0.ɵɵtext(26);
|
|
546
705
|
i0.ɵɵelementEnd();
|
|
547
|
-
i0.ɵɵelementStart(
|
|
548
|
-
i0.ɵɵtext(
|
|
706
|
+
i0.ɵɵelementStart(27, "div", 17);
|
|
707
|
+
i0.ɵɵtext(28, "Public Entities");
|
|
549
708
|
i0.ɵɵelementEnd()()();
|
|
550
|
-
i0.ɵɵelementStart(
|
|
551
|
-
i0.ɵɵelement(
|
|
709
|
+
i0.ɵɵelementStart(29, "div", 22)(30, "div", 23);
|
|
710
|
+
i0.ɵɵelement(31, "i", 24);
|
|
552
711
|
i0.ɵɵelementEnd();
|
|
553
|
-
i0.ɵɵelementStart(
|
|
554
|
-
i0.ɵɵtext(
|
|
712
|
+
i0.ɵɵelementStart(32, "div", 15)(33, "div", 25);
|
|
713
|
+
i0.ɵɵtext(34);
|
|
555
714
|
i0.ɵɵelementEnd();
|
|
556
|
-
i0.ɵɵelementStart(
|
|
557
|
-
i0.ɵɵtext(
|
|
715
|
+
i0.ɵɵelementStart(35, "div", 17);
|
|
716
|
+
i0.ɵɵtext(36, "Restricted Entities");
|
|
558
717
|
i0.ɵɵelementEnd()()();
|
|
559
|
-
i0.ɵɵelementStart(
|
|
560
|
-
i0.ɵɵelement(
|
|
718
|
+
i0.ɵɵelementStart(37, "div", 26)(38, "div", 27);
|
|
719
|
+
i0.ɵɵelement(39, "i", 28);
|
|
561
720
|
i0.ɵɵelementEnd();
|
|
562
|
-
i0.ɵɵelementStart(
|
|
563
|
-
i0.ɵɵtext(
|
|
721
|
+
i0.ɵɵelementStart(40, "div", 15)(41, "div", 29);
|
|
722
|
+
i0.ɵɵtext(42);
|
|
564
723
|
i0.ɵɵelementEnd();
|
|
565
|
-
i0.ɵɵelementStart(
|
|
566
|
-
i0.ɵɵtext(
|
|
724
|
+
i0.ɵɵelementStart(43, "div", 17);
|
|
725
|
+
i0.ɵɵtext(44, "Total Permissions");
|
|
567
726
|
i0.ɵɵelementEnd()()()();
|
|
568
|
-
i0.ɵɵelementStart(
|
|
569
|
-
i0.ɵɵelement(
|
|
570
|
-
i0.ɵɵelementStart(
|
|
571
|
-
i0.ɵɵlistener("input", function
|
|
727
|
+
i0.ɵɵelementStart(45, "div", 30)(46, "div", 31)(47, "div", 32)(48, "div", 33);
|
|
728
|
+
i0.ɵɵelement(49, "i", 34);
|
|
729
|
+
i0.ɵɵelementStart(50, "input", 35);
|
|
730
|
+
i0.ɵɵlistener("input", function EntityPermissionsComponent_Template_input_input_50_listener($event) { return ctx.onSearchChange($event); });
|
|
572
731
|
i0.ɵɵelementEnd()();
|
|
573
|
-
i0.ɵɵelementStart(
|
|
574
|
-
i0.ɵɵ
|
|
732
|
+
i0.ɵɵelementStart(51, "button", 36);
|
|
733
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_51_listener() { return ctx.showMobileFilters = true; });
|
|
734
|
+
i0.ɵɵelement(52, "i", 37);
|
|
735
|
+
i0.ɵɵelementStart(53, "span");
|
|
736
|
+
i0.ɵɵtext(54, "Filters");
|
|
737
|
+
i0.ɵɵelementEnd()()();
|
|
738
|
+
i0.ɵɵelementStart(55, "div", 38)(56, "label", 39);
|
|
739
|
+
i0.ɵɵtext(57, "Access Level");
|
|
575
740
|
i0.ɵɵelementEnd();
|
|
576
|
-
i0.ɵɵelementStart(
|
|
577
|
-
i0.ɵɵlistener("click", function
|
|
578
|
-
i0.ɵɵtext(
|
|
741
|
+
i0.ɵɵelementStart(58, "div", 40)(59, "button", 41);
|
|
742
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_59_listener() { return ctx.onAccessLevelChange("all"); });
|
|
743
|
+
i0.ɵɵtext(60, " All ");
|
|
579
744
|
i0.ɵɵelementEnd();
|
|
580
|
-
i0.ɵɵelementStart(
|
|
581
|
-
i0.ɵɵlistener("click", function
|
|
582
|
-
i0.ɵɵtext(
|
|
745
|
+
i0.ɵɵelementStart(61, "button", 42);
|
|
746
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_61_listener() { return ctx.onAccessLevelChange("public"); });
|
|
747
|
+
i0.ɵɵtext(62, " Public ");
|
|
583
748
|
i0.ɵɵelementEnd();
|
|
584
|
-
i0.ɵɵelementStart(
|
|
585
|
-
i0.ɵɵlistener("click", function
|
|
586
|
-
i0.ɵɵtext(
|
|
749
|
+
i0.ɵɵelementStart(63, "button", 43);
|
|
750
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_63_listener() { return ctx.onAccessLevelChange("restricted"); });
|
|
751
|
+
i0.ɵɵtext(64, " Restricted ");
|
|
587
752
|
i0.ɵɵelementEnd();
|
|
588
|
-
i0.ɵɵelementStart(
|
|
589
|
-
i0.ɵɵlistener("click", function
|
|
590
|
-
i0.ɵɵtext(
|
|
753
|
+
i0.ɵɵelementStart(65, "button", 44);
|
|
754
|
+
i0.ɵɵlistener("click", function EntityPermissionsComponent_Template_button_click_65_listener() { return ctx.onAccessLevelChange("custom"); });
|
|
755
|
+
i0.ɵɵtext(66, " Custom ");
|
|
591
756
|
i0.ɵɵelementEnd()()();
|
|
592
|
-
i0.ɵɵelementStart(
|
|
593
|
-
i0.ɵɵtext(
|
|
757
|
+
i0.ɵɵelementStart(67, "div", 38)(68, "label", 45);
|
|
758
|
+
i0.ɵɵtext(69, "Filter by Role");
|
|
594
759
|
i0.ɵɵelementEnd();
|
|
595
|
-
i0.ɵɵelementStart(
|
|
596
|
-
i0.ɵɵlistener("change", function
|
|
597
|
-
i0.ɵɵelementStart(
|
|
598
|
-
i0.ɵɵtext(
|
|
760
|
+
i0.ɵɵelementStart(70, "select", 46);
|
|
761
|
+
i0.ɵɵlistener("change", function EntityPermissionsComponent_Template_select_change_70_listener($event) { return ctx.onRoleFilterChange($event); });
|
|
762
|
+
i0.ɵɵelementStart(71, "option", 47);
|
|
763
|
+
i0.ɵɵtext(72, "All Roles");
|
|
764
|
+
i0.ɵɵelementEnd();
|
|
765
|
+
i0.ɵɵrepeaterCreate(73, EntityPermissionsComponent_For_74_Template, 2, 2, "option", 48, _forTrack0);
|
|
766
|
+
i0.ɵɵelementEnd()()()()();
|
|
767
|
+
i0.ɵɵelementStart(75, "div", 49);
|
|
768
|
+
i0.ɵɵtemplate(76, EntityPermissionsComponent_Conditional_76_Template, 2, 0, "div", 50)(77, EntityPermissionsComponent_Conditional_77_Template, 8, 1, "div", 51)(78, EntityPermissionsComponent_Conditional_78_Template, 4, 2, "div", 52);
|
|
769
|
+
i0.ɵɵelementEnd();
|
|
770
|
+
i0.ɵɵelementStart(79, "mj-permission-dialog", 53);
|
|
771
|
+
i0.ɵɵlistener("result", function EntityPermissionsComponent_Template_mj_permission_dialog_result_79_listener($event) { return ctx.onPermissionDialogResult($event); });
|
|
772
|
+
i0.ɵɵelementEnd();
|
|
773
|
+
i0.ɵɵtemplate(80, EntityPermissionsComponent_Conditional_80_Template, 45, 15, "div", 54);
|
|
599
774
|
i0.ɵɵelementEnd();
|
|
600
|
-
i0.ɵɵrepeaterCreate(66, EntityPermissionsComponent_For_67_Template, 2, 2, "option", 33, _forTrack0);
|
|
601
|
-
i0.ɵɵelementEnd()()()();
|
|
602
|
-
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);
|
|
603
|
-
i0.ɵɵelementStart(71, "mj-permission-dialog", 37);
|
|
604
|
-
i0.ɵɵlistener("result", function EntityPermissionsComponent_Template_mj_permission_dialog_result_71_listener($event) { return ctx.onPermissionDialogResult($event); });
|
|
605
|
-
i0.ɵɵelementEnd()();
|
|
606
775
|
} if (rf & 2) {
|
|
607
|
-
i0.ɵɵadvance(
|
|
776
|
+
i0.ɵɵadvance(4);
|
|
608
777
|
i0.ɵɵclassProp("mj-btn-primary", ctx.viewMode === "list");
|
|
778
|
+
i0.ɵɵattribute("aria-label", "List view" + (ctx.viewMode === "list" ? " (active)" : ""))("aria-pressed", ctx.viewMode === "list");
|
|
609
779
|
i0.ɵɵadvance(2);
|
|
610
780
|
i0.ɵɵclassProp("mj-btn-primary", ctx.viewMode === "grid");
|
|
781
|
+
i0.ɵɵattribute("aria-label", "Grid view" + (ctx.viewMode === "grid" ? " (active)" : ""))("aria-pressed", ctx.viewMode === "grid");
|
|
611
782
|
i0.ɵɵadvance(2);
|
|
612
783
|
i0.ɵɵproperty("disabled", ctx.isLoading);
|
|
613
784
|
i0.ɵɵadvance();
|
|
614
785
|
i0.ɵɵclassProp("fa-spin", ctx.isLoading);
|
|
615
|
-
i0.ɵɵadvance(
|
|
786
|
+
i0.ɵɵadvance(9);
|
|
616
787
|
i0.ɵɵtextInterpolate(ctx.stats.totalEntities);
|
|
617
788
|
i0.ɵɵadvance(8);
|
|
618
789
|
i0.ɵɵtextInterpolate(ctx.stats.publicEntities);
|
|
@@ -620,27 +791,33 @@ let EntityPermissionsComponent = class EntityPermissionsComponent extends BaseDa
|
|
|
620
791
|
i0.ɵɵtextInterpolate(ctx.stats.restrictedEntities);
|
|
621
792
|
i0.ɵɵadvance(8);
|
|
622
793
|
i0.ɵɵtextInterpolate(ctx.stats.totalPermissions);
|
|
623
|
-
i0.ɵɵadvance(
|
|
794
|
+
i0.ɵɵadvance(8);
|
|
624
795
|
i0.ɵɵproperty("value", ctx.filters$.value.entitySearch);
|
|
625
|
-
i0.ɵɵadvance(
|
|
796
|
+
i0.ɵɵadvance(9);
|
|
626
797
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.accessLevel === "all");
|
|
798
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.accessLevel === "all");
|
|
627
799
|
i0.ɵɵadvance(2);
|
|
628
800
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.accessLevel === "public");
|
|
801
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.accessLevel === "public");
|
|
629
802
|
i0.ɵɵadvance(2);
|
|
630
803
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.accessLevel === "restricted");
|
|
804
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.accessLevel === "restricted");
|
|
631
805
|
i0.ɵɵadvance(2);
|
|
632
806
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.accessLevel === "custom");
|
|
807
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.accessLevel === "custom");
|
|
633
808
|
i0.ɵɵadvance(8);
|
|
634
809
|
i0.ɵɵrepeater(ctx.roles);
|
|
635
|
-
i0.ɵɵadvance(
|
|
636
|
-
i0.ɵɵconditional(ctx.isLoading ?
|
|
810
|
+
i0.ɵɵadvance(3);
|
|
811
|
+
i0.ɵɵconditional(ctx.isLoading ? 76 : -1);
|
|
637
812
|
i0.ɵɵadvance();
|
|
638
|
-
i0.ɵɵconditional(ctx.error && !ctx.isLoading ?
|
|
813
|
+
i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 77 : -1);
|
|
639
814
|
i0.ɵɵadvance();
|
|
640
|
-
i0.ɵɵconditional(!ctx.isLoading && !ctx.error ?
|
|
815
|
+
i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 78 : -1);
|
|
641
816
|
i0.ɵɵadvance();
|
|
642
817
|
i0.ɵɵproperty("visible", ctx.showPermissionDialog)("data", ctx.permissionDialogData);
|
|
643
|
-
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i2.PermissionDialogComponent], styles: ["@keyframes _ngcontent-%COMP%_shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.entity-permissions-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n overflow: hidden;\n position: relative;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\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 .action-buttons[_ngcontent-%COMP%] {\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.view-btn[_ngcontent-%COMP%]:hover {\n color: #374151;\n}\n.view-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #2196f3;\n color: white;\n}\n.btn-primary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n.btn-primary[_ngcontent-%COMP%]:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n}\n.btn-secondary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-secondary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n.btn-secondary[_ngcontent-%COMP%]:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n}\n\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 .stats-grid[_ngcontent-%COMP%] {\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;\n}\n.stat-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\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.stat-icon-total[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n}\n.stat-icon-public[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n}\n.stat-icon-restricted[_ngcontent-%COMP%] {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n}\n.stat-icon-permissions[_ngcontent-%COMP%] {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n.stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n}\n.stat-content[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n}\n\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-container[_ngcontent-%COMP%] .search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n}\n.search-container[_ngcontent-%COMP%] .search-input[_ngcontent-%COMP%] {\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.search-container[_ngcontent-%COMP%] .search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.filter-group[_ngcontent-%COMP%] .filter-label[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 500;\n color: #374151;\n}\n.filter-group[_ngcontent-%COMP%] .filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n}\n.filter-group[_ngcontent-%COMP%] .filter-btn[_ngcontent-%COMP%] {\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.filter-group[_ngcontent-%COMP%] .filter-btn[_ngcontent-%COMP%]:hover {\n color: #374151;\n}\n.filter-group[_ngcontent-%COMP%] .filter-btn.active[_ngcontent-%COMP%] {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%] {\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.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\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.entities-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n max-height: calc(100vh - 450px);\n overflow-y: auto;\n padding-right: 0.5rem;\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.entity-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n.entity-card.expanded[_ngcontent-%COMP%] {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n.entity-card.expanded[_ngcontent-%COMP%] .expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transform: rotate(180deg);\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.entity-header[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\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-details[_ngcontent-%COMP%] .entity-name[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n}\n.entity-details[_ngcontent-%COMP%] .entity-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0;\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-badge.access-public[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n}\n.access-badge.access-restricted[_ngcontent-%COMP%] {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n}\n.access-badge.access-custom[_ngcontent-%COMP%] {\n background: rgba(156, 39, 176, 0.1);\n color: #7b1fa2;\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.action-btn[_ngcontent-%COMP%]:hover {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\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.expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.3s ease;\n}\n\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.permission-row[_ngcontent-%COMP%]:hover {\n background: white;\n}\n.permission-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\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.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.entity-grid-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n.entity-grid-card.access-public[_ngcontent-%COMP%] {\n border-left: 4px solid #4caf50;\n}\n.entity-grid-card.access-restricted[_ngcontent-%COMP%] {\n border-left: 4px solid #f44336;\n}\n.entity-grid-card.access-custom[_ngcontent-%COMP%] {\n border-left: 4px solid #9c27b0;\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.edit-btn[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n color: #2196f3;\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.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n}\n.empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n}\n.empty-state[_ngcontent-%COMP%] .empty-text[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n}\n.empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n color: #6b7280;\n margin: 0;\n}\n\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.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%] {\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.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%]:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n}\n.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%]:nth-child(2) {\n border-color: transparent #9c27b0 transparent transparent;\n animation-delay: -0.3s;\n}\n.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%]:nth-child(3) {\n border-color: transparent transparent #4caf50 transparent;\n animation-delay: -0.15s;\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.loading-text[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n.error-container[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n}\n.error-container[_ngcontent-%COMP%] .error-icon[_ngcontent-%COMP%] {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n}\n.error-container[_ngcontent-%COMP%] .error-message[_ngcontent-%COMP%] {\n color: #374151;\n margin-bottom: 1.5rem;\n}\n.error-container[_ngcontent-%COMP%] .retry-button[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #2196f3;\n color: white;\n}\n.error-container[_ngcontent-%COMP%] .retry-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.error-container[_ngcontent-%COMP%] .retry-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\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: _ngcontent-%COMP%_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-dialog.modal-large[_ngcontent-%COMP%] {\n max-width: 800px;\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-header[_ngcontent-%COMP%] .modal-title[_ngcontent-%COMP%] {\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.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%] {\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.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n color: #374151;\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n max-height: 60vh;\n overflow-y: auto;\n}\n.modal-body[_ngcontent-%COMP%] .modal-description[_ngcontent-%COMP%] {\n color: #374151;\n margin: 0 0 1.5rem 0;\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.permission-editor[_ngcontent-%COMP%] .coming-soon[_ngcontent-%COMP%] {\n color: #6b7280;\n margin: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n 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@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}\n.btn-edit[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n background: white;\n color: #666666;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n.btn-edit[_ngcontent-%COMP%]:hover {\n background: #f8f9fa;\n border-color: #2196f3;\n color: #2196f3;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);\n}\n.btn-edit[_ngcontent-%COMP%]:active {\n transform: translateY(0);\n}"] });
|
|
818
|
+
i0.ɵɵadvance();
|
|
819
|
+
i0.ɵɵconditional(ctx.showMobileFilters ? 80 : -1);
|
|
820
|
+
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i2.LoadingComponent, i3.PermissionDialogComponent], styles: ["\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n \n\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n \n\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n \n\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n \n\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n \n\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n \n\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n \n\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n \n\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n\n.entity-permissions-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n position: relative;\n max-width: 1920px;\n margin: 0 auto;\n width: 100%;\n background: var(--md-surface);\n}\n\n\n\n\n\n.sticky-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: var(--md-surface-container-lowest);\n padding: 1rem;\n border-bottom: 1px solid var(--md-outline-variant);\n box-shadow: var(--md-elevation-1);\n z-index: 10;\n}\n\n@media (min-width: 640px) {\n .sticky-header[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .sticky-header[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .sticky-header[_ngcontent-%COMP%] {\n padding: 1.5rem 2rem;\n }\n}\n\n\n\n\n\n.scrollable-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n padding: 1rem;\n background: var(--md-surface-container-low);\n}\n\n@media (min-width: 640px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 1.5rem 2rem;\n }\n}\n\n\n\n\n\n.mj-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n font-size: 0.875rem;\n font-weight: 600;\n border: none;\n border-radius: var(--md-corner-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-width: 44px;\n min-height: 44px;\n text-decoration: none;\n}\n\n.mj-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.mj-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n\n\n.mj-btn-primary[_ngcontent-%COMP%], \n.mj-btn.mj-btn-primary[_ngcontent-%COMP%] {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled), \n.mj-btn.mj-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.mj-btn-primary[_ngcontent-%COMP%]:active:not(:disabled), \n.mj-btn.mj-btn-primary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n\n\n.mj-btn-secondary[_ngcontent-%COMP%] {\n background: var(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.mj-btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.mj-btn-secondary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\n}\n\n\n\n.mj-btn-ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--md-on-surface-variant);\n padding: 0.75rem 1rem;\n}\n\n.mj-btn-ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.mj-btn-ghost[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #005A8C;\n}\n\n\n\n.mj-btn-icon-only[_ngcontent-%COMP%] {\n padding: 0.625rem;\n min-width: 44px;\n min-height: 44px;\n}\n\n\n\n.mj-btn-sm[_ngcontent-%COMP%] {\n padding: 0.5rem 0.875rem;\n min-height: 36px;\n min-width: 36px;\n font-size: 0.8125rem;\n}\n\n\n\n.mj-btn-icon-mobile[_ngcontent-%COMP%] {\n padding: 0.75rem 1.5rem;\n}\n\n@media (min-width: 640px) {\n .mj-btn-icon-mobile[_ngcontent-%COMP%] {\n padding: 0.75rem 1.5rem;\n }\n}\n\n@media (max-width: 639px) {\n .mj-btn-icon-mobile[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%] {\n display: none;\n }\n\n .mj-btn-icon-mobile[_ngcontent-%COMP%] {\n padding: 0.625rem;\n gap: 0;\n }\n}\n\n\n\n\n\n.action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: space-between;\n margin-bottom: 1rem;\n flex-wrap: wrap;\n align-items: center;\n}\n\n@media (min-width: 768px) {\n .action-buttons[_ngcontent-%COMP%] {\n margin-bottom: 1.25rem;\n }\n}\n\n\n\n\n\n@media (max-width: 639px) {\n .sticky-header[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n }\n\n .action-buttons[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n margin-bottom: 0;\n order: 1;\n width: 100%;\n }\n\n .mj-view-toggle[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-medium);\n padding: 3px;\n gap: 2px;\n }\n\n .mj-view-toggle[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 0.625rem;\n min-width: 36px;\n min-height: 36px;\n border-radius: var(--md-corner-small);\n }\n\n .mj-view-toggle[_ngcontent-%COMP%] .mj-btn.mj-btn-primary[_ngcontent-%COMP%] {\n box-shadow: none;\n }\n\n .action-buttons[_ngcontent-%COMP%] > .mj-btn-secondary[_ngcontent-%COMP%] {\n flex-shrink: 0;\n padding: 0.5rem 0.625rem;\n min-width: 36px;\n min-height: 36px;\n border-radius: var(--md-corner-medium);\n }\n\n .filters-section[_ngcontent-%COMP%] {\n order: 2;\n width: 100%;\n background: #F3F5F9;\n border: 1px solid var(--md-outline-variant);\n padding: 0.75rem;\n margin-bottom: 0.5rem;\n border-radius: var(--md-corner-medium);\n }\n\n .filters-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: nowrap;\n }\n\n \n\n .mobile-search-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex: 1;\n min-width: 0;\n }\n\n .mj-search[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 0.75rem 1rem 0.75rem 2.5rem;\n min-height: 44px;\n font-size: 1rem;\n border-width: 1.5px;\n border-radius: var(--md-corner-full);\n box-sizing: border-box;\n width: 100%;\n }\n\n .mj-search[_ngcontent-%COMP%] .mj-search-icon[_ngcontent-%COMP%] {\n left: 0.875rem;\n font-size: 1rem;\n }\n\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]::placeholder {\n font-size: 0.875rem;\n }\n\n \n\n .mj-filter-group[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mj-filter-label[_ngcontent-%COMP%] {\n display: none;\n }\n\n .mj-filter-select[_ngcontent-%COMP%] {\n display: none;\n }\n\n \n\n .filter-button[_ngcontent-%COMP%] {\n display: inline-flex !important;\n flex-shrink: 0;\n }\n}\n\n\n\n\n\n.mj-view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-full);\n padding: 4px;\n gap: 2px;\n}\n\n.mj-view-toggle[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n border-radius: var(--md-corner-full);\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.mj-view-toggle[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%]:hover:not(:disabled):not(.mj-btn-primary) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.mj-view-toggle[_ngcontent-%COMP%] .mj-btn.mj-btn-primary[_ngcontent-%COMP%] {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n\n\n\n\n.mj-grid-4[_ngcontent-%COMP%] {\n display: grid;\n gap: 0.75rem;\n margin-bottom: 1rem;\n width: 100%;\n grid-template-columns: repeat(2, 1fr);\n}\n\n@media (max-width: 639px) {\n .mj-grid-4[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n@media (min-width: 640px) {\n .mj-grid-4[_ngcontent-%COMP%] {\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .mj-grid-4[_ngcontent-%COMP%] {\n grid-template-columns: repeat(4, 1fr);\n gap: 1.25rem;\n margin-bottom: 1.25rem;\n }\n}\n\n\n\n.mj-card[_ngcontent-%COMP%] {\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n padding: 1rem;\n display: flex;\n align-items: center;\n gap: 1rem;\n min-width: 0;\n border: 1px solid var(--md-outline-variant);\n cursor: default;\n pointer-events: none;\n}\n\n@media (min-width: 768px) {\n .mj-card[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-medium);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .stat-icon[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--md-primary-container);\n color: var(--md-primary);\n}\n\n\n\n.stat-icon-public[_ngcontent-%COMP%] {\n background: var(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n\n\n.stat-icon-restricted[_ngcontent-%COMP%] {\n background: var(--md-error-container);\n color: var(--md-error);\n}\n\n\n\n.stat-icon-permissions[_ngcontent-%COMP%] {\n background: var(--md-secondary-container);\n color: #B5751A;\n}\n\n\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--md-on-surface);\n line-height: 1;\n letter-spacing: -0.02em;\n}\n\n@media (min-width: 768px) {\n .stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.875rem;\n }\n}\n\n.stat-content[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-top: 0.25rem;\n}\n\n@media (min-width: 768px) {\n .stat-content[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n }\n}\n\n\n\n\n\n.filters-section[_ngcontent-%COMP%] {\n background: #F3F5F9;\n border-radius: var(--md-corner-large);\n padding: 1rem;\n margin-bottom: 0;\n border: 1px solid var(--md-outline-variant);\n width: 100%;\n}\n\n@media (min-width: 768px) {\n .filters-section[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .filters-section[_ngcontent-%COMP%] {\n padding: 1.25rem 1.5rem;\n }\n}\n\n\n\n.filters-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n@media (max-width: 639px) {\n .filters-row[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: stretch;\n gap: 0.75rem;\n }\n}\n\n@media (min-width: 1024px) {\n .filters-row[_ngcontent-%COMP%] {\n gap: 1.5rem;\n }\n}\n\n\n\n\n\n.mj-search[_ngcontent-%COMP%] {\n position: relative;\n flex: 1;\n min-width: 200px;\n}\n\n@media (max-width: 639px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 100%;\n }\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-icon[_ngcontent-%COMP%] {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 0.875rem 1rem 0.875rem 2.75rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-full);\n font-size: 1rem;\n background: var(--md-surface);\n color: var(--md-on-surface);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]::placeholder {\n color: var(--md-on-surface-variant);\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--md-surface);\n}\n\n.mj-search[_ngcontent-%COMP%]:focus-within .mj-search-icon[_ngcontent-%COMP%] {\n color: var(--md-primary);\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem 1rem 3rem;\n }\n\n .mj-search[_ngcontent-%COMP%] .mj-search-icon[_ngcontent-%COMP%] {\n left: 1.125rem;\n font-size: 1.125rem;\n }\n}\n\n\n\n\n\n.mj-filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n justify-content: flex-end;\n}\n\n.mj-filter-label[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--md-on-surface);\n line-height: 1.2;\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-full);\n padding: 4px;\n gap: 2px;\n flex-wrap: wrap;\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 500;\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%]:hover:not(:disabled):not(.mj-btn-primary) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn.mj-btn-primary[_ngcontent-%COMP%] {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n@media (max-width: 639px) {\n .mj-filter-buttons[_ngcontent-%COMP%] {\n flex-direction: row;\n flex-wrap: wrap;\n }\n\n .mj-filter-buttons[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n flex: 1;\n min-width: calc(50% - 4px);\n padding: 0.5rem 0.75rem;\n font-size: 0.75rem;\n }\n}\n\n\n\n.mj-filter-select[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 500;\n background: var(--md-surface);\n color: var(--md-on-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n height: 44px;\n min-width: 150px;\n box-sizing: border-box;\n}\n\n.mj-filter-select[_ngcontent-%COMP%]:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.mj-filter-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n}\n\n@media (max-width: 639px) {\n .mj-filter-select[_ngcontent-%COMP%] {\n width: 100%;\n }\n}\n\n\n\n\n\n.mobile-search-container[_ngcontent-%COMP%] {\n display: contents;\n}\n\n\n\n\n\n.filter-button[_ngcontent-%COMP%] {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n border: 2px solid var(--md-outline-variant);\n background: var(--md-surface);\n color: var(--md-on-surface);\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n min-width: 44px;\n}\n\n.filter-button[_ngcontent-%COMP%]:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.filter-button[_ngcontent-%COMP%]:active {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.filter-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n.filter-button[_ngcontent-%COMP%] .filter-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -4px;\n right: -4px;\n background: var(--md-error);\n color: var(--md-on-error);\n font-size: 0.625rem;\n font-weight: 700;\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n}\n\n\n\n\n\n.filter-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.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.filter-modal[_ngcontent-%COMP%] {\n background: var(--md-surface);\n border-radius: var(--md-corner-extra-large) var(--md-corner-extra-large) 0 0;\n box-shadow: var(--md-elevation-5);\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.filter-modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--md-outline-variant);\n flex-shrink: 0;\n}\n\n.filter-modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.filter-modal-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-primary);\n font-size: 1.375rem;\n}\n\n.filter-modal-close[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--md-corner-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.filter-modal-close[_ngcontent-%COMP%]:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.filter-modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n.filter-modal-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--md-outline-variant);\n background: var(--md-surface-container-low);\n flex-shrink: 0;\n}\n\n.filter-modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\n margin: 0;\n}\n\n\n\n.filter-options-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.filter-group-label[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.filter-group-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.filter-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n background: var(--md-surface-container-low);\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.filter-option[_ngcontent-%COMP%]:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container);\n}\n\n.filter-option.selected[_ngcontent-%COMP%] {\n background: var(--md-primary-container);\n border-color: var(--md-primary);\n color: var(--md-primary);\n}\n\n.filter-option[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%], \n.filter-option[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--md-primary);\n flex-shrink: 0;\n}\n\n.filter-option-label[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 1rem;\n font-weight: 500;\n color: var(--md-on-surface);\n}\n\n.filter-option.selected[_ngcontent-%COMP%] .filter-option-label[_ngcontent-%COMP%] {\n color: var(--md-primary);\n font-weight: 600;\n}\n\n\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideUpFromBottom {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 200px;\n padding: 3rem 1.5rem;\n}\n\n\n\n\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n overflow: visible;\n position: relative;\n background: var(--md-surface-container-lowest);\n border-radius: var(--md-corner-large);\n box-shadow: var(--md-elevation-2);\n padding: 1.25rem;\n border: 1px solid var(--md-outline-variant);\n}\n\n@media (min-width: 768px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.75rem;\n }\n}\n\n\n\n\n\n.entities-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow: visible;\n}\n\n@media (min-width: 768px) {\n .entities-list[_ngcontent-%COMP%] {\n gap: 1rem;\n }\n}\n\n\n\n\n\n.entity-card[_ngcontent-%COMP%] {\n background: var(--md-surface);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-large);\n overflow: hidden;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.entity-card.expanded[_ngcontent-%COMP%] {\n box-shadow: var(--md-elevation-3);\n border-color: var(--md-primary);\n}\n\n.entity-card.expanded[_ngcontent-%COMP%] .expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n\n\n.entity-header[_ngcontent-%COMP%] {\n padding: 1rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n background: var(--md-surface-container-lowest);\n transition: background-color 0.2s ease;\n gap: 0.75rem;\n}\n\n.entity-header[_ngcontent-%COMP%]:hover {\n background: var(--md-surface-container-low);\n}\n\n@media (min-width: 768px) {\n .entity-header[_ngcontent-%COMP%] {\n padding: 1.25rem 1.5rem;\n }\n}\n\n\n\n.entity-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex: 1;\n min-width: 0;\n}\n\n@media (min-width: 768px) {\n .entity-info[_ngcontent-%COMP%] {\n gap: 1rem;\n }\n}\n\n\n\n.entity-icon-wrapper[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-medium);\n background: var(--md-primary-container);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--md-primary);\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .entity-icon-wrapper[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n\n\n.entity-details[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.entity-details[_ngcontent-%COMP%] .entity-name[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0 0 0.25rem 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (min-width: 768px) {\n .entity-details[_ngcontent-%COMP%] .entity-name[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n}\n\n.entity-details[_ngcontent-%COMP%] .entity-description[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (min-width: 768px) {\n .entity-details[_ngcontent-%COMP%] .entity-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n}\n\n\n\n.entity-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .entity-meta[_ngcontent-%COMP%] {\n gap: 0.75rem;\n }\n}\n\n\n\n\n\n.access-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n white-space: nowrap;\n}\n\n@media (min-width: 768px) {\n .access-badge[_ngcontent-%COMP%] {\n padding: 0.5rem 1rem;\n font-size: 0.8125rem;\n }\n}\n\n\n\n.access-badge.access-public[_ngcontent-%COMP%] {\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n\n\n.access-badge.access-restricted[_ngcontent-%COMP%] {\n background: var(--md-error-container);\n color: var(--md-on-error-container);\n border: 1px solid var(--md-error);\n}\n\n\n\n.access-badge.access-custom[_ngcontent-%COMP%] {\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\n}\n\n\n\n.entity-actions[_ngcontent-%COMP%] {\n display: none;\n}\n\n@media (min-width: 640px) {\n .entity-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\n }\n}\n\n@media (max-width: 639px) {\n .entity-meta[_ngcontent-%COMP%] > .access-badge[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n\n\n.expand-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--md-corner-full);\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.expand-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n\n\n\n\n.entity-content[_ngcontent-%COMP%] {\n padding: 1.25rem;\n background: var(--md-surface-container-lowest);\n border-top: 1px solid var(--md-outline-variant);\n animation: _ngcontent-%COMP%_slideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@media (min-width: 768px) {\n .entity-content[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .entity-content[_ngcontent-%COMP%] {\n padding: 1.75rem;\n }\n}\n\n\n\n\n\n.mobile-actions-bar[_ngcontent-%COMP%] {\n display: none;\n}\n\n@media (max-width: 639px) {\n .mobile-actions-bar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.75rem;\n margin: -1.25rem -1.25rem 1rem -1.25rem;\n background: var(--md-surface-container-low);\n border-bottom: 1px solid var(--md-outline-variant);\n }\n\n .mobile-action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n }\n\n .mobile-action-buttons[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n }\n\n .mobile-action-buttons[_ngcontent-%COMP%] .btn-label[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n }\n}\n\n\n\n\n\n.permissions-grid[_ngcontent-%COMP%] {\n width: 100%;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n overflow: hidden;\n border: 1px solid var(--md-outline-variant);\n border-collapse: collapse;\n}\n\n\n\n.permissions-header[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background: var(--md-surface-container-high);\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n@media (min-width: 768px) {\n .permissions-header[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n gap: 0.75rem;\n }\n}\n\n@media (max-width: 639px) {\n .permissions-header[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;\n padding: 0.625rem 0.75rem;\n font-size: 0.75rem;\n }\n}\n\n\n\n.permission-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--md-outline-variant);\n transition: background-color 0.2s ease;\n}\n\n.permission-row[_ngcontent-%COMP%]:hover {\n background: var(--md-surface-container-lowest);\n}\n\n.permission-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n@media (min-width: 768px) {\n .permission-row[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n gap: 0.75rem;\n }\n}\n\n@media (max-width: 639px) {\n .permission-row[_ngcontent-%COMP%] {\n grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;\n padding: 0.625rem 0.75rem;\n }\n}\n\n.role-header[_ngcontent-%COMP%], \n.permission-header[_ngcontent-%COMP%] {\n text-align: left;\n}\n\n.permission-header[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.role-name[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--md-on-surface);\n font-size: 0.875rem;\n display: flex;\n align-items: center;\n}\n\n@media (max-width: 639px) {\n .role-name[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n }\n}\n\n.permission-cell[_ngcontent-%COMP%] {\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n\n\n.text-success[_ngcontent-%COMP%] {\n color: var(--md-tertiary);\n}\n\n.text-muted[_ngcontent-%COMP%] {\n color: var(--md-outline);\n opacity: 0.6;\n}\n\n.no-permissions[_ngcontent-%COMP%] {\n color: var(--md-on-surface-variant);\n font-size: 0.875rem;\n margin: 0;\n padding: 1rem;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n text-align: center;\n}\n\n\n\n\n\n.entities-grid[_ngcontent-%COMP%] {\n display: grid;\n gap: 0.75rem;\n grid-template-columns: 1fr;\n}\n\n@media (min-width: 640px) {\n .entities-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .entities-grid[_ngcontent-%COMP%] {\n gap: 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .entities-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(3, 1fr);\n gap: 1.5rem;\n }\n}\n\n\n\n.entity-grid-card[_ngcontent-%COMP%] {\n background: var(--md-surface);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-large);\n padding: 1.25rem;\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-grid-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n\n\n.entity-grid-card.access-public[_ngcontent-%COMP%] {\n border-left: 4px solid var(--md-tertiary);\n}\n\n\n\n.entity-grid-card.access-restricted[_ngcontent-%COMP%] {\n border-left: 4px solid var(--md-error);\n}\n\n\n\n.entity-grid-card.access-custom[_ngcontent-%COMP%] {\n border-left: 4px solid var(--md-secondary);\n}\n\n@media (min-width: 768px) {\n .entity-grid-card[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n\n\n.grid-card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 0.75rem;\n font-size: 1.5rem;\n color: var(--md-primary);\n}\n\n@media (min-width: 768px) {\n .grid-card-header[_ngcontent-%COMP%] {\n margin-bottom: 1rem;\n }\n}\n\n\n\n.grid-card-title[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0 0 0.5rem 0;\n}\n\n@media (min-width: 768px) {\n .grid-card-title[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n}\n\n\n\n.grid-card-description[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n margin: 0 0 0.75rem 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@media (min-width: 768px) {\n .grid-card-description[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n margin: 0 0 1rem 0;\n }\n}\n\n\n\n.grid-card-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.8125rem;\n}\n\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: var(--md-on-surface-variant);\n}\n\n\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n@media (min-width: 768px) {\n .empty-state[_ngcontent-%COMP%] {\n padding: 5rem 2.5rem;\n }\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-state-icon[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 0.5rem;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-text[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n\n\n\n\n.error-container[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n}\n\n@media (min-width: 768px) {\n .error-container[_ngcontent-%COMP%] {\n padding: 5rem 2.5rem;\n }\n}\n\n.error-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n.error-container[_ngcontent-%COMP%] .error-icon[_ngcontent-%COMP%] {\n font-size: 3.5rem;\n color: var(--md-error);\n margin-bottom: 0.5rem;\n}\n\n.error-container[_ngcontent-%COMP%] .error-message[_ngcontent-%COMP%] {\n font-size: 1.0625rem;\n color: var(--md-on-surface);\n margin: 0 0 1.5rem 0;\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\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}\n\n\n\n\n\n@media (max-width: 374px) {\n .filters-section[_ngcontent-%COMP%] {\n padding: 0.5rem;\n margin-bottom: 0.375rem;\n }\n\n .filters-row[_ngcontent-%COMP%] {\n gap: 0.375rem;\n }\n\n .mobile-search-container[_ngcontent-%COMP%] {\n gap: 0.375rem;\n }\n\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 0.625rem 0.75rem 0.625rem 2.25rem;\n font-size: 0.875rem;\n }\n\n .mj-search[_ngcontent-%COMP%] .mj-search-icon[_ngcontent-%COMP%] {\n left: 0.75rem;\n font-size: 0.875rem;\n }\n\n .filter-button[_ngcontent-%COMP%] {\n padding: 0.625rem;\n min-width: 40px;\n flex-shrink: 0;\n }\n\n .filter-button[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: none;\n }\n\n .filter-modal-header[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n\n .filter-modal-body[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n\n .filter-modal-footer[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n\n\n\n\n@media (prefers-reduced-motion: reduce) {\n *[_ngcontent-%COMP%], \n *[_ngcontent-%COMP%]::before, \n *[_ngcontent-%COMP%]::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}"] });
|
|
644
821
|
};
|
|
645
822
|
EntityPermissionsComponent = __decorate([
|
|
646
823
|
RegisterClass(BaseDashboard, 'EntityPermissions')
|
|
@@ -648,7 +825,7 @@ EntityPermissionsComponent = __decorate([
|
|
|
648
825
|
export { EntityPermissionsComponent };
|
|
649
826
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityPermissionsComponent, [{
|
|
650
827
|
type: Component,
|
|
651
|
-
args: [{ selector: 'mj-entity-permissions', template: "<div class=\"entity-permissions-container\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\">\n <div class=\"mj-view-toggle\">\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"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=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"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=\"mj-btn mj-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=\"mj-grid mj-grid-4\">\n <div class=\"mj-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=\"mj-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=\"mj-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=\"mj-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=\"mj-search\">\n <i class=\"fa-solid fa-search mj-search-icon\"></i>\n <input \n type=\"text\" \n class=\"mj-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=\"mj-filter-group\">\n <label class=\"mj-filter-label\">Access Level</label>\n <div class=\"mj-filter-buttons\">\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'all'\"\n (click)=\"onAccessLevelChange('all')\"\n >\n All\n </button>\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'public'\"\n (click)=\"onAccessLevelChange('public')\"\n >\n Public\n </button>\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'restricted'\"\n (click)=\"onAccessLevelChange('restricted')\"\n >\n Restricted\n </button>\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'custom'\"\n (click)=\"onAccessLevelChange('custom')\"\n >\n Custom\n </button>\n </div>\n </div>\n \n <!-- Role Filter -->\n <div class=\"mj-filter-group\">\n <label class=\"mj-filter-label\">Filter by Role</label>\n <select class=\"mj-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=\"mj-btn mj-btn-primary\" (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 \n type=\"button\"\n class=\"btn-edit\" \n (click)=\"editEntityPermissions(ea); $event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n title=\"Edit Permissions\"\n >\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 \n type=\"button\"\n class=\"btn-edit\" \n (click)=\"editEntityPermissions(ea)\"\n title=\"Edit Permissions\"\n >\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 <mj-permission-dialog\n [visible]=\"showPermissionDialog\"\n [data]=\"permissionDialogData\"\n (result)=\"onPermissionDialogResult($event)\"\n ></mj-permission-dialog>\n</div>", styles: ["@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.entity-permissions-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n overflow: hidden;\n position: relative;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\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 .action-buttons {\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.view-btn:hover {\n color: #374151;\n}\n.view-btn.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.btn-primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #2196f3;\n color: white;\n}\n.btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-primary i {\n font-size: 0.875rem;\n}\n.btn-primary:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n}\n\n.btn-secondary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n}\n.btn-secondary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-secondary i {\n font-size: 0.875rem;\n}\n.btn-secondary:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n}\n\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 .stats-grid {\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;\n}\n.stat-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\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.stat-icon-total {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n}\n.stat-icon-public {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n}\n.stat-icon-restricted {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n}\n.stat-icon-permissions {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n}\n\n.stat-content {\n flex: 1;\n}\n.stat-content .stat-value {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n}\n.stat-content .stat-label {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n}\n\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-container .search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: #6b7280;\n font-size: 1rem;\n}\n.search-container .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.search-container .search-input:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.filter-group .filter-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: #374151;\n}\n.filter-group .filter-buttons {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n}\n.filter-group .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.filter-group .filter-btn:hover {\n color: #374151;\n}\n.filter-group .filter-btn.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.filter-group .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.filter-group .filter-select:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.content-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\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.entities-list {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n max-height: calc(100vh - 450px);\n overflow-y: auto;\n padding-right: 0.5rem;\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.entity-card:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n.entity-card.expanded {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n.entity-card.expanded .expand-btn i {\n transform: rotate(180deg);\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.entity-header:hover {\n background: #f3f4f6;\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-details .entity-name {\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n}\n.entity-details .entity-description {\n font-size: 0.875rem;\n color: #6b7280;\n margin: 0;\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-badge.access-public {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n}\n.access-badge.access-restricted {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n}\n.access-badge.access-custom {\n background: rgba(156, 39, 176, 0.1);\n color: #7b1fa2;\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.action-btn:hover {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\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.expand-btn i {\n transition: transform 0.3s ease;\n}\n\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.permission-row:hover {\n background: white;\n}\n.permission-row:last-child {\n border-bottom: none;\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.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.entity-grid-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n.entity-grid-card.access-public {\n border-left: 4px solid #4caf50;\n}\n.entity-grid-card.access-restricted {\n border-left: 4px solid #f44336;\n}\n.entity-grid-card.access-custom {\n border-left: 4px solid #9c27b0;\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.edit-btn:hover {\n background: #f3f4f6;\n color: #2196f3;\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 text-align: center;\n padding: 4rem 2rem;\n}\n.empty-state .empty-icon {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n}\n.empty-state .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n}\n.empty-state .empty-subtext {\n color: #6b7280;\n margin: 0;\n}\n\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.loading-spinner .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.loading-spinner .spinner-ring:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n}\n.loading-spinner .spinner-ring:nth-child(2) {\n border-color: transparent #9c27b0 transparent transparent;\n animation-delay: -0.3s;\n}\n.loading-spinner .spinner-ring:nth-child(3) {\n border-color: transparent transparent #4caf50 transparent;\n animation-delay: -0.15s;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.loading-text {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n.error-container {\n text-align: center;\n padding: 4rem 2rem;\n}\n.error-container .error-icon {\n font-size: 3rem;\n color: #f44336;\n margin-bottom: 1rem;\n}\n.error-container .error-message {\n color: #374151;\n margin-bottom: 1.5rem;\n}\n.error-container .retry-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #2196f3;\n color: white;\n}\n.error-container .retry-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.error-container .retry-button i {\n font-size: 0.875rem;\n}\n\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-dialog.modal-large {\n max-width: 800px;\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-header .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.modal-header .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.modal-header .modal-close:hover {\n background: #f3f4f6;\n color: #374151;\n}\n\n.modal-body {\n padding: 1.5rem;\n max-height: 60vh;\n overflow-y: auto;\n}\n.modal-body .modal-description {\n color: #374151;\n margin: 0 0 1.5rem 0;\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.permission-editor .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@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n 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@keyframes slideDown {\n from {\n opacity: 0;\n max-height: 0;\n }\n to {\n opacity: 1;\n max-height: 800px;\n }\n}\n.btn-edit {\n width: 36px;\n height: 36px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n background: white;\n color: #666666;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 14px;\n}\n.btn-edit:hover {\n background: #f8f9fa;\n border-color: #2196f3;\n color: #2196f3;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.2);\n}\n.btn-edit:active {\n transform: translateY(0);\n}\n"] }]
|
|
828
|
+
args: [{ selector: 'mj-entity-permissions', template: "<div class=\"entity-permissions-container\">\n <!-- Sticky Header Section - Contains controls that should always be visible -->\n <div class=\"sticky-header\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\" role=\"toolbar\" aria-label=\"Entity permissions actions\">\n <div class=\"mj-view-toggle\">\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"viewMode === 'list'\"\n (click)=\"setViewMode('list')\"\n (keydown.enter)=\"setViewMode('list')\"\n (keydown.space)=\"setViewMode('list'); $event.preventDefault()\"\n [attr.aria-label]=\"'List view' + (viewMode === 'list' ? ' (active)' : '')\"\n [attr.aria-pressed]=\"viewMode === 'list'\"\n role=\"button\"\n tabindex=\"0\"\n title=\"List View\"\n >\n <i class=\"fa-solid fa-list\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"viewMode === 'grid'\"\n (click)=\"setViewMode('grid')\"\n (keydown.enter)=\"setViewMode('grid')\"\n (keydown.space)=\"setViewMode('grid'); $event.preventDefault()\"\n [attr.aria-label]=\"'Grid view' + (viewMode === 'grid' ? ' (active)' : '')\"\n [attr.aria-pressed]=\"viewMode === 'grid'\"\n role=\"button\"\n tabindex=\"0\"\n title=\"Grid View\"\n >\n <i class=\"fa-solid fa-th\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <button\n class=\"mj-btn mj-btn-secondary mj-btn-icon-mobile\"\n (click)=\"refreshData()\"\n [disabled]=\"isLoading\"\n aria-label=\"Refresh entity permissions data\"\n title=\"Refresh\"\n >\n <i class=\"fa-solid fa-refresh\" [class.fa-spin]=\"isLoading\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Refresh</span>\n </button>\n </div>\n\n <!-- Stats Cards -->\n <div class=\"mj-grid-4\" role=\"region\" aria-label=\"Permission statistics\">\n <div class=\"mj-card\" role=\"article\" aria-label=\"Total entities statistic\">\n <div class=\"stat-icon stat-icon-total\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-database\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Total entities count\">{{ stats.totalEntities }}</div>\n <div class=\"stat-label\">Total Entities</div>\n </div>\n </div>\n\n <div class=\"mj-card\" role=\"article\" aria-label=\"Public entities statistic\">\n <div class=\"stat-icon stat-icon-public\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-globe\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Public entities count\">{{ stats.publicEntities }}</div>\n <div class=\"stat-label\">Public Entities</div>\n </div>\n </div>\n\n <div class=\"mj-card\" role=\"article\" aria-label=\"Restricted entities statistic\">\n <div class=\"stat-icon stat-icon-restricted\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-lock\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Restricted entities count\">{{ stats.restrictedEntities }}</div>\n <div class=\"stat-label\">Restricted Entities</div>\n </div>\n </div>\n\n <div class=\"mj-card\" role=\"article\" aria-label=\"Total permissions statistic\">\n <div class=\"stat-icon stat-icon-permissions\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-key\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Total permissions count\">{{ 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\" role=\"search\" aria-label=\"Entity filters\">\n <div class=\"filters-row\">\n <!-- Mobile: Search + Filter Button Container -->\n <div class=\"mobile-search-container\">\n <!-- Entity Search -->\n <div class=\"mj-search\">\n <i class=\"fa-solid fa-search mj-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"mj-search-input\"\n placeholder=\"Search entities by name or description...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"filters$.value.entitySearch\"\n aria-label=\"Search entities\"\n />\n </div>\n\n <!-- Filter Button (Mobile Only) -->\n <button\n class=\"filter-button\"\n (click)=\"showMobileFilters = true\"\n aria-label=\"Open filters\"\n >\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n <span>Filters</span>\n </button>\n </div>\n\n <!-- Access Level Filter -->\n <div class=\"mj-filter-group\">\n <label class=\"mj-filter-label\" id=\"access-level-label\">Access Level</label>\n <div class=\"mj-filter-buttons\" role=\"group\" aria-labelledby=\"access-level-label\">\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'all'\"\n (click)=\"onAccessLevelChange('all')\"\n [attr.aria-pressed]=\"filters$.value.accessLevel === 'all'\"\n aria-label=\"Show all access levels\"\n >\n All\n </button>\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'public'\"\n (click)=\"onAccessLevelChange('public')\"\n [attr.aria-pressed]=\"filters$.value.accessLevel === 'public'\"\n aria-label=\"Show only public entities\"\n >\n Public\n </button>\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'restricted'\"\n (click)=\"onAccessLevelChange('restricted')\"\n [attr.aria-pressed]=\"filters$.value.accessLevel === 'restricted'\"\n aria-label=\"Show only restricted entities\"\n >\n Restricted\n </button>\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.accessLevel === 'custom'\"\n (click)=\"onAccessLevelChange('custom')\"\n [attr.aria-pressed]=\"filters$.value.accessLevel === 'custom'\"\n aria-label=\"Show only custom access entities\"\n >\n Custom\n </button>\n </div>\n </div>\n\n <!-- Role Filter -->\n <div class=\"mj-filter-group\">\n <label class=\"mj-filter-label\" for=\"role-filter\">Filter by Role</label>\n <select\n id=\"role-filter\"\n class=\"mj-filter-select\"\n (change)=\"onRoleFilterChange($event)\"\n aria-label=\"Filter entities by role\"\n >\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 </div><!-- End Sticky Header -->\n\n <!-- Scrollable Content Section -->\n <div class=\"scrollable-content\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n <mj-loading text=\"Loading entity permissions...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\" role=\"alert\" aria-live=\"assertive\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\" aria-hidden=\"true\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button\n class=\"mj-btn mj-btn-primary\"\n (click)=\"loadInitialData()\"\n aria-label=\"Retry loading entity permissions\"\n >\n <i class=\"fa-solid fa-refresh\" aria-hidden=\"true\"></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\" role=\"list\" aria-label=\"Entity permissions list\">\n @for (ea of filteredEntityAccess; track ea.entity.ID) {\n <div\n class=\"entity-card\"\n [class.expanded]=\"isEntityExpanded(ea.entity.ID)\"\n role=\"listitem\"\n [attr.aria-expanded]=\"isEntityExpanded(ea.entity.ID)\"\n >\n <div\n class=\"entity-header\"\n (click)=\"toggleEntityExpansion(ea.entity.ID)\"\n (keydown.enter)=\"toggleEntityExpansion(ea.entity.ID)\"\n (keydown.space)=\"toggleEntityExpansion(ea.entity.ID); $event.preventDefault()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Expand permissions for ' + ea.entity.Name\"\n >\n <div class=\"entity-info\">\n <div class=\"entity-icon-wrapper\" aria-hidden=\"true\">\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\n class=\"access-badge\"\n [class]=\"getAccessLevelClass(ea)\"\n [attr.aria-label]=\"'Access level: ' + getAccessLevelLabel(ea)\"\n >\n <i\n [class]=\"getAccessLevelClass(ea) === 'access-public' ? 'fa-solid fa-globe' :\n getAccessLevelClass(ea) === 'access-restricted' ? 'fa-solid fa-lock' :\n 'fa-solid fa-key'\"\n aria-hidden=\"true\"\n ></i>\n {{ getAccessLevelLabel(ea) }}\n </span>\n <div class=\"entity-actions\" (click)=\"$event.stopPropagation()\">\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"editEntityPermissions(ea)\"\n title=\"Edit Permissions\"\n [attr.aria-label]=\"'Edit permissions for ' + ea.entity.Name\"\n >\n <i class=\"fa-solid fa-edit\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <button\n class=\"expand-btn\"\n [attr.aria-label]=\"(isEntityExpanded(ea.entity.ID) ? 'Collapse' : 'Expand') + ' permissions for ' + ea.entity.Name\"\n >\n <i class=\"fa-solid fa-chevron-down\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n @if (isEntityExpanded(ea.entity.ID)) {\n <div class=\"entity-content\" role=\"region\" [attr.aria-label]=\"'Permissions for ' + ea.entity.Name\">\n <!-- Mobile-only actions bar -->\n <div class=\"mobile-actions-bar\" (click)=\"$event.stopPropagation()\">\n <span class=\"access-badge\" [class]=\"getAccessLevelClass(ea)\">\n <i\n [class]=\"getAccessLevelClass(ea) === 'access-public' ? 'fa-solid fa-globe' :\n getAccessLevelClass(ea) === 'access-restricted' ? 'fa-solid fa-lock' :\n 'fa-solid fa-key'\"\n aria-hidden=\"true\"\n ></i>\n {{ getAccessLevelLabel(ea) }}\n </span>\n <div class=\"mobile-action-buttons\">\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"editEntityPermissions(ea)\"\n title=\"Edit Permissions\"\n [attr.aria-label]=\"'Edit permissions for ' + ea.entity.Name\"\n >\n <i class=\"fa-solid fa-edit\" aria-hidden=\"true\"></i>\n <span class=\"btn-label\">Edit</span>\n </button>\n </div>\n </div>\n\n @if (ea.permissions.length > 0) {\n <table class=\"permissions-grid\" role=\"table\" aria-label=\"Role permissions\">\n <thead class=\"permissions-header\" role=\"rowgroup\">\n <tr role=\"row\">\n <th class=\"role-header\" scope=\"col\" role=\"columnheader\">Role</th>\n <th class=\"permission-header\" scope=\"col\" role=\"columnheader\">Create</th>\n <th class=\"permission-header\" scope=\"col\" role=\"columnheader\">Read</th>\n <th class=\"permission-header\" scope=\"col\" role=\"columnheader\">Update</th>\n <th class=\"permission-header\" scope=\"col\" role=\"columnheader\">Delete</th>\n </tr>\n </thead>\n <tbody role=\"rowgroup\">\n @for (roleId of ea.rolePermissions.keys(); track roleId) {\n <tr class=\"permission-row\" role=\"row\">\n <td class=\"role-name\" role=\"cell\">{{ getRoleName(roleId) }}</td>\n <td class=\"permission-cell\" role=\"cell\" [attr.aria-label]=\"'Create: ' + (hasPermission(ea, roleId, 'canCreate') ? 'allowed' : 'denied')\">\n <i\n [class]=\"hasPermission(ea, roleId, 'canCreate') ?\n 'fa-solid fa-check text-success' :\n 'fa-solid fa-times text-muted'\"\n [attr.aria-hidden]=\"true\"\n ></i>\n </td>\n <td class=\"permission-cell\" role=\"cell\" [attr.aria-label]=\"'Read: ' + (hasPermission(ea, roleId, 'canRead') ? 'allowed' : 'denied')\">\n <i\n [class]=\"hasPermission(ea, roleId, 'canRead') ?\n 'fa-solid fa-check text-success' :\n 'fa-solid fa-times text-muted'\"\n [attr.aria-hidden]=\"true\"\n ></i>\n </td>\n <td class=\"permission-cell\" role=\"cell\" [attr.aria-label]=\"'Update: ' + (hasPermission(ea, roleId, 'canUpdate') ? 'allowed' : 'denied')\">\n <i\n [class]=\"hasPermission(ea, roleId, 'canUpdate') ?\n 'fa-solid fa-check text-success' :\n 'fa-solid fa-times text-muted'\"\n [attr.aria-hidden]=\"true\"\n ></i>\n </td>\n <td class=\"permission-cell\" role=\"cell\" [attr.aria-label]=\"'Delete: ' + (hasPermission(ea, roleId, 'canDelete') ? 'allowed' : 'denied')\">\n <i\n [class]=\"hasPermission(ea, roleId, 'canDelete') ?\n 'fa-solid fa-check text-success' :\n 'fa-solid fa-times text-muted'\"\n [attr.aria-hidden]=\"true\"\n ></i>\n </td>\n </tr>\n }\n </tbody>\n </table>\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\" role=\"list\" aria-label=\"Entity permissions grid\">\n @for (ea of filteredEntityAccess; track ea.entity.ID) {\n <article\n class=\"entity-grid-card\"\n [class]=\"getAccessLevelClass(ea)\"\n [attr.aria-label]=\"'Entity: ' + ea.entity.Name\"\n >\n <div class=\"grid-card-header\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"editEntityPermissions(ea)\"\n [attr.aria-label]=\"'Edit permissions for ' + ea.entity.Name\"\n title=\"Edit Permissions\"\n >\n <i class=\"fa-solid fa-edit\" aria-hidden=\"true\"></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\n class=\"access-label\"\n [attr.aria-label]=\"'Access level: ' + getAccessLevelLabel(ea)\"\n >\n <i\n [class]=\"getAccessLevelClass(ea) === 'access-public' ? 'fa-solid fa-globe' :\n getAccessLevelClass(ea) === 'access-restricted' ? 'fa-solid fa-lock' :\n 'fa-solid fa-key'\"\n aria-hidden=\"true\"\n ></i>\n {{ getAccessLevelLabel(ea) }}\n </span>\n @if (ea.permissions.length > 0) {\n <span\n class=\"permission-count\"\n [attr.aria-label]=\"ea.permissions.length + ' permission' + (ea.permissions.length === 1 ? '' : 's')\"\n >\n {{ ea.permissions.length }} permission{{ ea.permissions.length === 1 ? '' : 's' }}\n </span>\n }\n </div>\n </article>\n }\n </div>\n }\n\n @if (filteredEntityAccess.length === 0) {\n <div class=\"empty-state\" role=\"status\">\n <i class=\"fa-solid fa-shield-alt empty-state-icon\" aria-hidden=\"true\"></i>\n <h3 class=\"empty-text\">No Permissions Found</h3>\n <p class=\"empty-subtext\">Try adjusting your filters or refresh the data.</p>\n <button\n class=\"mj-btn mj-btn-primary\"\n (click)=\"refreshData()\"\n aria-label=\"Refresh permissions data\"\n >\n <i class=\"fa-solid fa-refresh\" aria-hidden=\"true\"></i>\n Refresh\n </button>\n </div>\n }\n </div>\n }\n </div><!-- End Scrollable Content -->\n\n <!-- Permission Edit Dialog -->\n <mj-permission-dialog\n [visible]=\"showPermissionDialog\"\n [data]=\"permissionDialogData\"\n (result)=\"onPermissionDialogResult($event)\"\n ></mj-permission-dialog>\n\n <!-- Mobile Filter Modal -->\n @if (showMobileFilters) {\n <div\n class=\"filter-modal-backdrop\"\n (click)=\"showMobileFilters = false\"\n role=\"presentation\"\n >\n <div\n class=\"filter-modal\"\n (click)=\"$event.stopPropagation()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"filter-modal-title\"\n >\n <div class=\"filter-modal-header\">\n <h3 class=\"filter-modal-title\" id=\"filter-modal-title\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n Filters\n </h3>\n <button\n class=\"filter-modal-close\"\n (click)=\"showMobileFilters = false\"\n aria-label=\"Close filters\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"filter-modal-body\">\n <div class=\"filter-options-container\">\n <!-- Access Level Filter -->\n <div class=\"filter-group\">\n <h4 class=\"filter-group-label\">Access Level</h4>\n <div class=\"filter-group-options\">\n <label\n class=\"filter-option\"\n [class.selected]=\"filters$.value.accessLevel === 'all'\"\n >\n <input\n type=\"radio\"\n name=\"accessLevel\"\n value=\"all\"\n [checked]=\"filters$.value.accessLevel === 'all'\"\n (change)=\"onAccessLevelChange('all')\"\n />\n <span class=\"filter-option-label\">All Levels</span>\n </label>\n <label\n class=\"filter-option\"\n [class.selected]=\"filters$.value.accessLevel === 'public'\"\n >\n <input\n type=\"radio\"\n name=\"accessLevel\"\n value=\"public\"\n [checked]=\"filters$.value.accessLevel === 'public'\"\n (change)=\"onAccessLevelChange('public')\"\n />\n <span class=\"filter-option-label\">Public Entities</span>\n </label>\n <label\n class=\"filter-option\"\n [class.selected]=\"filters$.value.accessLevel === 'restricted'\"\n >\n <input\n type=\"radio\"\n name=\"accessLevel\"\n value=\"restricted\"\n [checked]=\"filters$.value.accessLevel === 'restricted'\"\n (change)=\"onAccessLevelChange('restricted')\"\n />\n <span class=\"filter-option-label\">Restricted Entities</span>\n </label>\n <label\n class=\"filter-option\"\n [class.selected]=\"filters$.value.accessLevel === 'custom'\"\n >\n <input\n type=\"radio\"\n name=\"accessLevel\"\n value=\"custom\"\n [checked]=\"filters$.value.accessLevel === 'custom'\"\n (change)=\"onAccessLevelChange('custom')\"\n />\n <span class=\"filter-option-label\">Custom Access Entities</span>\n </label>\n </div>\n </div>\n\n <!-- Role Filter -->\n <div class=\"filter-group\">\n <h4 class=\"filter-group-label\">Filter by Role</h4>\n <div class=\"filter-group-options\">\n <label class=\"filter-option\" [class.selected]=\"!filters$.value.roleId\">\n <input\n type=\"radio\"\n name=\"role\"\n value=\"\"\n [checked]=\"!filters$.value.roleId\"\n (change)=\"onRoleFilterChange($event)\"\n />\n <span class=\"filter-option-label\">All Roles</span>\n </label>\n @for (role of roles; track role.ID) {\n <label\n class=\"filter-option\"\n [class.selected]=\"filters$.value.roleId === role.ID\"\n >\n <input\n type=\"radio\"\n name=\"role\"\n [value]=\"role.ID\"\n [checked]=\"filters$.value.roleId === role.ID\"\n (change)=\"onRoleFilterChange($event)\"\n />\n <span class=\"filter-option-label\">{{ role.Name }}</span>\n </label>\n }\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"filter-modal-footer\">\n <button\n class=\"mj-btn mj-btn-primary\"\n (click)=\"showMobileFilters = false\"\n >\n Apply Filters\n </button>\n <button\n class=\"mj-btn mj-btn-secondary\"\n (click)=\"showMobileFilters = false\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* ==============================================\n Entity Permissions Component - Material Design 3\n ============================================== */\n\n/* ==============================================\n CSS Custom Properties (Design Tokens)\n ============================================== */\n:host {\n /* Primary - Deep Blue */\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n /* Secondary - Light Orange */\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n /* Tertiary - Light Green */\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n /* Error - Red */\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n /* Surface Colors */\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n /* Elevation */\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n /* Corner Radii */\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n /* Host element fills container */\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n/* ==============================================\n Container Layout\n ============================================== */\n.entity-permissions-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n position: relative;\n max-width: 1920px;\n margin: 0 auto;\n width: 100%;\n background: var(--md-surface);\n}\n\n/* ==============================================\n Sticky Header\n ============================================== */\n.sticky-header {\n flex-shrink: 0;\n background: var(--md-surface-container-lowest);\n padding: 1rem;\n border-bottom: 1px solid var(--md-outline-variant);\n box-shadow: var(--md-elevation-1);\n z-index: 10;\n}\n\n@media (min-width: 640px) {\n .sticky-header {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .sticky-header {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .sticky-header {\n padding: 1.5rem 2rem;\n }\n}\n\n/* ==============================================\n Scrollable Content\n ============================================== */\n.scrollable-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n padding: 1rem;\n background: var(--md-surface-container-low);\n}\n\n@media (min-width: 640px) {\n .scrollable-content {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .scrollable-content {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .scrollable-content {\n padding: 1.5rem 2rem;\n }\n}\n\n/* ==============================================\n Button System - MD3 Style\n ============================================== */\n.mj-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n font-size: 0.875rem;\n font-weight: 600;\n border: none;\n border-radius: var(--md-corner-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-width: 44px;\n min-height: 44px;\n text-decoration: none;\n}\n\n.mj-btn:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.mj-btn:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n/* Primary Button - Dark, lightens on hover */\n.mj-btn-primary,\n.mj-btn.mj-btn-primary {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-btn-primary:hover:not(:disabled),\n.mj-btn.mj-btn-primary:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.mj-btn-primary:active:not(:disabled),\n.mj-btn.mj-btn-primary:active:not(:disabled) {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n/* Secondary Button - Light, darkens on hover */\n.mj-btn-secondary {\n background: var(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.mj-btn-secondary:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.mj-btn-secondary:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\n}\n\n/* Ghost Button - Transparent, fills on hover */\n.mj-btn-ghost {\n background: transparent;\n color: var(--md-on-surface-variant);\n padding: 0.75rem 1rem;\n}\n\n.mj-btn-ghost:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.mj-btn-ghost:active:not(:disabled) {\n background: #005A8C;\n}\n\n/* Icon-only Button */\n.mj-btn-icon-only {\n padding: 0.625rem;\n min-width: 44px;\n min-height: 44px;\n}\n\n/* Small Button */\n.mj-btn-sm {\n padding: 0.5rem 0.875rem;\n min-height: 36px;\n min-width: 36px;\n font-size: 0.8125rem;\n}\n\n/* Icon-only on Mobile Button */\n.mj-btn-icon-mobile {\n padding: 0.75rem 1.5rem;\n}\n\n@media (min-width: 640px) {\n .mj-btn-icon-mobile {\n padding: 0.75rem 1.5rem;\n }\n}\n\n@media (max-width: 639px) {\n .mj-btn-icon-mobile .btn-text {\n display: none;\n }\n\n .mj-btn-icon-mobile {\n padding: 0.625rem;\n gap: 0;\n }\n}\n\n/* ==============================================\n Action Buttons\n ============================================== */\n.action-buttons {\n display: flex;\n gap: 0.75rem;\n justify-content: space-between;\n margin-bottom: 1rem;\n flex-wrap: wrap;\n align-items: center;\n}\n\n@media (min-width: 768px) {\n .action-buttons {\n margin-bottom: 1.25rem;\n }\n}\n\n/* ==============================================\n Mobile Navigation Rail - MD3 Style\n ============================================== */\n@media (max-width: 639px) {\n .sticky-header {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n }\n\n .action-buttons {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n margin-bottom: 0;\n order: 1;\n width: 100%;\n }\n\n .mj-view-toggle {\n flex-shrink: 0;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-medium);\n padding: 3px;\n gap: 2px;\n }\n\n .mj-view-toggle .mj-btn {\n padding: 0.5rem 0.625rem;\n min-width: 36px;\n min-height: 36px;\n border-radius: var(--md-corner-small);\n }\n\n .mj-view-toggle .mj-btn.mj-btn-primary {\n box-shadow: none;\n }\n\n .action-buttons > .mj-btn-secondary {\n flex-shrink: 0;\n padding: 0.5rem 0.625rem;\n min-width: 36px;\n min-height: 36px;\n border-radius: var(--md-corner-medium);\n }\n\n .filters-section {\n order: 2;\n width: 100%;\n background: #F3F5F9;\n border: 1px solid var(--md-outline-variant);\n padding: 0.75rem;\n margin-bottom: 0.5rem;\n border-radius: var(--md-corner-medium);\n }\n\n .filters-row {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: nowrap;\n }\n\n /* Mobile search container */\n .mobile-search-container {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex: 1;\n min-width: 0;\n }\n\n .mj-search {\n flex: 1;\n min-width: 0;\n }\n\n .mj-search .mj-search-input {\n padding: 0.75rem 1rem 0.75rem 2.5rem;\n min-height: 44px;\n font-size: 1rem;\n border-width: 1.5px;\n border-radius: var(--md-corner-full);\n box-sizing: border-box;\n width: 100%;\n }\n\n .mj-search .mj-search-icon {\n left: 0.875rem;\n font-size: 1rem;\n }\n\n .mj-search .mj-search-input::placeholder {\n font-size: 0.875rem;\n }\n\n /* Hide filter groups on mobile - they go in modal */\n .mj-filter-group {\n display: none !important;\n }\n\n .mj-filter-label {\n display: none;\n }\n\n .mj-filter-select {\n display: none;\n }\n\n /* Show filter button on mobile */\n .filter-button {\n display: inline-flex !important;\n flex-shrink: 0;\n }\n}\n\n/* ==============================================\n View Toggle\n ============================================== */\n.mj-view-toggle {\n display: flex;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-full);\n padding: 4px;\n gap: 2px;\n}\n\n.mj-view-toggle .mj-btn {\n padding: 0.5rem 1rem;\n border-radius: var(--md-corner-full);\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.mj-view-toggle .mj-btn:hover:not(:disabled):not(.mj-btn-primary) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.mj-view-toggle .mj-btn.mj-btn-primary {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n/* ==============================================\n Stats Grid - Static Display Cards\n ============================================== */\n.mj-grid-4 {\n display: grid;\n gap: 0.75rem;\n margin-bottom: 1rem;\n width: 100%;\n grid-template-columns: repeat(2, 1fr);\n}\n\n@media (max-width: 639px) {\n .mj-grid-4 {\n display: none !important;\n }\n}\n\n@media (min-width: 640px) {\n .mj-grid-4 {\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .mj-grid-4 {\n grid-template-columns: repeat(4, 1fr);\n gap: 1.25rem;\n margin-bottom: 1.25rem;\n }\n}\n\n/* Stat Card - Static (Non-interactive) */\n.mj-card {\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n padding: 1rem;\n display: flex;\n align-items: center;\n gap: 1rem;\n min-width: 0;\n border: 1px solid var(--md-outline-variant);\n cursor: default;\n pointer-events: none;\n}\n\n@media (min-width: 768px) {\n .mj-card {\n padding: 1rem 1.25rem;\n }\n}\n\n/* Stat Icon Containers */\n.stat-icon {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-medium);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .stat-icon {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n/* Total stat - Primary Blue */\n.stat-icon-total {\n background: var(--md-primary-container);\n color: var(--md-primary);\n}\n\n/* Public stat - Tertiary Green */\n.stat-icon-public {\n background: var(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n/* Restricted stat - Error Red */\n.stat-icon-restricted {\n background: var(--md-error-container);\n color: var(--md-error);\n}\n\n/* Permissions stat - Secondary Orange */\n.stat-icon-permissions {\n background: var(--md-secondary-container);\n color: #B5751A;\n}\n\n/* Stat Content */\n.stat-content {\n flex: 1;\n min-width: 0;\n}\n\n.stat-content .stat-value {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--md-on-surface);\n line-height: 1;\n letter-spacing: -0.02em;\n}\n\n@media (min-width: 768px) {\n .stat-content .stat-value {\n font-size: 1.875rem;\n }\n}\n\n.stat-content .stat-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-top: 0.25rem;\n}\n\n@media (min-width: 768px) {\n .stat-content .stat-label {\n font-size: 0.8125rem;\n }\n}\n\n/* ==============================================\n Filters Section\n ============================================== */\n.filters-section {\n background: #F3F5F9;\n border-radius: var(--md-corner-large);\n padding: 1rem;\n margin-bottom: 0;\n border: 1px solid var(--md-outline-variant);\n width: 100%;\n}\n\n@media (min-width: 768px) {\n .filters-section {\n padding: 1rem 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .filters-section {\n padding: 1.25rem 1.5rem;\n }\n}\n\n/* Filters Row */\n.filters-row {\n display: flex;\n gap: 1rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n@media (max-width: 639px) {\n .filters-row {\n flex-direction: column;\n align-items: stretch;\n gap: 0.75rem;\n }\n}\n\n@media (min-width: 1024px) {\n .filters-row {\n gap: 1.5rem;\n }\n}\n\n/* ==============================================\n Search Input - MD3 Style\n ============================================== */\n.mj-search {\n position: relative;\n flex: 1;\n min-width: 200px;\n}\n\n@media (max-width: 639px) {\n .mj-search {\n min-width: 100%;\n }\n}\n\n.mj-search .mj-search-icon {\n position: absolute;\n left: 1rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n.mj-search .mj-search-input {\n width: 100%;\n padding: 0.875rem 1rem 0.875rem 2.75rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-full);\n font-size: 1rem;\n background: var(--md-surface);\n color: var(--md-on-surface);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n}\n\n.mj-search .mj-search-input::placeholder {\n color: var(--md-on-surface-variant);\n}\n\n.mj-search .mj-search-input:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.mj-search .mj-search-input:focus {\n outline: none;\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--md-surface);\n}\n\n.mj-search:focus-within .mj-search-icon {\n color: var(--md-primary);\n}\n\n@media (min-width: 1024px) {\n .mj-search .mj-search-input {\n padding: 1rem 1.25rem 1rem 3rem;\n }\n\n .mj-search .mj-search-icon {\n left: 1.125rem;\n font-size: 1.125rem;\n }\n}\n\n/* ==============================================\n Filter Group - MD3 Style\n ============================================== */\n.mj-filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n justify-content: flex-end;\n}\n\n.mj-filter-label {\n font-size: 0.8125rem;\n font-weight: 500;\n color: var(--md-on-surface);\n line-height: 1.2;\n}\n\n.mj-filter-buttons {\n display: flex;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-full);\n padding: 4px;\n gap: 2px;\n flex-wrap: wrap;\n}\n\n.mj-filter-buttons .mj-btn {\n padding: 0.5rem 1rem;\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 500;\n background: transparent;\n color: var(--md-on-surface-variant);\n border: none;\n}\n\n.mj-filter-buttons .mj-btn:hover:not(:disabled):not(.mj-btn-primary) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.mj-filter-buttons .mj-btn.mj-btn-primary {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n@media (max-width: 639px) {\n .mj-filter-buttons {\n flex-direction: row;\n flex-wrap: wrap;\n }\n\n .mj-filter-buttons .mj-btn {\n flex: 1;\n min-width: calc(50% - 4px);\n padding: 0.5rem 0.75rem;\n font-size: 0.75rem;\n }\n}\n\n/* Filter Select Dropdown */\n.mj-filter-select {\n padding: 0.5rem 1rem;\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 500;\n background: var(--md-surface);\n color: var(--md-on-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n height: 44px;\n min-width: 150px;\n box-sizing: border-box;\n}\n\n.mj-filter-select:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.mj-filter-select:focus {\n outline: none;\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n}\n\n@media (max-width: 639px) {\n .mj-filter-select {\n width: 100%;\n }\n}\n\n/* ==============================================\n Mobile Search Container (Desktop Default)\n ============================================== */\n.mobile-search-container {\n display: contents;\n}\n\n/* ==============================================\n Filter Button (Mobile Only)\n ============================================== */\n.filter-button {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n border: 2px solid var(--md-outline-variant);\n background: var(--md-surface);\n color: var(--md-on-surface);\n border-radius: var(--md-corner-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n min-width: 44px;\n}\n\n.filter-button:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.filter-button:active {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.filter-button i {\n font-size: 1rem;\n}\n\n.filter-button .filter-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n background: var(--md-error);\n color: var(--md-on-error);\n font-size: 0.625rem;\n font-weight: 700;\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 4px;\n}\n\n/* ==============================================\n Filter Modal (Mobile)\n ============================================== */\n.filter-modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.filter-modal {\n background: var(--md-surface);\n border-radius: var(--md-corner-extra-large) var(--md-corner-extra-large) 0 0;\n box-shadow: var(--md-elevation-5);\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n animation: slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.filter-modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--md-outline-variant);\n flex-shrink: 0;\n}\n\n.filter-modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.filter-modal-title i {\n color: var(--md-primary);\n font-size: 1.375rem;\n}\n\n.filter-modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--md-corner-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.filter-modal-close:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.filter-modal-body {\n padding: 1.5rem;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n.filter-modal-footer {\n display: flex;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--md-outline-variant);\n background: var(--md-surface-container-low);\n flex-shrink: 0;\n}\n\n.filter-modal-footer button {\n flex: 1;\n margin: 0;\n}\n\n/* Filter Options Container (Inside Modal) */\n.filter-options-container {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.filter-group-label {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.filter-group-options {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.filter-option {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n background: var(--md-surface-container-low);\n border: 2px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.filter-option:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container);\n}\n\n.filter-option.selected {\n background: var(--md-primary-container);\n border-color: var(--md-primary);\n color: var(--md-primary);\n}\n\n.filter-option input[type=\"checkbox\"],\n.filter-option input[type=\"radio\"] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--md-primary);\n flex-shrink: 0;\n}\n\n.filter-option-label {\n flex: 1;\n font-size: 1rem;\n font-weight: 500;\n color: var(--md-on-surface);\n}\n\n.filter-option.selected .filter-option-label {\n color: var(--md-primary);\n font-weight: 600;\n}\n\n/* Animations */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUpFromBottom {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* ==============================================\n Loading Container\n ============================================== */\n.loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 200px;\n padding: 3rem 1.5rem;\n}\n\n/* ==============================================\n Content Area\n ============================================== */\n.content-area {\n flex: 1 1 auto;\n overflow: visible;\n position: relative;\n background: var(--md-surface-container-lowest);\n border-radius: var(--md-corner-large);\n box-shadow: var(--md-elevation-2);\n padding: 1.25rem;\n border: 1px solid var(--md-outline-variant);\n}\n\n@media (min-width: 768px) {\n .content-area {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .content-area {\n padding: 1.75rem;\n }\n}\n\n/* ==============================================\n Entities List\n ============================================== */\n.entities-list {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow: visible;\n}\n\n@media (min-width: 768px) {\n .entities-list {\n gap: 1rem;\n }\n}\n\n/* ==============================================\n Entity Card - Interactive\n ============================================== */\n.entity-card {\n background: var(--md-surface);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-large);\n overflow: hidden;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-card:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.entity-card.expanded {\n box-shadow: var(--md-elevation-3);\n border-color: var(--md-primary);\n}\n\n.entity-card.expanded .expand-btn i {\n transform: rotate(180deg);\n}\n\n/* Entity Header */\n.entity-header {\n padding: 1rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n background: var(--md-surface-container-lowest);\n transition: background-color 0.2s ease;\n gap: 0.75rem;\n}\n\n.entity-header:hover {\n background: var(--md-surface-container-low);\n}\n\n@media (min-width: 768px) {\n .entity-header {\n padding: 1.25rem 1.5rem;\n }\n}\n\n/* Entity Info */\n.entity-info {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex: 1;\n min-width: 0;\n}\n\n@media (min-width: 768px) {\n .entity-info {\n gap: 1rem;\n }\n}\n\n/* Entity Icon Container - Primary */\n.entity-icon-wrapper {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-medium);\n background: var(--md-primary-container);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--md-primary);\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .entity-icon-wrapper {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n/* Entity Details */\n.entity-details {\n flex: 1;\n min-width: 0;\n}\n\n.entity-details .entity-name {\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0 0 0.25rem 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (min-width: 768px) {\n .entity-details .entity-name {\n font-size: 1.125rem;\n }\n}\n\n.entity-details .entity-description {\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (min-width: 768px) {\n .entity-details .entity-description {\n font-size: 0.875rem;\n }\n}\n\n/* Entity Meta */\n.entity-meta {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .entity-meta {\n gap: 0.75rem;\n }\n}\n\n/* ==============================================\n Access Badges - MD3 Style\n ============================================== */\n.access-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n white-space: nowrap;\n}\n\n@media (min-width: 768px) {\n .access-badge {\n padding: 0.5rem 1rem;\n font-size: 0.8125rem;\n }\n}\n\n/* Public Access - Tertiary Green */\n.access-badge.access-public {\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n/* Restricted Access - Error Red */\n.access-badge.access-restricted {\n background: var(--md-error-container);\n color: var(--md-on-error-container);\n border: 1px solid var(--md-error);\n}\n\n/* Custom Access - Secondary Orange */\n.access-badge.access-custom {\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\n}\n\n/* Entity Actions - Hide on mobile */\n.entity-actions {\n display: none;\n}\n\n@media (min-width: 640px) {\n .entity-actions {\n display: flex;\n gap: 0.25rem;\n }\n}\n\n@media (max-width: 639px) {\n .entity-meta > .access-badge {\n display: none;\n }\n}\n\n/* Expand Button */\n.expand-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--md-corner-full);\n}\n\n.expand-btn:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.expand-btn:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.expand-btn i {\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n/* ==============================================\n Entity Content - Expanded Area\n ============================================== */\n.entity-content {\n padding: 1.25rem;\n background: var(--md-surface-container-lowest);\n border-top: 1px solid var(--md-outline-variant);\n animation: slideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n@media (min-width: 768px) {\n .entity-content {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .entity-content {\n padding: 1.75rem;\n }\n}\n\n/* ==============================================\n Mobile Actions Bar\n ============================================== */\n.mobile-actions-bar {\n display: none;\n}\n\n@media (max-width: 639px) {\n .mobile-actions-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.75rem;\n margin: -1.25rem -1.25rem 1rem -1.25rem;\n background: var(--md-surface-container-low);\n border-bottom: 1px solid var(--md-outline-variant);\n }\n\n .mobile-action-buttons {\n display: flex;\n gap: 0.5rem;\n }\n\n .mobile-action-buttons .mj-btn {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n }\n\n .mobile-action-buttons .btn-label {\n font-size: 0.8125rem;\n }\n}\n\n/* ==============================================\n Permissions Grid (Table)\n ============================================== */\n.permissions-grid {\n width: 100%;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n overflow: hidden;\n border: 1px solid var(--md-outline-variant);\n border-collapse: collapse;\n}\n\n/* Permissions Header */\n.permissions-header tr {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background: var(--md-surface-container-high);\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n@media (min-width: 768px) {\n .permissions-header tr {\n padding: 1rem 1.25rem;\n gap: 0.75rem;\n }\n}\n\n@media (max-width: 639px) {\n .permissions-header tr {\n grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;\n padding: 0.625rem 0.75rem;\n font-size: 0.75rem;\n }\n}\n\n/* Permission Row */\n.permission-row {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr 1fr 1fr;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--md-outline-variant);\n transition: background-color 0.2s ease;\n}\n\n.permission-row:hover {\n background: var(--md-surface-container-lowest);\n}\n\n.permission-row:last-child {\n border-bottom: none;\n}\n\n@media (min-width: 768px) {\n .permission-row {\n padding: 1rem 1.25rem;\n gap: 0.75rem;\n }\n}\n\n@media (max-width: 639px) {\n .permission-row {\n grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;\n padding: 0.625rem 0.75rem;\n }\n}\n\n.role-header,\n.permission-header {\n text-align: left;\n}\n\n.permission-header {\n text-align: center;\n}\n\n.role-name {\n font-weight: 500;\n color: var(--md-on-surface);\n font-size: 0.875rem;\n display: flex;\n align-items: center;\n}\n\n@media (max-width: 639px) {\n .role-name {\n font-size: 0.75rem;\n }\n}\n\n.permission-cell {\n text-align: center;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Success text - Tertiary Green */\n.text-success {\n color: var(--md-tertiary);\n}\n\n.text-muted {\n color: var(--md-outline);\n opacity: 0.6;\n}\n\n.no-permissions {\n color: var(--md-on-surface-variant);\n font-size: 0.875rem;\n margin: 0;\n padding: 1rem;\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n text-align: center;\n}\n\n/* ==============================================\n Entities Grid (Grid View)\n ============================================== */\n.entities-grid {\n display: grid;\n gap: 0.75rem;\n grid-template-columns: 1fr;\n}\n\n@media (min-width: 640px) {\n .entities-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .entities-grid {\n gap: 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .entities-grid {\n grid-template-columns: repeat(3, 1fr);\n gap: 1.5rem;\n }\n}\n\n/* Entity Grid Card */\n.entity-grid-card {\n background: var(--md-surface);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-large);\n padding: 1.25rem;\n position: relative;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.entity-grid-card:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n/* Public - Green border */\n.entity-grid-card.access-public {\n border-left: 4px solid var(--md-tertiary);\n}\n\n/* Restricted - Red border */\n.entity-grid-card.access-restricted {\n border-left: 4px solid var(--md-error);\n}\n\n/* Custom - Orange border */\n.entity-grid-card.access-custom {\n border-left: 4px solid var(--md-secondary);\n}\n\n@media (min-width: 768px) {\n .entity-grid-card {\n padding: 1.5rem;\n }\n}\n\n/* Grid Card Header */\n.grid-card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 0.75rem;\n font-size: 1.5rem;\n color: var(--md-primary);\n}\n\n@media (min-width: 768px) {\n .grid-card-header {\n margin-bottom: 1rem;\n }\n}\n\n/* Grid Card Title */\n.grid-card-title {\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0 0 0.5rem 0;\n}\n\n@media (min-width: 768px) {\n .grid-card-title {\n font-size: 1.125rem;\n }\n}\n\n/* Grid Card Description */\n.grid-card-description {\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n margin: 0 0 0.75rem 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@media (min-width: 768px) {\n .grid-card-description {\n font-size: 0.875rem;\n margin: 0 0 1rem 0;\n }\n}\n\n/* Grid Card Footer */\n.grid-card-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-size: 0.8125rem;\n}\n\n/* Access Label */\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: var(--md-on-surface-variant);\n}\n\n/* ==============================================\n Empty State\n ============================================== */\n.empty-state {\n text-align: center;\n padding: 4rem 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n@media (min-width: 768px) {\n .empty-state {\n padding: 5rem 2.5rem;\n }\n}\n\n.empty-state .empty-state-icon {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 0.5rem;\n}\n\n.empty-state .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.empty-state .empty-subtext {\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n/* ==============================================\n Error Container\n ============================================== */\n.error-container {\n text-align: center;\n padding: 4rem 2rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n}\n\n@media (min-width: 768px) {\n .error-container {\n padding: 5rem 2.5rem;\n }\n}\n\n.error-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n.error-container .error-icon {\n font-size: 3.5rem;\n color: var(--md-error);\n margin-bottom: 0.5rem;\n}\n\n.error-container .error-message {\n font-size: 1.0625rem;\n color: var(--md-on-surface);\n margin: 0 0 1.5rem 0;\n}\n\n/* ==============================================\n Animations\n ============================================== */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\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}\n\n/* ==============================================\n Very Small Mobile (< 375px)\n ============================================== */\n@media (max-width: 374px) {\n .filters-section {\n padding: 0.5rem;\n margin-bottom: 0.375rem;\n }\n\n .filters-row {\n gap: 0.375rem;\n }\n\n .mobile-search-container {\n gap: 0.375rem;\n }\n\n .mj-search .mj-search-input {\n padding: 0.625rem 0.75rem 0.625rem 2.25rem;\n font-size: 0.875rem;\n }\n\n .mj-search .mj-search-icon {\n left: 0.75rem;\n font-size: 0.875rem;\n }\n\n .filter-button {\n padding: 0.625rem;\n min-width: 40px;\n flex-shrink: 0;\n }\n\n .filter-button span {\n display: none;\n }\n\n .filter-modal-header {\n padding: 1rem 1.25rem;\n }\n\n .filter-modal-body {\n padding: 1.25rem;\n }\n\n .filter-modal-footer {\n padding: 1rem 1.25rem;\n }\n}\n\n/* ==============================================\n Reduced Motion Support\n ============================================== */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n"] }]
|
|
652
829
|
}], () => [], null); })();
|
|
653
830
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityPermissionsComponent, { className: "EntityPermissionsComponent", filePath: "src/lib/entity-permissions/entity-permissions.component.ts", lineNumber: 48 }); })();
|
|
654
831
|
//# sourceMappingURL=entity-permissions.component.js.map
|