@memberjunction/ng-explorer-settings 3.2.0 → 3.3.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/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/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/module.d.ts +20 -25
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/module.js +20 -44
- 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 +54 -1
- package/dist/lib/settings/settings.component.d.ts.map +1 -1
- package/dist/lib/settings/settings.component.js +528 -182
- 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 +12 -3
- 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 +21 -20
|
@@ -12,294 +12,576 @@ 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 "
|
|
16
|
-
import * as i3 from "
|
|
15
|
+
import * as i2 from "@memberjunction/ng-shared-generic";
|
|
16
|
+
import * as i3 from "./user-dialog/user-dialog.component";
|
|
17
|
+
import * as i4 from "@angular/common";
|
|
17
18
|
const _forTrack0 = ($index, $item) => $item.ID;
|
|
18
|
-
function
|
|
19
|
-
i0.ɵɵ
|
|
19
|
+
function UserManagementComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
20
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
21
|
+
i0.ɵɵelementStart(0, "div", 10)(1, "div", 52);
|
|
22
|
+
i0.ɵɵelement(2, "i", 53);
|
|
23
|
+
i0.ɵɵelementStart(3, "span");
|
|
24
|
+
i0.ɵɵtext(4);
|
|
25
|
+
i0.ɵɵelementEnd();
|
|
26
|
+
i0.ɵɵelementStart(5, "button", 54);
|
|
27
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_15_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.clearSelection()); });
|
|
28
|
+
i0.ɵɵelement(6, "i", 55);
|
|
29
|
+
i0.ɵɵtext(7, " Clear ");
|
|
30
|
+
i0.ɵɵelementEnd()();
|
|
31
|
+
i0.ɵɵelementStart(8, "div", 56)(9, "button", 57);
|
|
32
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_15_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmBulkAction("enable")); });
|
|
33
|
+
i0.ɵɵelement(10, "i", 58);
|
|
34
|
+
i0.ɵɵelementStart(11, "span", 5);
|
|
35
|
+
i0.ɵɵtext(12, "Enable");
|
|
36
|
+
i0.ɵɵelementEnd()();
|
|
37
|
+
i0.ɵɵelementStart(13, "button", 59);
|
|
38
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_15_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmBulkAction("disable")); });
|
|
39
|
+
i0.ɵɵelement(14, "i", 60);
|
|
40
|
+
i0.ɵɵelementStart(15, "span", 5);
|
|
41
|
+
i0.ɵɵtext(16, "Disable");
|
|
42
|
+
i0.ɵɵelementEnd()();
|
|
43
|
+
i0.ɵɵelementStart(17, "button", 61);
|
|
44
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_15_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openBulkRoleAssign()); });
|
|
45
|
+
i0.ɵɵelement(18, "i", 62);
|
|
46
|
+
i0.ɵɵelementStart(19, "span", 5);
|
|
47
|
+
i0.ɵɵtext(20, "Assign Role");
|
|
48
|
+
i0.ɵɵelementEnd()();
|
|
49
|
+
i0.ɵɵelementStart(21, "button", 63);
|
|
50
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_15_Template_button_click_21_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmBulkAction("delete")); });
|
|
51
|
+
i0.ɵɵelement(22, "i", 64);
|
|
52
|
+
i0.ɵɵelementStart(23, "span", 5);
|
|
53
|
+
i0.ɵɵtext(24, "Delete");
|
|
54
|
+
i0.ɵɵelementEnd()()()();
|
|
55
|
+
} if (rf & 2) {
|
|
56
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
57
|
+
i0.ɵɵadvance(4);
|
|
58
|
+
i0.ɵɵtextInterpolate2("", ctx_r1.selectedCount, " user", ctx_r1.selectedCount > 1 ? "s" : "", " selected");
|
|
59
|
+
} }
|
|
60
|
+
function UserManagementComponent_Conditional_56_Template(rf, ctx) { if (rf & 1) {
|
|
61
|
+
i0.ɵɵelementStart(0, "span", 34);
|
|
20
62
|
i0.ɵɵtext(1);
|
|
21
63
|
i0.ɵɵelementEnd();
|
|
22
64
|
} if (rf & 2) {
|
|
23
|
-
const
|
|
24
|
-
i0.ɵɵproperty("value", role_r1.ID);
|
|
65
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
25
66
|
i0.ɵɵadvance();
|
|
26
|
-
i0.ɵɵtextInterpolate(
|
|
67
|
+
i0.ɵɵtextInterpolate(ctx_r1.activeFilterCount);
|
|
27
68
|
} }
|
|
28
|
-
function
|
|
29
|
-
i0.ɵɵelementStart(0, "
|
|
30
|
-
i0.ɵɵ
|
|
69
|
+
function UserManagementComponent_For_74_Template(rf, ctx) { if (rf & 1) {
|
|
70
|
+
i0.ɵɵelementStart(0, "option", 42);
|
|
71
|
+
i0.ɵɵtext(1);
|
|
31
72
|
i0.ɵɵelementEnd();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
i0.ɵɵ
|
|
73
|
+
} if (rf & 2) {
|
|
74
|
+
const role_r3 = ctx.$implicit;
|
|
75
|
+
i0.ɵɵproperty("value", role_r3.ID);
|
|
76
|
+
i0.ɵɵadvance();
|
|
77
|
+
i0.ɵɵtextInterpolate(role_r3.Name);
|
|
35
78
|
} }
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
i0.ɵɵ
|
|
39
|
-
i0.ɵɵelement(2, "i", 47);
|
|
40
|
-
i0.ɵɵelementStart(3, "p", 48);
|
|
41
|
-
i0.ɵɵtext(4);
|
|
79
|
+
function UserManagementComponent_Conditional_75_For_19_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
+
i0.ɵɵelementStart(0, "option", 42);
|
|
81
|
+
i0.ɵɵtext(1);
|
|
42
82
|
i0.ɵɵelementEnd();
|
|
43
|
-
i0.ɵɵelementStart(5, "button", 49);
|
|
44
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_73_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.loadInitialData()); });
|
|
45
|
-
i0.ɵɵelement(6, "i", 3);
|
|
46
|
-
i0.ɵɵtext(7, " Try Again ");
|
|
47
|
-
i0.ɵɵelementEnd()()();
|
|
48
83
|
} if (rf & 2) {
|
|
49
|
-
const
|
|
50
|
-
i0.ɵɵ
|
|
51
|
-
i0.ɵɵ
|
|
84
|
+
const role_r5 = ctx.$implicit;
|
|
85
|
+
i0.ɵɵproperty("value", role_r5.ID);
|
|
86
|
+
i0.ɵɵadvance();
|
|
87
|
+
i0.ɵɵtextInterpolate(role_r5.Name);
|
|
52
88
|
} }
|
|
53
|
-
function
|
|
89
|
+
function UserManagementComponent_Conditional_75_Conditional_20_Template(rf, ctx) { if (rf & 1) {
|
|
90
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
91
|
+
i0.ɵɵelementStart(0, "button", 75);
|
|
92
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_75_Conditional_20_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.clearFilters()); });
|
|
93
|
+
i0.ɵɵelement(1, "i", 55);
|
|
94
|
+
i0.ɵɵtext(2, " Clear Filters ");
|
|
95
|
+
i0.ɵɵelementEnd();
|
|
96
|
+
} }
|
|
97
|
+
function UserManagementComponent_Conditional_75_Template(rf, ctx) { if (rf & 1) {
|
|
54
98
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
55
|
-
i0.ɵɵelementStart(0, "
|
|
56
|
-
i0.ɵɵ
|
|
57
|
-
i0.ɵɵelementStart(1, "td", 59);
|
|
58
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_td_click_1_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
59
|
-
i0.ɵɵelement(2, "input", 54);
|
|
99
|
+
i0.ɵɵelementStart(0, "div", 43)(1, "div", 65)(2, "div", 66)(3, "label", 67);
|
|
100
|
+
i0.ɵɵtext(4, "Status");
|
|
60
101
|
i0.ɵɵelementEnd();
|
|
61
|
-
i0.ɵɵelementStart(
|
|
62
|
-
i0.ɵɵ
|
|
102
|
+
i0.ɵɵelementStart(5, "select", 68);
|
|
103
|
+
i0.ɵɵlistener("change", function UserManagementComponent_Conditional_75_Template_select_change_5_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onStatusFilterChange($event.target.value)); });
|
|
104
|
+
i0.ɵɵelementStart(6, "option", 69);
|
|
105
|
+
i0.ɵɵtext(7, "All Status");
|
|
63
106
|
i0.ɵɵelementEnd();
|
|
64
|
-
i0.ɵɵelementStart(
|
|
65
|
-
i0.ɵɵtext(9);
|
|
107
|
+
i0.ɵɵelementStart(8, "option", 70);
|
|
108
|
+
i0.ɵɵtext(9, "Active");
|
|
66
109
|
i0.ɵɵelementEnd();
|
|
67
|
-
i0.ɵɵelementStart(10, "
|
|
68
|
-
i0.ɵɵtext(11);
|
|
69
|
-
i0.ɵɵelementEnd()()()
|
|
70
|
-
i0.ɵɵelementStart(12, "
|
|
71
|
-
i0.ɵɵtext(
|
|
110
|
+
i0.ɵɵelementStart(10, "option", 71);
|
|
111
|
+
i0.ɵɵtext(11, "Inactive");
|
|
112
|
+
i0.ɵɵelementEnd()()();
|
|
113
|
+
i0.ɵɵelementStart(12, "div", 66)(13, "label", 72);
|
|
114
|
+
i0.ɵɵtext(14, "Role");
|
|
72
115
|
i0.ɵɵelementEnd();
|
|
73
|
-
i0.ɵɵelementStart(
|
|
74
|
-
i0.ɵɵ
|
|
75
|
-
i0.ɵɵ
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵ
|
|
78
|
-
i0.ɵɵ
|
|
79
|
-
i0.ɵɵtext(21);
|
|
116
|
+
i0.ɵɵelementStart(15, "select", 73);
|
|
117
|
+
i0.ɵɵlistener("change", function UserManagementComponent_Conditional_75_Template_select_change_15_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onRoleFilterChange($event.target.value)); });
|
|
118
|
+
i0.ɵɵelementStart(16, "option", 41);
|
|
119
|
+
i0.ɵɵtext(17, "All Roles");
|
|
120
|
+
i0.ɵɵelementEnd();
|
|
121
|
+
i0.ɵɵrepeaterCreate(18, UserManagementComponent_Conditional_75_For_19_Template, 2, 2, "option", 42, _forTrack0);
|
|
80
122
|
i0.ɵɵelementEnd()();
|
|
81
|
-
i0.ɵɵ
|
|
82
|
-
i0.ɵɵtext(24);
|
|
83
|
-
i0.ɵɵpipe(25, "date");
|
|
123
|
+
i0.ɵɵtemplate(20, UserManagementComponent_Conditional_75_Conditional_20_Template, 3, 0, "button", 74);
|
|
84
124
|
i0.ɵɵelementEnd()();
|
|
85
|
-
i0.ɵɵelementStart(26, "td", 68);
|
|
86
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_td_click_26_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
87
|
-
i0.ɵɵelementStart(27, "button", 69);
|
|
88
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_button_click_27_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.editUser(user_r5)); });
|
|
89
|
-
i0.ɵɵelement(28, "i", 70);
|
|
90
|
-
i0.ɵɵelementEnd();
|
|
91
|
-
i0.ɵɵelementStart(29, "button", 71);
|
|
92
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_button_click_29_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.toggleUserStatus(user_r5)); });
|
|
93
|
-
i0.ɵɵelement(30, "i");
|
|
94
|
-
i0.ɵɵelementEnd();
|
|
95
|
-
i0.ɵɵelementStart(31, "button", 72);
|
|
96
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_1_For_20_Template_button_click_31_listener() { const user_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.confirmDeleteUser(user_r5)); });
|
|
97
|
-
i0.ɵɵelement(32, "i", 73);
|
|
98
|
-
i0.ɵɵelementEnd()()();
|
|
99
125
|
} if (rf & 2) {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
i0.ɵɵ
|
|
103
|
-
i0.ɵɵ
|
|
104
|
-
i0.ɵɵ
|
|
105
|
-
i0.ɵɵtextInterpolate(user_r5.Name);
|
|
106
|
-
i0.ɵɵadvance(2);
|
|
107
|
-
i0.ɵɵtextInterpolate2(" ", user_r5.FirstName, " ", user_r5.LastName, " ");
|
|
126
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
127
|
+
i0.ɵɵadvance(5);
|
|
128
|
+
i0.ɵɵproperty("value", ctx_r1.filters$.value.status);
|
|
129
|
+
i0.ɵɵadvance(13);
|
|
130
|
+
i0.ɵɵrepeater(ctx_r1.roles);
|
|
108
131
|
i0.ɵɵadvance(2);
|
|
109
|
-
i0.ɵɵ
|
|
110
|
-
|
|
111
|
-
|
|
132
|
+
i0.ɵɵconditional(ctx_r1.hasActiveFilters ? 20 : -1);
|
|
133
|
+
} }
|
|
134
|
+
function UserManagementComponent_Conditional_77_Template(rf, ctx) { if (rf & 1) {
|
|
135
|
+
i0.ɵɵelementStart(0, "div", 45);
|
|
136
|
+
i0.ɵɵelement(1, "mj-loading", 76);
|
|
137
|
+
i0.ɵɵelementEnd();
|
|
138
|
+
} }
|
|
139
|
+
function UserManagementComponent_Conditional_78_Template(rf, ctx) { if (rf & 1) {
|
|
140
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
141
|
+
i0.ɵɵelementStart(0, "div", 46)(1, "div", 77);
|
|
142
|
+
i0.ɵɵelement(2, "i", 78);
|
|
143
|
+
i0.ɵɵelementStart(3, "p", 79);
|
|
144
|
+
i0.ɵɵtext(4);
|
|
145
|
+
i0.ɵɵelementEnd();
|
|
146
|
+
i0.ɵɵelementStart(5, "button", 80);
|
|
147
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_78_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.loadInitialData()); });
|
|
148
|
+
i0.ɵɵelement(6, "i", 4);
|
|
149
|
+
i0.ɵɵtext(7, " Try Again ");
|
|
150
|
+
i0.ɵɵelementEnd()()();
|
|
151
|
+
} if (rf & 2) {
|
|
152
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
153
|
+
i0.ɵɵadvance(4);
|
|
154
|
+
i0.ɵɵtextInterpolate(ctx_r1.error);
|
|
155
|
+
} }
|
|
156
|
+
function UserManagementComponent_Conditional_79_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
157
|
+
i0.ɵɵelementStart(0, "span", 86);
|
|
158
|
+
i0.ɵɵtext(1);
|
|
159
|
+
i0.ɵɵelementEnd();
|
|
160
|
+
} if (rf & 2) {
|
|
161
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
112
162
|
i0.ɵɵadvance();
|
|
113
|
-
i0.ɵɵtextInterpolate1("
|
|
163
|
+
i0.ɵɵtextInterpolate1("", ctx_r1.selectedCount, " selected");
|
|
164
|
+
} }
|
|
165
|
+
function UserManagementComponent_Conditional_79_For_9_Conditional_25_Conditional_50_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
166
|
+
i0.ɵɵelementStart(0, "div", 125);
|
|
167
|
+
i0.ɵɵelement(1, "i", 126);
|
|
168
|
+
i0.ɵɵtext(2);
|
|
169
|
+
i0.ɵɵelementEnd();
|
|
170
|
+
} if (rf & 2) {
|
|
171
|
+
const role_r12 = ctx.$implicit;
|
|
114
172
|
i0.ɵɵadvance(2);
|
|
115
|
-
i0.ɵɵ
|
|
116
|
-
i0.ɵɵadvance();
|
|
117
|
-
i0.ɵɵclassMap("fa-solid " + ctx_r2.getStatusIcon(user_r5));
|
|
118
|
-
i0.ɵɵadvance();
|
|
119
|
-
i0.ɵɵtextInterpolate1(" ", user_r5.IsActive ? "Active" : "Inactive", " ");
|
|
120
|
-
i0.ɵɵadvance(3);
|
|
121
|
-
i0.ɵɵtextInterpolate1(" ", user_r5.__mj_UpdatedAt ? i0.ɵɵpipeBind2(25, 17, user_r5.__mj_UpdatedAt, "short") : "Never", " ");
|
|
122
|
-
i0.ɵɵadvance(5);
|
|
123
|
-
i0.ɵɵproperty("title", user_r5.IsActive ? "Deactivate" : "Activate");
|
|
124
|
-
i0.ɵɵadvance();
|
|
125
|
-
i0.ɵɵclassMap(user_r5.IsActive ? "fa-solid fa-toggle-on" : "fa-solid fa-toggle-off");
|
|
173
|
+
i0.ɵɵtextInterpolate1(" ", role_r12.Name, " ");
|
|
126
174
|
} }
|
|
127
|
-
function
|
|
128
|
-
i0.ɵɵelementStart(0, "div",
|
|
129
|
-
i0.ɵɵ
|
|
130
|
-
i0.ɵɵelementStart(2, "p", 75);
|
|
131
|
-
i0.ɵɵtext(3, "No users found");
|
|
175
|
+
function UserManagementComponent_Conditional_79_For_9_Conditional_25_Conditional_50_Template(rf, ctx) { if (rf & 1) {
|
|
176
|
+
i0.ɵɵelementStart(0, "div", 123);
|
|
177
|
+
i0.ɵɵrepeaterCreate(1, UserManagementComponent_Conditional_79_For_9_Conditional_25_Conditional_50_For_2_Template, 3, 1, "div", 125, _forTrack0);
|
|
132
178
|
i0.ɵɵelementEnd();
|
|
133
|
-
|
|
134
|
-
i0.ɵɵ
|
|
135
|
-
i0.ɵɵ
|
|
179
|
+
} if (rf & 2) {
|
|
180
|
+
const user_r10 = i0.ɵɵnextContext(2).$implicit;
|
|
181
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
182
|
+
i0.ɵɵadvance();
|
|
183
|
+
i0.ɵɵrepeater(ctx_r1.getUserRoles(user_r10.ID));
|
|
136
184
|
} }
|
|
137
|
-
function
|
|
138
|
-
i0.ɵɵelementStart(0, "
|
|
139
|
-
i0.ɵɵ
|
|
185
|
+
function UserManagementComponent_Conditional_79_For_9_Conditional_25_Conditional_51_Template(rf, ctx) { if (rf & 1) {
|
|
186
|
+
i0.ɵɵelementStart(0, "p", 124);
|
|
187
|
+
i0.ɵɵtext(1, "No roles assigned to this user");
|
|
140
188
|
i0.ɵɵelementEnd();
|
|
141
|
-
|
|
142
|
-
|
|
189
|
+
} }
|
|
190
|
+
function UserManagementComponent_Conditional_79_For_9_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
191
|
+
const _r11 = i0.ɵɵgetCurrentView();
|
|
192
|
+
i0.ɵɵelementStart(0, "div", 108)(1, "div", 109);
|
|
193
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Conditional_25_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r11); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
194
|
+
i0.ɵɵelementStart(2, "span", 99);
|
|
195
|
+
i0.ɵɵelement(3, "i", 100);
|
|
196
|
+
i0.ɵɵtext(4);
|
|
143
197
|
i0.ɵɵelementEnd();
|
|
144
|
-
i0.ɵɵelementStart(
|
|
145
|
-
i0.ɵɵ
|
|
198
|
+
i0.ɵɵelementStart(5, "div", 110)(6, "button", 111);
|
|
199
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Conditional_25_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r11); const user_r10 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.editUser(user_r10)); });
|
|
200
|
+
i0.ɵɵelement(7, "i", 103);
|
|
201
|
+
i0.ɵɵelementStart(8, "span", 112);
|
|
202
|
+
i0.ɵɵtext(9, "Edit");
|
|
203
|
+
i0.ɵɵelementEnd()();
|
|
204
|
+
i0.ɵɵelementStart(10, "button", 111);
|
|
205
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Conditional_25_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r11); const user_r10 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleUserStatus(user_r10)); });
|
|
206
|
+
i0.ɵɵelement(11, "i", 100);
|
|
207
|
+
i0.ɵɵelementStart(12, "span", 112);
|
|
208
|
+
i0.ɵɵtext(13);
|
|
209
|
+
i0.ɵɵelementEnd()();
|
|
210
|
+
i0.ɵɵelementStart(14, "button", 113);
|
|
211
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Conditional_25_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r11); const user_r10 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.confirmDeleteUser(user_r10)); });
|
|
212
|
+
i0.ɵɵelement(15, "i", 64);
|
|
213
|
+
i0.ɵɵelementStart(16, "span", 112);
|
|
214
|
+
i0.ɵɵtext(17, "Delete");
|
|
215
|
+
i0.ɵɵelementEnd()()()();
|
|
216
|
+
i0.ɵɵelementStart(18, "div", 114)(19, "div", 115);
|
|
217
|
+
i0.ɵɵelement(20, "i", 62);
|
|
218
|
+
i0.ɵɵelementStart(21, "span", 17);
|
|
219
|
+
i0.ɵɵtext(22, "Type:");
|
|
146
220
|
i0.ɵɵelementEnd();
|
|
147
|
-
i0.ɵɵelementStart(
|
|
148
|
-
i0.ɵɵ
|
|
221
|
+
i0.ɵɵelementStart(23, "span", 116);
|
|
222
|
+
i0.ɵɵelement(24, "i", 100);
|
|
223
|
+
i0.ɵɵtext(25);
|
|
224
|
+
i0.ɵɵelementEnd()();
|
|
225
|
+
i0.ɵɵelementStart(26, "div", 115);
|
|
226
|
+
i0.ɵɵelement(27, "i", 117);
|
|
227
|
+
i0.ɵɵelementStart(28, "span", 17);
|
|
228
|
+
i0.ɵɵtext(29, "Full Name:");
|
|
149
229
|
i0.ɵɵelementEnd();
|
|
150
|
-
i0.ɵɵelementStart(
|
|
151
|
-
i0.ɵɵtext(
|
|
230
|
+
i0.ɵɵelementStart(30, "span", 116);
|
|
231
|
+
i0.ɵɵtext(31);
|
|
232
|
+
i0.ɵɵelementEnd()();
|
|
233
|
+
i0.ɵɵelementStart(32, "div", 115);
|
|
234
|
+
i0.ɵɵelement(33, "i", 118);
|
|
235
|
+
i0.ɵɵelementStart(34, "span", 17);
|
|
236
|
+
i0.ɵɵtext(35, "Created:");
|
|
152
237
|
i0.ɵɵelementEnd();
|
|
153
|
-
i0.ɵɵelementStart(
|
|
154
|
-
i0.ɵɵtext(
|
|
238
|
+
i0.ɵɵelementStart(36, "span", 116);
|
|
239
|
+
i0.ɵɵtext(37);
|
|
240
|
+
i0.ɵɵpipe(38, "date");
|
|
241
|
+
i0.ɵɵelementEnd()();
|
|
242
|
+
i0.ɵɵelementStart(39, "div", 115);
|
|
243
|
+
i0.ɵɵelement(40, "i", 119);
|
|
244
|
+
i0.ɵɵelementStart(41, "span", 17);
|
|
245
|
+
i0.ɵɵtext(42, "Updated:");
|
|
155
246
|
i0.ɵɵelementEnd();
|
|
156
|
-
i0.ɵɵelementStart(
|
|
157
|
-
i0.ɵɵtext(
|
|
247
|
+
i0.ɵɵelementStart(43, "span", 116);
|
|
248
|
+
i0.ɵɵtext(44);
|
|
249
|
+
i0.ɵɵpipe(45, "date");
|
|
158
250
|
i0.ɵɵelementEnd()()();
|
|
159
|
-
i0.ɵɵelementStart(
|
|
160
|
-
i0.ɵɵ
|
|
161
|
-
i0.ɵɵ
|
|
162
|
-
i0.ɵɵtemplate(21, UserManagementComponent_Conditional_74_Conditional_1_Conditional_21_Template, 6, 0, "div", 57);
|
|
251
|
+
i0.ɵɵelementStart(46, "div", 120)(47, "h4", 121);
|
|
252
|
+
i0.ɵɵelement(48, "i", 122);
|
|
253
|
+
i0.ɵɵtext(49, " Assigned Roles ");
|
|
163
254
|
i0.ɵɵelementEnd();
|
|
255
|
+
i0.ɵɵtemplate(50, UserManagementComponent_Conditional_79_For_9_Conditional_25_Conditional_50_Template, 3, 0, "div", 123)(51, UserManagementComponent_Conditional_79_For_9_Conditional_25_Conditional_51_Template, 2, 0, "p", 124);
|
|
256
|
+
i0.ɵɵelementEnd()();
|
|
164
257
|
} if (rf & 2) {
|
|
165
|
-
const
|
|
166
|
-
i0.ɵɵ
|
|
167
|
-
i0.ɵɵ
|
|
258
|
+
const user_r10 = i0.ɵɵnextContext().$implicit;
|
|
259
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
260
|
+
i0.ɵɵadvance(2);
|
|
261
|
+
i0.ɵɵclassMap(ctx_r1.getStatusClass(user_r10));
|
|
262
|
+
i0.ɵɵadvance();
|
|
263
|
+
i0.ɵɵclassMap("fa-solid " + ctx_r1.getStatusIcon(user_r10));
|
|
264
|
+
i0.ɵɵadvance();
|
|
265
|
+
i0.ɵɵtextInterpolate1(" ", user_r10.IsActive ? "Active" : "Inactive", " ");
|
|
266
|
+
i0.ɵɵadvance(2);
|
|
267
|
+
i0.ɵɵattribute("aria-label", "Edit " + user_r10.Name);
|
|
268
|
+
i0.ɵɵadvance(4);
|
|
269
|
+
i0.ɵɵattribute("aria-label", (user_r10.IsActive ? "Deactivate " : "Activate ") + user_r10.Name);
|
|
270
|
+
i0.ɵɵadvance();
|
|
271
|
+
i0.ɵɵclassMap(user_r10.IsActive ? "fa-solid fa-toggle-on" : "fa-solid fa-toggle-off");
|
|
168
272
|
i0.ɵɵadvance(2);
|
|
169
|
-
i0.ɵɵ
|
|
273
|
+
i0.ɵɵtextInterpolate(user_r10.IsActive ? "Disable" : "Enable");
|
|
274
|
+
i0.ɵɵadvance();
|
|
275
|
+
i0.ɵɵattribute("aria-label", "Delete " + user_r10.Name);
|
|
276
|
+
i0.ɵɵadvance(10);
|
|
277
|
+
i0.ɵɵclassMap("fa-solid " + ctx_r1.getUserTypeIcon(user_r10));
|
|
278
|
+
i0.ɵɵadvance();
|
|
279
|
+
i0.ɵɵtextInterpolate1(" ", user_r10.Type, " ");
|
|
280
|
+
i0.ɵɵadvance(6);
|
|
281
|
+
i0.ɵɵtextInterpolate2("", user_r10.FirstName, " ", user_r10.LastName, "");
|
|
282
|
+
i0.ɵɵadvance(6);
|
|
283
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(38, 19, user_r10.__mj_CreatedAt, "short"));
|
|
284
|
+
i0.ɵɵadvance(7);
|
|
285
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(45, 22, user_r10.__mj_UpdatedAt, "short"));
|
|
286
|
+
i0.ɵɵadvance(6);
|
|
287
|
+
i0.ɵɵconditional(ctx_r1.getUserRoles(user_r10.ID).length > 0 ? 50 : 51);
|
|
170
288
|
} }
|
|
171
|
-
function
|
|
172
|
-
const
|
|
173
|
-
i0.ɵɵelementStart(0, "div",
|
|
174
|
-
i0.ɵɵlistener("click", function
|
|
175
|
-
i0.ɵɵelementStart(
|
|
176
|
-
i0.ɵɵ
|
|
289
|
+
function UserManagementComponent_Conditional_79_For_9_Template(rf, ctx) { if (rf & 1) {
|
|
290
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
291
|
+
i0.ɵɵelementStart(0, "div", 89)(1, "div", 90);
|
|
292
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Template_div_click_1_listener() { const user_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleUserExpansion(user_r10.ID)); })("keydown.enter", function UserManagementComponent_Conditional_79_For_9_Template_div_keydown_enter_1_listener() { const user_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleUserExpansion(user_r10.ID)); });
|
|
293
|
+
i0.ɵɵelementStart(2, "div", 91);
|
|
294
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Template_div_click_2_listener($event) { i0.ɵɵrestoreView(_r9); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
295
|
+
i0.ɵɵelementStart(3, "input", 92);
|
|
296
|
+
i0.ɵɵlistener("change", function UserManagementComponent_Conditional_79_For_9_Template_input_change_3_listener($event) { const user_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleUserSelection(user_r10.ID, $event)); });
|
|
297
|
+
i0.ɵɵelementEnd()();
|
|
298
|
+
i0.ɵɵelementStart(4, "div", 93)(5, "div", 94);
|
|
299
|
+
i0.ɵɵtext(6);
|
|
177
300
|
i0.ɵɵelementEnd();
|
|
178
|
-
i0.ɵɵelementStart(
|
|
179
|
-
i0.ɵɵ
|
|
180
|
-
i0.ɵɵelement(6, "i", 70);
|
|
301
|
+
i0.ɵɵelementStart(7, "div", 95)(8, "h3", 96);
|
|
302
|
+
i0.ɵɵtext(9);
|
|
181
303
|
i0.ɵɵelementEnd();
|
|
182
|
-
i0.ɵɵelementStart(
|
|
183
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_74_Conditional_2_For_2_Template_button_click_7_listener($event) { const user_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); ctx_r2.confirmDeleteUser(user_r7); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
184
|
-
i0.ɵɵelement(8, "i", 73);
|
|
185
|
-
i0.ɵɵelementEnd()()();
|
|
186
|
-
i0.ɵɵelementStart(9, "div", 82)(10, "h3", 63);
|
|
304
|
+
i0.ɵɵelementStart(10, "p", 97);
|
|
187
305
|
i0.ɵɵtext(11);
|
|
306
|
+
i0.ɵɵelementEnd()()();
|
|
307
|
+
i0.ɵɵelementStart(12, "div", 98)(13, "span", 99);
|
|
308
|
+
i0.ɵɵelement(14, "i", 100);
|
|
309
|
+
i0.ɵɵtext(15);
|
|
188
310
|
i0.ɵɵelementEnd();
|
|
189
|
-
i0.ɵɵelementStart(
|
|
190
|
-
i0.ɵɵ
|
|
191
|
-
i0.ɵɵ
|
|
192
|
-
i0.ɵɵ
|
|
193
|
-
i0.ɵɵelement(
|
|
194
|
-
i0.ɵɵtext(16);
|
|
311
|
+
i0.ɵɵelementStart(16, "div", 101);
|
|
312
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Template_div_click_16_listener($event) { i0.ɵɵrestoreView(_r9); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
313
|
+
i0.ɵɵelementStart(17, "button", 102);
|
|
314
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Template_button_click_17_listener() { const user_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.editUser(user_r10)); });
|
|
315
|
+
i0.ɵɵelement(18, "i", 103);
|
|
195
316
|
i0.ɵɵelementEnd();
|
|
196
|
-
i0.ɵɵelementStart(
|
|
197
|
-
i0.ɵɵ
|
|
198
|
-
i0.ɵɵ
|
|
317
|
+
i0.ɵɵelementStart(19, "button", 104);
|
|
318
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Template_button_click_19_listener() { const user_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleUserStatus(user_r10)); });
|
|
319
|
+
i0.ɵɵelement(20, "i", 100);
|
|
199
320
|
i0.ɵɵelementEnd();
|
|
200
|
-
i0.ɵɵelementStart(21, "
|
|
201
|
-
i0.ɵɵ
|
|
202
|
-
i0.ɵɵ
|
|
321
|
+
i0.ɵɵelementStart(21, "button", 105);
|
|
322
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_79_For_9_Template_button_click_21_listener() { const user_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.confirmDeleteUser(user_r10)); });
|
|
323
|
+
i0.ɵɵelement(22, "i", 64);
|
|
203
324
|
i0.ɵɵelementEnd()();
|
|
204
|
-
i0.ɵɵelementStart(
|
|
205
|
-
i0.ɵɵelement(
|
|
206
|
-
i0.ɵɵ
|
|
207
|
-
i0.ɵɵ
|
|
208
|
-
i0.ɵɵelementEnd()
|
|
325
|
+
i0.ɵɵelementStart(23, "button", 106);
|
|
326
|
+
i0.ɵɵelement(24, "i", 107);
|
|
327
|
+
i0.ɵɵelementEnd()()();
|
|
328
|
+
i0.ɵɵtemplate(25, UserManagementComponent_Conditional_79_For_9_Conditional_25_Template, 52, 25, "div", 108);
|
|
329
|
+
i0.ɵɵelementEnd();
|
|
209
330
|
} if (rf & 2) {
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
i0.ɵɵ
|
|
213
|
-
i0.ɵɵ
|
|
214
|
-
i0.ɵɵ
|
|
215
|
-
i0.ɵɵtextInterpolate(user_r7.Name);
|
|
331
|
+
const user_r10 = ctx.$implicit;
|
|
332
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
333
|
+
i0.ɵɵclassProp("expanded", ctx_r1.isUserExpanded(user_r10.ID))("selected", ctx_r1.isUserSelected(user_r10.ID));
|
|
334
|
+
i0.ɵɵadvance();
|
|
335
|
+
i0.ɵɵattribute("aria-expanded", ctx_r1.isUserExpanded(user_r10.ID));
|
|
216
336
|
i0.ɵɵadvance(2);
|
|
217
|
-
i0.ɵɵ
|
|
337
|
+
i0.ɵɵproperty("checked", ctx_r1.isUserSelected(user_r10.ID));
|
|
338
|
+
i0.ɵɵattribute("aria-label", "Select " + user_r10.Name);
|
|
218
339
|
i0.ɵɵadvance(3);
|
|
219
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
340
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getUserInitials(user_r10), " ");
|
|
220
341
|
i0.ɵɵadvance(3);
|
|
221
|
-
i0.ɵɵ
|
|
342
|
+
i0.ɵɵtextInterpolate(user_r10.Name);
|
|
343
|
+
i0.ɵɵadvance(2);
|
|
344
|
+
i0.ɵɵtextInterpolate(user_r10.Email);
|
|
345
|
+
i0.ɵɵadvance(2);
|
|
346
|
+
i0.ɵɵclassMap(ctx_r1.getStatusClass(user_r10));
|
|
222
347
|
i0.ɵɵadvance();
|
|
223
|
-
i0.ɵɵ
|
|
348
|
+
i0.ɵɵclassMap("fa-solid " + ctx_r1.getStatusIcon(user_r10));
|
|
224
349
|
i0.ɵɵadvance();
|
|
225
|
-
i0.ɵɵ
|
|
350
|
+
i0.ɵɵtextInterpolate1(" ", user_r10.IsActive ? "Active" : "Inactive", " ");
|
|
351
|
+
i0.ɵɵadvance(2);
|
|
352
|
+
i0.ɵɵattribute("aria-label", "Edit " + user_r10.Name);
|
|
353
|
+
i0.ɵɵadvance(2);
|
|
354
|
+
i0.ɵɵproperty("title", user_r10.IsActive ? "Deactivate" : "Activate");
|
|
355
|
+
i0.ɵɵattribute("aria-label", (user_r10.IsActive ? "Deactivate " : "Activate ") + user_r10.Name);
|
|
226
356
|
i0.ɵɵadvance();
|
|
227
|
-
i0.ɵɵclassMap("fa-solid "
|
|
357
|
+
i0.ɵɵclassMap(user_r10.IsActive ? "fa-solid fa-toggle-on" : "fa-solid fa-toggle-off");
|
|
228
358
|
i0.ɵɵadvance();
|
|
229
|
-
i0.ɵɵ
|
|
359
|
+
i0.ɵɵattribute("aria-label", "Delete " + user_r10.Name);
|
|
230
360
|
i0.ɵɵadvance(4);
|
|
231
|
-
i0.ɵɵ
|
|
361
|
+
i0.ɵɵconditional(ctx_r1.isUserExpanded(user_r10.ID) ? 25 : -1);
|
|
232
362
|
} }
|
|
233
|
-
function
|
|
234
|
-
i0.ɵɵelementStart(0, "div",
|
|
235
|
-
i0.ɵɵelement(1, "i",
|
|
236
|
-
i0.ɵɵelementStart(2, "p",
|
|
363
|
+
function UserManagementComponent_Conditional_79_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
364
|
+
i0.ɵɵelementStart(0, "div", 88);
|
|
365
|
+
i0.ɵɵelement(1, "i", 127);
|
|
366
|
+
i0.ɵɵelementStart(2, "p", 128);
|
|
237
367
|
i0.ɵɵtext(3, "No users found");
|
|
238
368
|
i0.ɵɵelementEnd();
|
|
239
|
-
i0.ɵɵelementStart(4, "p",
|
|
369
|
+
i0.ɵɵelementStart(4, "p", 129);
|
|
240
370
|
i0.ɵɵtext(5, "Try adjusting your filters or add a new user");
|
|
241
371
|
i0.ɵɵelementEnd()();
|
|
242
372
|
} }
|
|
243
|
-
function
|
|
244
|
-
i0.ɵɵ
|
|
245
|
-
i0.ɵɵ
|
|
246
|
-
i0.ɵɵ
|
|
373
|
+
function UserManagementComponent_Conditional_79_Template(rf, ctx) { if (rf & 1) {
|
|
374
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
375
|
+
i0.ɵɵelementStart(0, "div", 47)(1, "div", 81)(2, "div", 82)(3, "label", 83)(4, "input", 84);
|
|
376
|
+
i0.ɵɵlistener("change", function UserManagementComponent_Conditional_79_Template_input_change_4_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleSelectAll()); });
|
|
247
377
|
i0.ɵɵelementEnd();
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
i0.ɵɵ
|
|
251
|
-
i0.ɵɵ
|
|
252
|
-
i0.ɵɵadvance(2);
|
|
253
|
-
i0.ɵɵconditional(ctx_r2.filteredUsers.length === 0 ? 3 : -1);
|
|
254
|
-
} }
|
|
255
|
-
function UserManagementComponent_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
256
|
-
i0.ɵɵelementStart(0, "div", 40);
|
|
257
|
-
i0.ɵɵtemplate(1, UserManagementComponent_Conditional_74_Conditional_1_Template, 22, 1, "div", 50)(2, UserManagementComponent_Conditional_74_Conditional_2_Template, 4, 1, "div", 51);
|
|
378
|
+
i0.ɵɵelementStart(5, "span", 85);
|
|
379
|
+
i0.ɵɵtext(6);
|
|
380
|
+
i0.ɵɵelementEnd()();
|
|
381
|
+
i0.ɵɵtemplate(7, UserManagementComponent_Conditional_79_Conditional_7_Template, 2, 1, "span", 86);
|
|
258
382
|
i0.ɵɵelementEnd();
|
|
383
|
+
i0.ɵɵrepeaterCreate(8, UserManagementComponent_Conditional_79_For_9_Template, 26, 22, "div", 87, _forTrack0);
|
|
384
|
+
i0.ɵɵtemplate(10, UserManagementComponent_Conditional_79_Conditional_10_Template, 6, 0, "div", 88);
|
|
385
|
+
i0.ɵɵelementEnd()();
|
|
259
386
|
} if (rf & 2) {
|
|
260
|
-
const
|
|
387
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
388
|
+
i0.ɵɵadvance(4);
|
|
389
|
+
i0.ɵɵproperty("checked", ctx_r1.isAllSelected)("indeterminate", ctx_r1.isIndeterminate);
|
|
390
|
+
i0.ɵɵadvance(2);
|
|
391
|
+
i0.ɵɵtextInterpolate1("Select All (", ctx_r1.filteredUsers.length, ")");
|
|
261
392
|
i0.ɵɵadvance();
|
|
262
|
-
i0.ɵɵconditional(
|
|
393
|
+
i0.ɵɵconditional(ctx_r1.hasSelection ? 7 : -1);
|
|
263
394
|
i0.ɵɵadvance();
|
|
264
|
-
i0.ɵɵ
|
|
395
|
+
i0.ɵɵrepeater(ctx_r1.filteredUsers);
|
|
396
|
+
i0.ɵɵadvance(2);
|
|
397
|
+
i0.ɵɵconditional(ctx_r1.filteredUsers.length === 0 ? 10 : -1);
|
|
265
398
|
} }
|
|
266
|
-
function
|
|
267
|
-
const
|
|
268
|
-
i0.ɵɵelementStart(0, "div",
|
|
269
|
-
i0.ɵɵlistener("click", function
|
|
270
|
-
i0.ɵɵelementStart(1, "div",
|
|
271
|
-
i0.ɵɵlistener("click", function
|
|
272
|
-
i0.ɵɵelementStart(2, "div",
|
|
273
|
-
i0.ɵɵelement(4, "i",
|
|
399
|
+
function UserManagementComponent_Conditional_81_Template(rf, ctx) { if (rf & 1) {
|
|
400
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
401
|
+
i0.ɵɵelementStart(0, "div", 130);
|
|
402
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_81_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showDeleteConfirm = false); });
|
|
403
|
+
i0.ɵɵelementStart(1, "div", 131);
|
|
404
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_81_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r13); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
405
|
+
i0.ɵɵelementStart(2, "div", 132)(3, "h3", 133);
|
|
406
|
+
i0.ɵɵelement(4, "i", 134);
|
|
274
407
|
i0.ɵɵtext(5, " Confirm Delete ");
|
|
275
408
|
i0.ɵɵelementEnd();
|
|
276
|
-
i0.ɵɵelementStart(6, "button",
|
|
277
|
-
i0.ɵɵlistener("click", function
|
|
278
|
-
i0.ɵɵelement(7, "i",
|
|
409
|
+
i0.ɵɵelementStart(6, "button", 135);
|
|
410
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_81_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showDeleteConfirm = false); });
|
|
411
|
+
i0.ɵɵelement(7, "i", 55);
|
|
279
412
|
i0.ɵɵelementEnd()();
|
|
280
|
-
i0.ɵɵelementStart(8, "div",
|
|
413
|
+
i0.ɵɵelementStart(8, "div", 136)(9, "p");
|
|
281
414
|
i0.ɵɵtext(10, "Are you sure you want to delete user ");
|
|
282
415
|
i0.ɵɵelementStart(11, "strong");
|
|
283
416
|
i0.ɵɵtext(12);
|
|
284
417
|
i0.ɵɵelementEnd();
|
|
285
418
|
i0.ɵɵtext(13, "?");
|
|
286
419
|
i0.ɵɵelementEnd();
|
|
287
|
-
i0.ɵɵelementStart(14, "p",
|
|
420
|
+
i0.ɵɵelementStart(14, "p", 137);
|
|
288
421
|
i0.ɵɵtext(15, "This action cannot be undone.");
|
|
289
422
|
i0.ɵɵelementEnd()();
|
|
290
|
-
i0.ɵɵelementStart(16, "div",
|
|
291
|
-
i0.ɵɵlistener("click", function
|
|
292
|
-
i0.ɵɵ
|
|
293
|
-
i0.ɵɵ
|
|
294
|
-
i0.ɵɵ
|
|
295
|
-
i0.ɵɵ
|
|
296
|
-
i0.ɵɵ
|
|
297
|
-
i0.ɵɵtext(21, "
|
|
423
|
+
i0.ɵɵelementStart(16, "div", 138)(17, "button", 139);
|
|
424
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_81_Template_button_click_17_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.deleteUser()); });
|
|
425
|
+
i0.ɵɵelement(18, "i", 64);
|
|
426
|
+
i0.ɵɵtext(19, " Delete User ");
|
|
427
|
+
i0.ɵɵelementEnd();
|
|
428
|
+
i0.ɵɵelementStart(20, "button", 140);
|
|
429
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_81_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showDeleteConfirm = false); });
|
|
430
|
+
i0.ɵɵtext(21, " Cancel ");
|
|
298
431
|
i0.ɵɵelementEnd()()()();
|
|
299
432
|
} if (rf & 2) {
|
|
300
|
-
const
|
|
433
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
301
434
|
i0.ɵɵadvance(12);
|
|
302
|
-
i0.ɵɵtextInterpolate(
|
|
435
|
+
i0.ɵɵtextInterpolate(ctx_r1.selectedUser.Name);
|
|
436
|
+
} }
|
|
437
|
+
function UserManagementComponent_Conditional_82_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
438
|
+
i0.ɵɵelement(0, "i", 134);
|
|
439
|
+
} }
|
|
440
|
+
function UserManagementComponent_Conditional_82_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
441
|
+
i0.ɵɵelement(0, "i", 143);
|
|
442
|
+
} }
|
|
443
|
+
function UserManagementComponent_Conditional_82_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
444
|
+
i0.ɵɵelement(0, "i", 144);
|
|
445
|
+
} }
|
|
446
|
+
function UserManagementComponent_Conditional_82_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
447
|
+
i0.ɵɵelementStart(0, "p", 137);
|
|
448
|
+
i0.ɵɵtext(1, "This action cannot be undone.");
|
|
449
|
+
i0.ɵɵelementEnd();
|
|
450
|
+
} }
|
|
451
|
+
function UserManagementComponent_Conditional_82_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
452
|
+
i0.ɵɵelement(0, "i", 148);
|
|
453
|
+
i0.ɵɵtext(1, " Processing... ");
|
|
454
|
+
} }
|
|
455
|
+
function UserManagementComponent_Conditional_82_Conditional_17_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
456
|
+
i0.ɵɵelement(0, "i", 64);
|
|
457
|
+
} }
|
|
458
|
+
function UserManagementComponent_Conditional_82_Conditional_17_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
459
|
+
i0.ɵɵelement(0, "i", 58);
|
|
460
|
+
} }
|
|
461
|
+
function UserManagementComponent_Conditional_82_Conditional_17_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
462
|
+
i0.ɵɵelement(0, "i", 60);
|
|
463
|
+
} }
|
|
464
|
+
function UserManagementComponent_Conditional_82_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
465
|
+
i0.ɵɵtemplate(0, UserManagementComponent_Conditional_82_Conditional_17_Conditional_0_Template, 1, 0, "i", 64)(1, UserManagementComponent_Conditional_82_Conditional_17_Conditional_1_Template, 1, 0, "i", 58)(2, UserManagementComponent_Conditional_82_Conditional_17_Conditional_2_Template, 1, 0, "i", 60);
|
|
466
|
+
i0.ɵɵtext(3);
|
|
467
|
+
} if (rf & 2) {
|
|
468
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
469
|
+
i0.ɵɵconditional(ctx_r1.bulkActionType === "delete" ? 0 : ctx_r1.bulkActionType === "enable" ? 1 : 2);
|
|
470
|
+
i0.ɵɵadvance(3);
|
|
471
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getBulkActionButtonText(), " ");
|
|
472
|
+
} }
|
|
473
|
+
function UserManagementComponent_Conditional_82_Template(rf, ctx) { if (rf & 1) {
|
|
474
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
475
|
+
i0.ɵɵelementStart(0, "div", 141);
|
|
476
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_82_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelBulkAction()); });
|
|
477
|
+
i0.ɵɵelementStart(1, "div", 131);
|
|
478
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_82_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r14); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
479
|
+
i0.ɵɵelementStart(2, "div", 132)(3, "h3", 142);
|
|
480
|
+
i0.ɵɵtemplate(4, UserManagementComponent_Conditional_82_Conditional_4_Template, 1, 0, "i", 134)(5, UserManagementComponent_Conditional_82_Conditional_5_Template, 1, 0, "i", 143)(6, UserManagementComponent_Conditional_82_Conditional_6_Template, 1, 0, "i", 144);
|
|
481
|
+
i0.ɵɵtext(7);
|
|
482
|
+
i0.ɵɵelementEnd();
|
|
483
|
+
i0.ɵɵelementStart(8, "button", 135);
|
|
484
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_82_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelBulkAction()); });
|
|
485
|
+
i0.ɵɵelement(9, "i", 55);
|
|
486
|
+
i0.ɵɵelementEnd()();
|
|
487
|
+
i0.ɵɵelementStart(10, "div", 145)(11, "p");
|
|
488
|
+
i0.ɵɵtext(12);
|
|
489
|
+
i0.ɵɵelementEnd();
|
|
490
|
+
i0.ɵɵtemplate(13, UserManagementComponent_Conditional_82_Conditional_13_Template, 2, 0, "p", 137);
|
|
491
|
+
i0.ɵɵelementEnd();
|
|
492
|
+
i0.ɵɵelementStart(14, "div", 138)(15, "button", 146);
|
|
493
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_82_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.executeBulkAction()); });
|
|
494
|
+
i0.ɵɵtemplate(16, UserManagementComponent_Conditional_82_Conditional_16_Template, 2, 0)(17, UserManagementComponent_Conditional_82_Conditional_17_Template, 4, 2);
|
|
495
|
+
i0.ɵɵelementEnd();
|
|
496
|
+
i0.ɵɵelementStart(18, "button", 147);
|
|
497
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_82_Template_button_click_18_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelBulkAction()); });
|
|
498
|
+
i0.ɵɵtext(19, " Cancel ");
|
|
499
|
+
i0.ɵɵelementEnd()()()();
|
|
500
|
+
} if (rf & 2) {
|
|
501
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
502
|
+
i0.ɵɵadvance(4);
|
|
503
|
+
i0.ɵɵconditional(ctx_r1.bulkActionType === "delete" ? 4 : ctx_r1.bulkActionType === "enable" ? 5 : 6);
|
|
504
|
+
i0.ɵɵadvance(3);
|
|
505
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getBulkActionTitle(), " ");
|
|
506
|
+
i0.ɵɵadvance(5);
|
|
507
|
+
i0.ɵɵtextInterpolate(ctx_r1.getBulkActionMessage());
|
|
508
|
+
i0.ɵɵadvance();
|
|
509
|
+
i0.ɵɵconditional(ctx_r1.bulkActionType === "delete" ? 13 : -1);
|
|
510
|
+
i0.ɵɵadvance(2);
|
|
511
|
+
i0.ɵɵclassMap(ctx_r1.bulkActionType === "delete" ? "mj-btn mj-btn-danger" : "mj-btn mj-btn-primary");
|
|
512
|
+
i0.ɵɵproperty("disabled", ctx_r1.isLoading);
|
|
513
|
+
i0.ɵɵadvance();
|
|
514
|
+
i0.ɵɵconditional(ctx_r1.isLoading ? 16 : 17);
|
|
515
|
+
i0.ɵɵadvance(2);
|
|
516
|
+
i0.ɵɵproperty("disabled", ctx_r1.isLoading);
|
|
517
|
+
} }
|
|
518
|
+
function UserManagementComponent_Conditional_83_For_18_Template(rf, ctx) { if (rf & 1) {
|
|
519
|
+
i0.ɵɵelementStart(0, "option", 42);
|
|
520
|
+
i0.ɵɵtext(1);
|
|
521
|
+
i0.ɵɵelementEnd();
|
|
522
|
+
} if (rf & 2) {
|
|
523
|
+
const role_r16 = ctx.$implicit;
|
|
524
|
+
i0.ɵɵproperty("value", role_r16.ID);
|
|
525
|
+
i0.ɵɵadvance();
|
|
526
|
+
i0.ɵɵtextInterpolate(role_r16.Name);
|
|
527
|
+
} }
|
|
528
|
+
function UserManagementComponent_Conditional_83_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
529
|
+
i0.ɵɵelement(0, "i", 148);
|
|
530
|
+
i0.ɵɵtext(1, " Assigning... ");
|
|
531
|
+
} }
|
|
532
|
+
function UserManagementComponent_Conditional_83_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
533
|
+
i0.ɵɵelement(0, "i", 62);
|
|
534
|
+
i0.ɵɵtext(1, " Assign Role ");
|
|
535
|
+
} }
|
|
536
|
+
function UserManagementComponent_Conditional_83_Template(rf, ctx) { if (rf & 1) {
|
|
537
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
538
|
+
i0.ɵɵelementStart(0, "div", 149);
|
|
539
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_83_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelBulkRoleAssign()); });
|
|
540
|
+
i0.ɵɵelementStart(1, "div", 131);
|
|
541
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_83_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r15); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
542
|
+
i0.ɵɵelementStart(2, "div", 132)(3, "h3", 150);
|
|
543
|
+
i0.ɵɵelement(4, "i", 62);
|
|
544
|
+
i0.ɵɵtext(5);
|
|
545
|
+
i0.ɵɵelementEnd();
|
|
546
|
+
i0.ɵɵelementStart(6, "button", 135);
|
|
547
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_83_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelBulkRoleAssign()); });
|
|
548
|
+
i0.ɵɵelement(7, "i", 55);
|
|
549
|
+
i0.ɵɵelementEnd()();
|
|
550
|
+
i0.ɵɵelementStart(8, "div", 151)(9, "p");
|
|
551
|
+
i0.ɵɵtext(10, "Select a role to assign to the selected users:");
|
|
552
|
+
i0.ɵɵelementEnd();
|
|
553
|
+
i0.ɵɵelementStart(11, "div", 152)(12, "label", 153);
|
|
554
|
+
i0.ɵɵtext(13, "Role");
|
|
555
|
+
i0.ɵɵelementEnd();
|
|
556
|
+
i0.ɵɵelementStart(14, "select", 154);
|
|
557
|
+
i0.ɵɵtwoWayListener("ngModelChange", function UserManagementComponent_Conditional_83_Template_select_ngModelChange_14_listener($event) { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.bulkRoleId, $event) || (ctx_r1.bulkRoleId = $event); return i0.ɵɵresetView($event); });
|
|
558
|
+
i0.ɵɵelementStart(15, "option", 41);
|
|
559
|
+
i0.ɵɵtext(16, "Select a role...");
|
|
560
|
+
i0.ɵɵelementEnd();
|
|
561
|
+
i0.ɵɵrepeaterCreate(17, UserManagementComponent_Conditional_83_For_18_Template, 2, 2, "option", 42, _forTrack0);
|
|
562
|
+
i0.ɵɵelementEnd()()();
|
|
563
|
+
i0.ɵɵelementStart(19, "div", 138)(20, "button", 155);
|
|
564
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_83_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.executeBulkRoleAssign()); });
|
|
565
|
+
i0.ɵɵtemplate(21, UserManagementComponent_Conditional_83_Conditional_21_Template, 2, 0)(22, UserManagementComponent_Conditional_83_Conditional_22_Template, 2, 0);
|
|
566
|
+
i0.ɵɵelementEnd();
|
|
567
|
+
i0.ɵɵelementStart(23, "button", 147);
|
|
568
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Conditional_83_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r15); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelBulkRoleAssign()); });
|
|
569
|
+
i0.ɵɵtext(24, " Cancel ");
|
|
570
|
+
i0.ɵɵelementEnd()()()();
|
|
571
|
+
} if (rf & 2) {
|
|
572
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
573
|
+
i0.ɵɵadvance(5);
|
|
574
|
+
i0.ɵɵtextInterpolate2(" Assign Role to ", ctx_r1.selectedCount, " User", ctx_r1.selectedCount > 1 ? "s" : "", " ");
|
|
575
|
+
i0.ɵɵadvance(9);
|
|
576
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.bulkRoleId);
|
|
577
|
+
i0.ɵɵadvance(3);
|
|
578
|
+
i0.ɵɵrepeater(ctx_r1.roles);
|
|
579
|
+
i0.ɵɵadvance(3);
|
|
580
|
+
i0.ɵɵproperty("disabled", !ctx_r1.bulkRoleId || ctx_r1.isLoading);
|
|
581
|
+
i0.ɵɵadvance();
|
|
582
|
+
i0.ɵɵconditional(ctx_r1.isLoading ? 21 : 22);
|
|
583
|
+
i0.ɵɵadvance(2);
|
|
584
|
+
i0.ɵɵproperty("disabled", ctx_r1.isLoading);
|
|
303
585
|
} }
|
|
304
586
|
let UserManagementComponent = class UserManagementComponent extends BaseDashboard {
|
|
305
587
|
// State management
|
|
@@ -309,9 +591,16 @@ let UserManagementComponent = class UserManagementComponent extends BaseDashboar
|
|
|
309
591
|
selectedUser = null;
|
|
310
592
|
isLoading = false;
|
|
311
593
|
error = null;
|
|
594
|
+
// Selection state for bulk actions
|
|
595
|
+
selectedUserIds = new Set();
|
|
312
596
|
// Dialog state
|
|
313
597
|
showUserDialog = false;
|
|
314
598
|
userDialogData = null;
|
|
599
|
+
// Bulk action dialog state
|
|
600
|
+
showBulkActionConfirm = false;
|
|
601
|
+
bulkActionType = null;
|
|
602
|
+
showBulkRoleAssign = false;
|
|
603
|
+
bulkRoleId = '';
|
|
315
604
|
// Stats
|
|
316
605
|
stats = {
|
|
317
606
|
totalUsers: 0,
|
|
@@ -329,7 +618,9 @@ let UserManagementComponent = class UserManagementComponent extends BaseDashboar
|
|
|
329
618
|
showCreateDialog = false;
|
|
330
619
|
showEditDialog = false;
|
|
331
620
|
showDeleteConfirm = false;
|
|
332
|
-
|
|
621
|
+
showMobileFilters = false;
|
|
622
|
+
// Mobile expansion state
|
|
623
|
+
expandedUserIds = new Set();
|
|
333
624
|
// User-Role mapping
|
|
334
625
|
userRoleMap = new Map(); // userId -> roleIds[]
|
|
335
626
|
// Grid configuration
|
|
@@ -535,9 +826,6 @@ let UserManagementComponent = class UserManagementComponent extends BaseDashboar
|
|
|
535
826
|
user.IsActive = !user.IsActive; // Revert on error
|
|
536
827
|
}
|
|
537
828
|
}
|
|
538
|
-
toggleViewMode() {
|
|
539
|
-
this.viewMode = this.viewMode === 'grid' ? 'cards' : 'grid';
|
|
540
|
-
}
|
|
541
829
|
exportUsers() {
|
|
542
830
|
if (this.filteredUsers.length === 0) {
|
|
543
831
|
this.error = 'No users to export';
|
|
@@ -618,109 +906,336 @@ let UserManagementComponent = class UserManagementComponent extends BaseDashboar
|
|
|
618
906
|
this.loadInitialData();
|
|
619
907
|
}
|
|
620
908
|
}
|
|
909
|
+
// Selection methods for bulk actions
|
|
910
|
+
get isAllSelected() {
|
|
911
|
+
return this.filteredUsers.length > 0 &&
|
|
912
|
+
this.filteredUsers.every(user => this.selectedUserIds.has(user.ID));
|
|
913
|
+
}
|
|
914
|
+
get isIndeterminate() {
|
|
915
|
+
const selectedCount = this.filteredUsers.filter(user => this.selectedUserIds.has(user.ID)).length;
|
|
916
|
+
return selectedCount > 0 && selectedCount < this.filteredUsers.length;
|
|
917
|
+
}
|
|
918
|
+
get hasSelection() {
|
|
919
|
+
return this.selectedUserIds.size > 0;
|
|
920
|
+
}
|
|
921
|
+
get selectedCount() {
|
|
922
|
+
return this.selectedUserIds.size;
|
|
923
|
+
}
|
|
924
|
+
get hasActiveFilters() {
|
|
925
|
+
const filters = this.filters$.value;
|
|
926
|
+
return filters.status !== 'all' || filters.role !== '';
|
|
927
|
+
}
|
|
928
|
+
get activeFilterCount() {
|
|
929
|
+
let count = 0;
|
|
930
|
+
const filters = this.filters$.value;
|
|
931
|
+
if (filters.status !== 'all')
|
|
932
|
+
count++;
|
|
933
|
+
if (filters.role !== '')
|
|
934
|
+
count++;
|
|
935
|
+
return count;
|
|
936
|
+
}
|
|
937
|
+
clearFilters() {
|
|
938
|
+
this.filters$.next({
|
|
939
|
+
...this.filters$.value,
|
|
940
|
+
status: 'all',
|
|
941
|
+
role: ''
|
|
942
|
+
});
|
|
943
|
+
this.showMobileFilters = false;
|
|
944
|
+
}
|
|
945
|
+
toggleSelectAll() {
|
|
946
|
+
if (this.isAllSelected) {
|
|
947
|
+
// Deselect all filtered users
|
|
948
|
+
this.filteredUsers.forEach(user => this.selectedUserIds.delete(user.ID));
|
|
949
|
+
}
|
|
950
|
+
else {
|
|
951
|
+
// Select all filtered users
|
|
952
|
+
this.filteredUsers.forEach(user => this.selectedUserIds.add(user.ID));
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
toggleUserSelection(userId, event) {
|
|
956
|
+
if (event) {
|
|
957
|
+
event.stopPropagation();
|
|
958
|
+
}
|
|
959
|
+
if (this.selectedUserIds.has(userId)) {
|
|
960
|
+
this.selectedUserIds.delete(userId);
|
|
961
|
+
}
|
|
962
|
+
else {
|
|
963
|
+
this.selectedUserIds.add(userId);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
isUserSelected(userId) {
|
|
967
|
+
return this.selectedUserIds.has(userId);
|
|
968
|
+
}
|
|
969
|
+
clearSelection() {
|
|
970
|
+
this.selectedUserIds.clear();
|
|
971
|
+
}
|
|
972
|
+
// Bulk action methods
|
|
973
|
+
confirmBulkAction(action) {
|
|
974
|
+
if (!this.hasSelection)
|
|
975
|
+
return;
|
|
976
|
+
this.bulkActionType = action;
|
|
977
|
+
this.showBulkActionConfirm = true;
|
|
978
|
+
}
|
|
979
|
+
cancelBulkAction() {
|
|
980
|
+
this.showBulkActionConfirm = false;
|
|
981
|
+
this.bulkActionType = null;
|
|
982
|
+
}
|
|
983
|
+
async executeBulkAction() {
|
|
984
|
+
if (!this.bulkActionType || !this.hasSelection)
|
|
985
|
+
return;
|
|
986
|
+
try {
|
|
987
|
+
this.isLoading = true;
|
|
988
|
+
const selectedUsers = this.users.filter(user => this.selectedUserIds.has(user.ID));
|
|
989
|
+
switch (this.bulkActionType) {
|
|
990
|
+
case 'enable':
|
|
991
|
+
await this.bulkSetUserStatus(selectedUsers, true);
|
|
992
|
+
break;
|
|
993
|
+
case 'disable':
|
|
994
|
+
await this.bulkSetUserStatus(selectedUsers, false);
|
|
995
|
+
break;
|
|
996
|
+
case 'delete':
|
|
997
|
+
await this.bulkDeleteUsers(selectedUsers);
|
|
998
|
+
break;
|
|
999
|
+
}
|
|
1000
|
+
this.clearSelection();
|
|
1001
|
+
this.showBulkActionConfirm = false;
|
|
1002
|
+
this.bulkActionType = null;
|
|
1003
|
+
await this.loadInitialData();
|
|
1004
|
+
}
|
|
1005
|
+
catch (error) {
|
|
1006
|
+
console.error('Bulk action failed:', error);
|
|
1007
|
+
this.error = error instanceof Error ? error.message : 'Bulk action failed';
|
|
1008
|
+
}
|
|
1009
|
+
finally {
|
|
1010
|
+
this.isLoading = false;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
async bulkSetUserStatus(users, isActive) {
|
|
1014
|
+
for (const user of users) {
|
|
1015
|
+
user.IsActive = isActive;
|
|
1016
|
+
const result = await user.Save();
|
|
1017
|
+
if (!result) {
|
|
1018
|
+
throw new Error(`Failed to update user ${user.Name}: ${user.LatestResult?.Message}`);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
async bulkDeleteUsers(users) {
|
|
1023
|
+
for (const user of users) {
|
|
1024
|
+
const result = await user.Delete();
|
|
1025
|
+
if (!result) {
|
|
1026
|
+
throw new Error(`Failed to delete user ${user.Name}: ${user.LatestResult?.Message}`);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
// Bulk role assignment
|
|
1031
|
+
openBulkRoleAssign() {
|
|
1032
|
+
if (!this.hasSelection)
|
|
1033
|
+
return;
|
|
1034
|
+
this.bulkRoleId = '';
|
|
1035
|
+
this.showBulkRoleAssign = true;
|
|
1036
|
+
}
|
|
1037
|
+
cancelBulkRoleAssign() {
|
|
1038
|
+
this.showBulkRoleAssign = false;
|
|
1039
|
+
this.bulkRoleId = '';
|
|
1040
|
+
}
|
|
1041
|
+
async executeBulkRoleAssign() {
|
|
1042
|
+
if (!this.bulkRoleId || !this.hasSelection)
|
|
1043
|
+
return;
|
|
1044
|
+
try {
|
|
1045
|
+
this.isLoading = true;
|
|
1046
|
+
const selectedUserIds = Array.from(this.selectedUserIds);
|
|
1047
|
+
for (const userId of selectedUserIds) {
|
|
1048
|
+
// Check if user already has this role
|
|
1049
|
+
const existingRoles = this.userRoleMap.get(userId) || [];
|
|
1050
|
+
if (!existingRoles.includes(this.bulkRoleId)) {
|
|
1051
|
+
const userRole = await this.metadata.GetEntityObject('User Roles');
|
|
1052
|
+
userRole.NewRecord();
|
|
1053
|
+
userRole.UserID = userId;
|
|
1054
|
+
userRole.RoleID = this.bulkRoleId;
|
|
1055
|
+
const result = await userRole.Save();
|
|
1056
|
+
if (!result) {
|
|
1057
|
+
console.warn(`Failed to assign role to user ${userId}:`, userRole.LatestResult?.Message);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
this.clearSelection();
|
|
1062
|
+
this.showBulkRoleAssign = false;
|
|
1063
|
+
this.bulkRoleId = '';
|
|
1064
|
+
await this.loadInitialData();
|
|
1065
|
+
}
|
|
1066
|
+
catch (error) {
|
|
1067
|
+
console.error('Bulk role assignment failed:', error);
|
|
1068
|
+
this.error = error instanceof Error ? error.message : 'Bulk role assignment failed';
|
|
1069
|
+
}
|
|
1070
|
+
finally {
|
|
1071
|
+
this.isLoading = false;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
getBulkActionMessage() {
|
|
1075
|
+
const count = this.selectedCount;
|
|
1076
|
+
switch (this.bulkActionType) {
|
|
1077
|
+
case 'enable':
|
|
1078
|
+
return `Are you sure you want to enable ${count} user${count > 1 ? 's' : ''}?`;
|
|
1079
|
+
case 'disable':
|
|
1080
|
+
return `Are you sure you want to disable ${count} user${count > 1 ? 's' : ''}?`;
|
|
1081
|
+
case 'delete':
|
|
1082
|
+
return `Are you sure you want to delete ${count} user${count > 1 ? 's' : ''}? This action cannot be undone.`;
|
|
1083
|
+
default:
|
|
1084
|
+
return '';
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
getBulkActionTitle() {
|
|
1088
|
+
switch (this.bulkActionType) {
|
|
1089
|
+
case 'enable':
|
|
1090
|
+
return 'Enable Users';
|
|
1091
|
+
case 'disable':
|
|
1092
|
+
return 'Disable Users';
|
|
1093
|
+
case 'delete':
|
|
1094
|
+
return 'Delete Users';
|
|
1095
|
+
default:
|
|
1096
|
+
return 'Confirm Action';
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
getBulkActionButtonText() {
|
|
1100
|
+
const count = this.selectedCount;
|
|
1101
|
+
switch (this.bulkActionType) {
|
|
1102
|
+
case 'enable':
|
|
1103
|
+
return `Enable ${count} User${count > 1 ? 's' : ''}`;
|
|
1104
|
+
case 'disable':
|
|
1105
|
+
return `Disable ${count} User${count > 1 ? 's' : ''}`;
|
|
1106
|
+
case 'delete':
|
|
1107
|
+
return `Delete ${count} User${count > 1 ? 's' : ''}`;
|
|
1108
|
+
default:
|
|
1109
|
+
return 'Confirm';
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
// Expansion methods
|
|
1113
|
+
toggleUserExpansion(userId) {
|
|
1114
|
+
if (this.expandedUserIds.has(userId)) {
|
|
1115
|
+
this.expandedUserIds.delete(userId);
|
|
1116
|
+
}
|
|
1117
|
+
else {
|
|
1118
|
+
this.expandedUserIds.add(userId);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
isUserExpanded(userId) {
|
|
1122
|
+
return this.expandedUserIds.has(userId);
|
|
1123
|
+
}
|
|
1124
|
+
// Get roles for a specific user
|
|
1125
|
+
getUserRoles(userId) {
|
|
1126
|
+
const roleIds = this.userRoleMap.get(userId) || [];
|
|
1127
|
+
return this.roles.filter(role => roleIds.includes(role.ID));
|
|
1128
|
+
}
|
|
621
1129
|
static ɵfac = function UserManagementComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserManagementComponent)(); };
|
|
622
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserManagementComponent, selectors: [["mj-user-management"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
623
|
-
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "
|
|
624
|
-
i0.ɵɵlistener("click", function
|
|
625
|
-
i0.ɵɵelement(
|
|
626
|
-
i0.ɵɵ
|
|
627
|
-
i0.ɵɵ
|
|
628
|
-
i0.ɵɵelementStart(5, "button", 4);
|
|
629
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_5_listener() { return ctx.exportUsers(); });
|
|
630
|
-
i0.ɵɵelement(6, "i", 5);
|
|
631
|
-
i0.ɵɵtext(7, " Export ");
|
|
632
|
-
i0.ɵɵelementEnd();
|
|
633
|
-
i0.ɵɵelementStart(8, "button", 6);
|
|
634
|
-
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_8_listener() { return ctx.createNewUser(); });
|
|
635
|
-
i0.ɵɵelement(9, "i", 7);
|
|
636
|
-
i0.ɵɵtext(10, " Add User ");
|
|
1130
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UserManagementComponent, selectors: [["mj-user-management"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 84, vars: 31, consts: [[1, "user-management-container"], [1, "sticky-header"], ["role", "toolbar", "aria-label", "User management actions", 1, "action-buttons"], ["aria-label", "Refresh user list", 1, "mj-btn", "mj-btn-secondary", "mj-btn-icon-mobile", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "btn-text"], ["aria-label", "Export users to file", 1, "mj-btn", "mj-btn-secondary", "mj-btn-icon-mobile", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-download"], ["aria-label", "Add new user", 1, "mj-btn", "mj-btn-primary", "mj-btn-icon-mobile", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], ["role", "toolbar", "aria-label", "Bulk actions", 1, "bulk-action-toolbar"], ["role", "region", "aria-label", "User statistics", 1, "mj-grid-4"], [1, "mj-card"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-total"], [1, "fa-solid", "fa-users"], [1, "stat-content"], ["aria-label", "Total users count", 1, "stat-value"], [1, "stat-label"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-active"], [1, "fa-solid", "fa-user-check"], ["aria-label", "Active users count", 1, "stat-value"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-inactive"], [1, "fa-solid", "fa-user-xmark"], ["aria-label", "Inactive users count", 1, "stat-value"], ["aria-hidden", "true", 1, "stat-icon", "stat-icon-admin"], [1, "fa-solid", "fa-shield-halved"], ["aria-label", "Owner users count", 1, "stat-value"], ["role", "search", "aria-label", "Filter users", 1, "filters-section"], [1, "filters-row"], [1, "mj-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "mj-search-icon"], ["type", "text", "placeholder", "Search users by name or email...", "aria-label", "Search users by name or email", 1, "mj-search-input", 3, "input", "value"], ["aria-label", "Toggle filters", 1, "mobile-filter-toggle", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], [1, "filter-badge"], [1, "mj-filter-group", "desktop-filter-group"], ["id", "status-filter-label", 1, "mj-filter-label"], ["role", "group", "aria-labelledby", "status-filter-label", 1, "mj-filter-buttons"], [1, "mj-btn", "mj-btn-ghost", 3, "click"], ["for", "role-filter", 1, "mj-filter-label"], ["id", "role-filter", "aria-label", "Filter by role", 1, "mj-filter-select", 3, "change"], ["value", ""], [3, "value"], [1, "mobile-filter-dropdown"], [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", "data", "visible"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "delete-dialog-title", "aria-describedby", "delete-dialog-desc", 1, "modal-backdrop"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "bulk-action-dialog-title", "aria-describedby", "bulk-action-dialog-desc", 1, "modal-backdrop"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "bulk-role-dialog-title", "aria-describedby", "bulk-role-dialog-desc", 1, "modal-backdrop"], [1, "bulk-selection-info"], ["aria-hidden", "true", 1, "fa-solid", "fa-check-square"], ["aria-label", "Clear selection", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], [1, "bulk-action-buttons"], ["aria-label", "Enable selected users", 1, "mj-btn", "mj-btn-secondary", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-toggle-on"], ["aria-label", "Disable selected users", 1, "mj-btn", "mj-btn-secondary", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-toggle-off"], ["aria-label", "Assign role to selected users", 1, "mj-btn", "mj-btn-secondary", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-user-tag"], ["aria-label", "Delete selected users", 1, "mj-btn", "mj-btn-danger", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-trash"], [1, "mobile-filter-content"], [1, "mj-filter-group"], ["id", "status-filter-label-mobile", 1, "mj-filter-label"], ["aria-labelledby", "status-filter-label-mobile", 1, "mj-filter-select", 3, "change", "value"], ["value", "all"], ["value", "active"], ["value", "inactive"], ["for", "role-filter-mobile", 1, "mj-filter-label"], ["id", "role-filter-mobile", "aria-label", "Filter by role", 1, "mj-filter-select", 3, "change"], [1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", "clear-filters-btn"], [1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", "clear-filters-btn", 3, "click"], ["text", "Loading users...", "size", "medium"], [1, "error-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], ["aria-label", "Retry loading users", 1, "retry-button", 3, "click"], ["role", "list", "aria-label", "Users list", 1, "users-list"], [1, "list-header"], [1, "select-all-label"], ["type", "checkbox", "aria-label", "Select all users", 1, "checkbox", 3, "change", "checked", "indeterminate"], [1, "select-all-text"], [1, "selection-count"], ["role", "listitem", 1, "user-card", 3, "expanded", "selected"], ["role", "status", 1, "empty-state"], ["role", "listitem", 1, "user-card"], ["role", "button", "tabindex", "0", 1, "user-header", 3, "click", "keydown.enter"], [1, "user-selection", 3, "click"], ["type", "checkbox", 1, "checkbox", 3, "change", "checked"], [1, "user-info"], ["aria-hidden", "true", 1, "user-avatar"], [1, "user-details"], [1, "user-name"], [1, "user-email"], [1, "user-meta"], [1, "status-badge"], ["aria-hidden", "true"], [1, "user-actions", "desktop-only", 3, "click"], ["title", "Edit", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-edit"], [1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click", "title"], ["title", "Delete", 1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", "mj-btn-danger", 3, "click"], ["aria-label", "Toggle user details", 1, "expand-btn"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down"], [1, "user-content"], [1, "mobile-actions-bar", 3, "click"], [1, "mobile-action-buttons"], [1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", 3, "click"], [1, "btn-label"], [1, "mj-btn", "mj-btn-ghost", "mj-btn-sm", "mj-btn-danger", 3, "click"], [1, "user-stats"], [1, "stat-item"], [1, "stat-value"], ["aria-hidden", "true", 1, "fa-solid", "fa-id-card"], ["aria-hidden", "true", 1, "fa-solid", "fa-calendar"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock"], [1, "roles-section"], [1, "section-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-user-shield"], [1, "roles-grid"], [1, "no-roles"], [1, "role-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-shield"], ["aria-hidden", "true", 1, "fa-solid", "fa-users-slash", "empty-icon"], [1, "empty-text"], [1, "empty-subtext"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "delete-dialog-title", "aria-describedby", "delete-dialog-desc", 1, "modal-backdrop", 3, "click"], [1, "modal-dialog", 3, "click"], [1, "modal-header"], ["id", "delete-dialog-title", 1, "modal-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "text-danger"], ["aria-label", "Close dialog", 1, "modal-close", 3, "click"], ["id", "delete-dialog-desc", 1, "modal-body"], [1, "text-muted"], [1, "modal-footer"], [1, "mj-btn", "mj-btn-danger", 3, "click"], [1, "mj-btn", "mj-btn-secondary", 3, "click"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "bulk-action-dialog-title", "aria-describedby", "bulk-action-dialog-desc", 1, "modal-backdrop", 3, "click"], ["id", "bulk-action-dialog-title", 1, "modal-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-toggle-on", "text-success"], ["aria-hidden", "true", 1, "fa-solid", "fa-toggle-off", "text-warning"], ["id", "bulk-action-dialog-desc", 1, "modal-body"], [3, "click", "disabled"], [1, "mj-btn", "mj-btn-secondary", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "bulk-role-dialog-title", "aria-describedby", "bulk-role-dialog-desc", 1, "modal-backdrop", 3, "click"], ["id", "bulk-role-dialog-title", 1, "modal-title"], ["id", "bulk-role-dialog-desc", 1, "modal-body"], [1, "form-field"], ["for", "bulk-role-select", 1, "field-label"], ["id", "bulk-role-select", "aria-label", "Select role to assign", 1, "field-select", 3, "ngModelChange", "ngModel"], [1, "mj-btn", "mj-btn-primary", 3, "click", "disabled"]], template: function UserManagementComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1131
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "button", 3);
|
|
1132
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_3_listener() { return ctx.refreshData(); });
|
|
1133
|
+
i0.ɵɵelement(4, "i", 4);
|
|
1134
|
+
i0.ɵɵelementStart(5, "span", 5);
|
|
1135
|
+
i0.ɵɵtext(6, "Refresh");
|
|
637
1136
|
i0.ɵɵelementEnd()();
|
|
638
|
-
i0.ɵɵelementStart(
|
|
639
|
-
i0.ɵɵ
|
|
1137
|
+
i0.ɵɵelementStart(7, "button", 6);
|
|
1138
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_7_listener() { return ctx.exportUsers(); });
|
|
1139
|
+
i0.ɵɵelement(8, "i", 7);
|
|
1140
|
+
i0.ɵɵelementStart(9, "span", 5);
|
|
1141
|
+
i0.ɵɵtext(10, "Export");
|
|
1142
|
+
i0.ɵɵelementEnd()();
|
|
1143
|
+
i0.ɵɵelementStart(11, "button", 8);
|
|
1144
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_11_listener() { return ctx.createNewUser(); });
|
|
1145
|
+
i0.ɵɵelement(12, "i", 9);
|
|
1146
|
+
i0.ɵɵelementStart(13, "span", 5);
|
|
1147
|
+
i0.ɵɵtext(14, "Add User");
|
|
1148
|
+
i0.ɵɵelementEnd()()();
|
|
1149
|
+
i0.ɵɵtemplate(15, UserManagementComponent_Conditional_15_Template, 25, 2, "div", 10);
|
|
1150
|
+
i0.ɵɵelementStart(16, "div", 11)(17, "div", 12)(18, "div", 13);
|
|
1151
|
+
i0.ɵɵelement(19, "i", 14);
|
|
640
1152
|
i0.ɵɵelementEnd();
|
|
641
|
-
i0.ɵɵelementStart(
|
|
642
|
-
i0.ɵɵtext(
|
|
1153
|
+
i0.ɵɵelementStart(20, "div", 15)(21, "div", 16);
|
|
1154
|
+
i0.ɵɵtext(22);
|
|
643
1155
|
i0.ɵɵelementEnd();
|
|
644
|
-
i0.ɵɵelementStart(
|
|
645
|
-
i0.ɵɵtext(
|
|
1156
|
+
i0.ɵɵelementStart(23, "div", 17);
|
|
1157
|
+
i0.ɵɵtext(24, "Total Users");
|
|
646
1158
|
i0.ɵɵelementEnd()()();
|
|
647
|
-
i0.ɵɵelementStart(
|
|
648
|
-
i0.ɵɵelement(
|
|
1159
|
+
i0.ɵɵelementStart(25, "div", 12)(26, "div", 18);
|
|
1160
|
+
i0.ɵɵelement(27, "i", 19);
|
|
649
1161
|
i0.ɵɵelementEnd();
|
|
650
|
-
i0.ɵɵelementStart(
|
|
651
|
-
i0.ɵɵtext(
|
|
1162
|
+
i0.ɵɵelementStart(28, "div", 15)(29, "div", 20);
|
|
1163
|
+
i0.ɵɵtext(30);
|
|
652
1164
|
i0.ɵɵelementEnd();
|
|
653
|
-
i0.ɵɵelementStart(
|
|
654
|
-
i0.ɵɵtext(
|
|
1165
|
+
i0.ɵɵelementStart(31, "div", 17);
|
|
1166
|
+
i0.ɵɵtext(32, "Active Users");
|
|
655
1167
|
i0.ɵɵelementEnd()()();
|
|
656
|
-
i0.ɵɵelementStart(
|
|
657
|
-
i0.ɵɵelement(
|
|
1168
|
+
i0.ɵɵelementStart(33, "div", 12)(34, "div", 21);
|
|
1169
|
+
i0.ɵɵelement(35, "i", 22);
|
|
658
1170
|
i0.ɵɵelementEnd();
|
|
659
|
-
i0.ɵɵelementStart(
|
|
660
|
-
i0.ɵɵtext(
|
|
1171
|
+
i0.ɵɵelementStart(36, "div", 15)(37, "div", 23);
|
|
1172
|
+
i0.ɵɵtext(38);
|
|
661
1173
|
i0.ɵɵelementEnd();
|
|
662
|
-
i0.ɵɵelementStart(
|
|
663
|
-
i0.ɵɵtext(
|
|
1174
|
+
i0.ɵɵelementStart(39, "div", 17);
|
|
1175
|
+
i0.ɵɵtext(40, "Inactive Users");
|
|
664
1176
|
i0.ɵɵelementEnd()()();
|
|
665
|
-
i0.ɵɵelementStart(
|
|
666
|
-
i0.ɵɵelement(
|
|
1177
|
+
i0.ɵɵelementStart(41, "div", 12)(42, "div", 24);
|
|
1178
|
+
i0.ɵɵelement(43, "i", 25);
|
|
667
1179
|
i0.ɵɵelementEnd();
|
|
668
|
-
i0.ɵɵelementStart(
|
|
669
|
-
i0.ɵɵtext(
|
|
1180
|
+
i0.ɵɵelementStart(44, "div", 15)(45, "div", 26);
|
|
1181
|
+
i0.ɵɵtext(46);
|
|
670
1182
|
i0.ɵɵelementEnd();
|
|
671
|
-
i0.ɵɵelementStart(
|
|
672
|
-
i0.ɵɵtext(
|
|
1183
|
+
i0.ɵɵelementStart(47, "div", 17);
|
|
1184
|
+
i0.ɵɵtext(48, "Owners");
|
|
673
1185
|
i0.ɵɵelementEnd()()()();
|
|
674
|
-
i0.ɵɵelementStart(
|
|
675
|
-
i0.ɵɵelement(
|
|
676
|
-
i0.ɵɵelementStart(
|
|
677
|
-
i0.ɵɵlistener("input", function
|
|
1186
|
+
i0.ɵɵelementStart(49, "div", 27)(50, "div", 28)(51, "div", 29);
|
|
1187
|
+
i0.ɵɵelement(52, "i", 30);
|
|
1188
|
+
i0.ɵɵelementStart(53, "input", 31);
|
|
1189
|
+
i0.ɵɵlistener("input", function UserManagementComponent_Template_input_input_53_listener($event) { return ctx.onSearchChange($event); });
|
|
678
1190
|
i0.ɵɵelementEnd()();
|
|
679
|
-
i0.ɵɵelementStart(
|
|
680
|
-
i0.ɵɵ
|
|
1191
|
+
i0.ɵɵelementStart(54, "button", 32);
|
|
1192
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_54_listener() { return ctx.showMobileFilters = !ctx.showMobileFilters; });
|
|
1193
|
+
i0.ɵɵelement(55, "i", 33);
|
|
1194
|
+
i0.ɵɵtemplate(56, UserManagementComponent_Conditional_56_Template, 2, 1, "span", 34);
|
|
681
1195
|
i0.ɵɵelementEnd();
|
|
682
|
-
i0.ɵɵelementStart(
|
|
683
|
-
i0.ɵɵ
|
|
684
|
-
i0.ɵɵtext(54, " All ");
|
|
1196
|
+
i0.ɵɵelementStart(57, "div", 35)(58, "label", 36);
|
|
1197
|
+
i0.ɵɵtext(59, "Status");
|
|
685
1198
|
i0.ɵɵelementEnd();
|
|
686
|
-
i0.ɵɵelementStart(
|
|
687
|
-
i0.ɵɵlistener("click", function
|
|
688
|
-
i0.ɵɵtext(
|
|
1199
|
+
i0.ɵɵelementStart(60, "div", 37)(61, "button", 38);
|
|
1200
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_61_listener() { return ctx.onStatusFilterChange("all"); });
|
|
1201
|
+
i0.ɵɵtext(62, " All ");
|
|
689
1202
|
i0.ɵɵelementEnd();
|
|
690
|
-
i0.ɵɵelementStart(
|
|
691
|
-
i0.ɵɵlistener("click", function
|
|
692
|
-
i0.ɵɵtext(
|
|
1203
|
+
i0.ɵɵelementStart(63, "button", 38);
|
|
1204
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_63_listener() { return ctx.onStatusFilterChange("active"); });
|
|
1205
|
+
i0.ɵɵtext(64, " Active ");
|
|
1206
|
+
i0.ɵɵelementEnd();
|
|
1207
|
+
i0.ɵɵelementStart(65, "button", 38);
|
|
1208
|
+
i0.ɵɵlistener("click", function UserManagementComponent_Template_button_click_65_listener() { return ctx.onStatusFilterChange("inactive"); });
|
|
1209
|
+
i0.ɵɵtext(66, " Inactive ");
|
|
693
1210
|
i0.ɵɵelementEnd()()();
|
|
694
|
-
i0.ɵɵelementStart(
|
|
695
|
-
i0.ɵɵtext(
|
|
1211
|
+
i0.ɵɵelementStart(67, "div", 35)(68, "label", 39);
|
|
1212
|
+
i0.ɵɵtext(69, "Role");
|
|
696
1213
|
i0.ɵɵelementEnd();
|
|
697
|
-
i0.ɵɵelementStart(
|
|
698
|
-
i0.ɵɵlistener("change", function
|
|
699
|
-
i0.ɵɵelementStart(
|
|
700
|
-
i0.ɵɵtext(
|
|
1214
|
+
i0.ɵɵelementStart(70, "select", 40);
|
|
1215
|
+
i0.ɵɵlistener("change", function UserManagementComponent_Template_select_change_70_listener($event) { return ctx.onRoleFilterChange($event.target.value); });
|
|
1216
|
+
i0.ɵɵelementStart(71, "option", 41);
|
|
1217
|
+
i0.ɵɵtext(72, "All Roles");
|
|
701
1218
|
i0.ɵɵelementEnd();
|
|
702
|
-
i0.ɵɵrepeaterCreate(
|
|
1219
|
+
i0.ɵɵrepeaterCreate(73, UserManagementComponent_For_74_Template, 2, 2, "option", 42, _forTrack0);
|
|
1220
|
+
i0.ɵɵelementEnd()()();
|
|
1221
|
+
i0.ɵɵtemplate(75, UserManagementComponent_Conditional_75_Template, 21, 2, "div", 43);
|
|
703
1222
|
i0.ɵɵelementEnd()();
|
|
704
|
-
i0.ɵɵelementStart(
|
|
705
|
-
i0.ɵɵ
|
|
706
|
-
i0.ɵɵelement(69, "i", 35);
|
|
1223
|
+
i0.ɵɵelementStart(76, "div", 44);
|
|
1224
|
+
i0.ɵɵtemplate(77, UserManagementComponent_Conditional_77_Template, 2, 0, "div", 45)(78, UserManagementComponent_Conditional_78_Template, 8, 1, "div", 46)(79, UserManagementComponent_Conditional_79_Template, 11, 5, "div", 47);
|
|
707
1225
|
i0.ɵɵelementEnd();
|
|
708
|
-
i0.ɵɵelementStart(
|
|
709
|
-
i0.ɵɵlistener("
|
|
710
|
-
i0.ɵɵelement(71, "i", 37);
|
|
711
|
-
i0.ɵɵelementEnd()()()();
|
|
712
|
-
i0.ɵɵtemplate(72, UserManagementComponent_Conditional_72_Template, 7, 0, "div", 38)(73, UserManagementComponent_Conditional_73_Template, 8, 1, "div", 39)(74, UserManagementComponent_Conditional_74_Template, 3, 2, "div", 40);
|
|
713
|
-
i0.ɵɵelementStart(75, "mj-user-dialog", 41);
|
|
714
|
-
i0.ɵɵlistener("result", function UserManagementComponent_Template_mj_user_dialog_result_75_listener($event) { return ctx.onUserDialogResult($event); });
|
|
1226
|
+
i0.ɵɵelementStart(80, "mj-user-dialog", 48);
|
|
1227
|
+
i0.ɵɵlistener("result", function UserManagementComponent_Template_mj_user_dialog_result_80_listener($event) { return ctx.onUserDialogResult($event); });
|
|
715
1228
|
i0.ɵɵelementEnd();
|
|
716
|
-
i0.ɵɵtemplate(
|
|
1229
|
+
i0.ɵɵtemplate(81, UserManagementComponent_Conditional_81_Template, 22, 1, "div", 49)(82, UserManagementComponent_Conditional_82_Template, 20, 9, "div", 50)(83, UserManagementComponent_Conditional_83_Template, 25, 6, "div", 51);
|
|
717
1230
|
i0.ɵɵelementEnd();
|
|
718
1231
|
} if (rf & 2) {
|
|
719
|
-
i0.ɵɵadvance(
|
|
1232
|
+
i0.ɵɵadvance(3);
|
|
720
1233
|
i0.ɵɵproperty("disabled", ctx.isLoading);
|
|
721
1234
|
i0.ɵɵadvance();
|
|
722
1235
|
i0.ɵɵclassProp("fa-spin", ctx.isLoading);
|
|
723
|
-
i0.ɵɵadvance(
|
|
1236
|
+
i0.ɵɵadvance(11);
|
|
1237
|
+
i0.ɵɵconditional(ctx.hasSelection ? 15 : -1);
|
|
1238
|
+
i0.ɵɵadvance(7);
|
|
724
1239
|
i0.ɵɵtextInterpolate(ctx.stats.totalUsers);
|
|
725
1240
|
i0.ɵɵadvance(8);
|
|
726
1241
|
i0.ɵɵtextInterpolate(ctx.stats.activeUsers);
|
|
@@ -730,29 +1245,39 @@ let UserManagementComponent = class UserManagementComponent extends BaseDashboar
|
|
|
730
1245
|
i0.ɵɵtextInterpolate(ctx.stats.adminUsers);
|
|
731
1246
|
i0.ɵɵadvance(7);
|
|
732
1247
|
i0.ɵɵproperty("value", ctx.filters$.value.search);
|
|
1248
|
+
i0.ɵɵadvance();
|
|
1249
|
+
i0.ɵɵclassProp("active", ctx.showMobileFilters);
|
|
1250
|
+
i0.ɵɵattribute("aria-expanded", ctx.showMobileFilters);
|
|
1251
|
+
i0.ɵɵadvance(2);
|
|
1252
|
+
i0.ɵɵconditional(ctx.hasActiveFilters ? 56 : -1);
|
|
733
1253
|
i0.ɵɵadvance(5);
|
|
734
1254
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.status === "all");
|
|
1255
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.status === "all");
|
|
735
1256
|
i0.ɵɵadvance(2);
|
|
736
1257
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.status === "active");
|
|
1258
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.status === "active");
|
|
737
1259
|
i0.ɵɵadvance(2);
|
|
738
1260
|
i0.ɵɵclassProp("mj-btn-primary", ctx.filters$.value.status === "inactive");
|
|
1261
|
+
i0.ɵɵattribute("aria-pressed", ctx.filters$.value.status === "inactive");
|
|
739
1262
|
i0.ɵɵadvance(8);
|
|
740
1263
|
i0.ɵɵrepeater(ctx.roles);
|
|
741
|
-
i0.ɵɵadvance(3);
|
|
742
|
-
i0.ɵɵclassProp("mj-btn-primary", ctx.viewMode === "grid")("mj-btn-ghost", ctx.viewMode !== "grid");
|
|
743
1264
|
i0.ɵɵadvance(2);
|
|
744
|
-
i0.ɵɵ
|
|
1265
|
+
i0.ɵɵconditional(ctx.showMobileFilters ? 75 : -1);
|
|
745
1266
|
i0.ɵɵadvance(2);
|
|
746
|
-
i0.ɵɵconditional(ctx.isLoading ?
|
|
1267
|
+
i0.ɵɵconditional(ctx.isLoading ? 77 : -1);
|
|
747
1268
|
i0.ɵɵadvance();
|
|
748
|
-
i0.ɵɵconditional(ctx.error && !ctx.isLoading ?
|
|
1269
|
+
i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 78 : -1);
|
|
749
1270
|
i0.ɵɵadvance();
|
|
750
|
-
i0.ɵɵconditional(!ctx.isLoading && !ctx.error ?
|
|
1271
|
+
i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 79 : -1);
|
|
751
1272
|
i0.ɵɵadvance();
|
|
752
1273
|
i0.ɵɵproperty("data", ctx.userDialogData)("visible", ctx.showUserDialog);
|
|
753
1274
|
i0.ɵɵadvance();
|
|
754
|
-
i0.ɵɵconditional(ctx.showDeleteConfirm && ctx.selectedUser ?
|
|
755
|
-
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i2.UserDialogComponent, i3.DatePipe], styles: ["@keyframes _ngcontent-%COMP%_shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.user-management-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n overflow: hidden;\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.action-buttons[_ngcontent-%COMP%] {\n flex-shrink: 0;\n position: sticky;\n top: 0;\n z-index: 10;\n background: inherit;\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n padding: 1rem 2rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n}\n@media (max-width: 768px) {\n .action-buttons[_ngcontent-%COMP%] {\n justify-content: center;\n flex-wrap: wrap;\n padding: 1rem;\n }\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.btn-primary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\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.btn-danger[_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: #f44336;\n color: white;\n}\n.btn-danger[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n.btn-danger[_ngcontent-%COMP%]:hover {\n background-color: #d32f2f;\n}\n\n.stats-grid[_ngcontent-%COMP%] {\n flex-shrink: 0;\n position: sticky;\n top: 0;\n z-index: 10;\n background: inherit;\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 1rem 2rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\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 padding: 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-active[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n}\n.stat-icon-inactive[_ngcontent-%COMP%] {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n}\n.stat-icon-admin[_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 flex-shrink: 0;\n position: sticky;\n top: 0;\n z-index: 10;\n background: inherit;\n background: white;\n padding: 1.5rem 2rem;\n border-bottom: 1px solid #e0e0e0;\n}\n@media (max-width: 768px) {\n .filters-section[_ngcontent-%COMP%] {\n padding: 1rem;\n }\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@media (max-width: 768px) {\n .filters-row[_ngcontent-%COMP%] {\n gap: 1rem;\n }\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.625rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: white;\n font-size: 0.875rem;\n color: #374151;\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.view-toggle[_ngcontent-%COMP%] {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n}\n.view-toggle[_ngcontent-%COMP%] .view-btn[_ngcontent-%COMP%] {\n padding: 0.5rem 0.75rem;\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.view-toggle[_ngcontent-%COMP%] .view-btn[_ngcontent-%COMP%]:hover {\n color: #374151;\n}\n.view-toggle[_ngcontent-%COMP%] .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.content-area[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n padding: 2rem;\n background: white;\n}\n@media (max-width: 768px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n}\n\n.users-table[_ngcontent-%COMP%] {\n width: 100%;\n overflow-x: auto;\n}\n\n.modern-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n.modern-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] {\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n.modern-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n padding: 1rem;\n text-align: left;\n font-size: 0.875rem;\n font-weight: 600;\n color: #374151;\n white-space: nowrap;\n}\n.modern-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th.th-checkbox[_ngcontent-%COMP%] {\n width: 50px;\n}\n.modern-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th.th-actions[_ngcontent-%COMP%] {\n text-align: center;\n width: 150px;\n}\n.modern-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n border-bottom: 1px solid #f3f4f6;\n transition: background-color 0.2s;\n cursor: pointer;\n}\n.modern-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: #f9fafb;\n}\n.modern-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 1rem;\n font-size: 0.875rem;\n color: #374151;\n}\n.modern-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td.td-checkbox[_ngcontent-%COMP%] {\n width: 50px;\n}\n.modern-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td.td-actions[_ngcontent-%COMP%] {\n text-align: center;\n}\n\n.checkbox[_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n}\n\n.user-cell[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.user-avatar[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 0.875rem;\n}\n\n.user-avatar-large[_ngcontent-%COMP%] {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 1.5rem;\n margin: 0 auto 1rem;\n}\n\n.user-info[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #1f2937;\n}\n.user-info[_ngcontent-%COMP%] .user-fullname[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: #6b7280;\n}\n\n.user-type[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n color: #4b5563;\n}\n.user-type[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n border-radius: 20px;\n font-size: 0.75rem;\n font-weight: 500;\n}\n.status-badge.status-active[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n}\n.status-badge.status-inactive[_ngcontent-%COMP%] {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n}\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.625rem;\n}\n\n.last-login[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.875rem;\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: #f3f4f6;\n color: #2196f3;\n}\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n color: #f44336;\n}\n\n.users-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 1.5rem;\n}\n@media (max-width: 768px) {\n .users-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 1rem;\n padding: 1rem;\n }\n}\n\n.user-card[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n padding: 1.5rem;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n.user-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n border-color: #2196f3;\n}\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 1rem;\n}\n\n.card-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n.card-body[_ngcontent-%COMP%] {\n text-align: center;\n}\n.card-body[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n}\n.card-body[_ngcontent-%COMP%] .user-fullname[_ngcontent-%COMP%] {\n color: #6b7280;\n margin: 0 0 0.75rem 0;\n}\n.card-body[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n color: #4b5563;\n font-size: 0.875rem;\n margin-bottom: 1rem;\n}\n.card-body[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n.card-meta[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 1rem;\n padding: 1rem 0;\n border-top: 1px solid #f3f4f6;\n border-bottom: 1px solid #f3f4f6;\n margin-bottom: 1rem;\n}\n.card-meta[_ngcontent-%COMP%] .meta-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n color: #4b5563;\n font-size: 0.875rem;\n}\n\n.card-footer[_ngcontent-%COMP%] .last-login[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n color: #6b7280;\n font-size: 0.75rem;\n}\n.card-footer[_ngcontent-%COMP%] .last-login[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\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 #4caf50 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 #ff9800 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\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}\n.modal-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 1rem 0;\n color: #374151;\n}\n.modal-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n.modal-body[_ngcontent-%COMP%] .text-muted[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.875rem;\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@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.text-danger[_ngcontent-%COMP%] {\n color: #f44336;\n}"] });
|
|
1275
|
+
i0.ɵɵconditional(ctx.showDeleteConfirm && ctx.selectedUser ? 81 : -1);
|
|
1276
|
+
i0.ɵɵadvance();
|
|
1277
|
+
i0.ɵɵconditional(ctx.showBulkActionConfirm ? 82 : -1);
|
|
1278
|
+
i0.ɵɵadvance();
|
|
1279
|
+
i0.ɵɵconditional(ctx.showBulkRoleAssign ? 83 : -1);
|
|
1280
|
+
} }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.LoadingComponent, i3.UserDialogComponent, i4.DatePipe], styles: ["\n\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.user-management-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n position: relative;\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);\n border-bottom: 1px solid var(--md-outline-variant);\n box-shadow: var(--md-elevation-1);\n z-index: 10;\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-lowest);\n}\n\n@media (min-width: 768px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 1.5rem 2rem;\n }\n}\n\n@media (min-width: 1024px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 2rem;\n }\n}\n\n\n\n\n\n.action-buttons[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n padding: 0.75rem 1rem;\n background: var(--md-surface);\n}\n\n@media (min-width: 768px) {\n .action-buttons[_ngcontent-%COMP%] {\n padding: 1rem 1.5rem;\n }\n}\n\n@media (max-width: 639px) {\n .action-buttons[_ngcontent-%COMP%] {\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .mj-btn-icon-mobile[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%] {\n display: none;\n }\n\n .mj-btn-icon-mobile[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n padding: 0;\n border-radius: var(--md-corner-full);\n min-width: 48px;\n min-height: 48px;\n }\n\n .mj-btn-icon-mobile[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n }\n\n .mj-btn-primary.mj-btn-icon-mobile[_ngcontent-%COMP%] {\n box-shadow: var(--md-elevation-2);\n }\n\n .mj-btn-primary.mj-btn-icon-mobile[_ngcontent-%COMP%]:hover {\n box-shadow: var(--md-elevation-3);\n transform: scale(1.05);\n }\n\n .mj-btn-secondary.mj-btn-icon-mobile[_ngcontent-%COMP%] {\n background: var(--md-surface);\n border: 1px solid var(--md-outline);\n }\n\n .mj-btn-secondary.mj-btn-icon-mobile[_ngcontent-%COMP%]:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n }\n}\n\n\n\n\n\n.bulk-action-toolbar[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n background: var(--md-primary-container);\n border-bottom: 1px solid var(--md-outline-variant);\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n}\n\n@media (min-width: 768px) {\n .bulk-action-toolbar[_ngcontent-%COMP%] {\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n }\n}\n\n.bulk-selection-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-primary-container);\n}\n\n.bulk-selection-info[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n}\n\n.bulk-action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n\n@media (max-width: 639px) {\n .bulk-action-buttons[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%] {\n display: none;\n }\n\n .bulk-action-buttons[_ngcontent-%COMP%] .mj-btn-sm[_ngcontent-%COMP%] {\n padding: 0.5rem;\n min-width: 36px;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n transform: translateY(-10px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.mj-grid-4[_ngcontent-%COMP%] {\n display: none;\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 1rem 0.75rem 1rem;\n background: var(--md-surface);\n}\n\n@media (min-width: 768px) {\n .mj-grid-4[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n padding: 0 1.5rem 1rem 1.5rem;\n gap: 0.75rem;\n }\n}\n\n@media (min-width: 1024px) {\n .mj-grid-4[_ngcontent-%COMP%] {\n gap: 1rem;\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 box-shadow: none;\n display: flex;\n align-items: center;\n gap: 1rem;\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.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: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n}\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--md-primary-container);\n color: var(--md-primary);\n}\n\n.stat-icon-active[_ngcontent-%COMP%] {\n background: var(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n.stat-icon-inactive[_ngcontent-%COMP%] {\n background: var(--md-error-container);\n color: var(--md-error);\n}\n\n.stat-icon-admin[_ngcontent-%COMP%] {\n background: var(--md-secondary-container);\n color: #B5751A;\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: 2rem;\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 flex-shrink: 0;\n background: var(--md-surface-container);\n margin: 0 1rem 0.75rem 1rem;\n padding: 0.75rem;\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n}\n\n@media (min-width: 768px) {\n .filters-section[_ngcontent-%COMP%] {\n margin: 0 1.5rem 1rem 1.5rem;\n padding: 1rem 1.25rem;\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 (min-width: 768px) {\n .filters-row[_ngcontent-%COMP%] {\n gap: 1.5rem;\n }\n}\n\n@media (max-width: 767px) {\n .filters-section[_ngcontent-%COMP%] {\n padding: 0.75rem;\n }\n\n .filters-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: row;\n gap: 0.75rem;\n align-items: center;\n }\n\n .filters-row[_ngcontent-%COMP%] .mj-search[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.mj-search[_ngcontent-%COMP%] {\n position: relative;\n flex: 1;\n min-width: 200px;\n max-width: 100%;\n}\n\n@media (min-width: 640px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 280px;\n max-width: 500px;\n }\n}\n\n@media (min-width: 768px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 320px;\n max-width: 600px;\n }\n}\n\n@media (max-width: 767px) {\n .mj-search[_ngcontent-%COMP%] {\n width: 100%;\n max-width: none;\n min-width: 0;\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: 48px;\n}\n\n@media (min-width: 768px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem 1rem 3rem;\n min-height: 52px;\n font-size: 1.0625rem;\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.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\n\n\n\n.mobile-filter-toggle[_ngcontent-%COMP%] {\n display: none;\n align-items: center;\n justify-content: center;\n position: relative;\n width: 48px;\n height: 48px;\n min-width: 48px;\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n background: var(--md-surface-container-low);\n color: var(--md-on-surface-variant);\n font-size: 1.125rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--md-elevation-1);\n flex-shrink: 0;\n}\n\n.mobile-filter-toggle[_ngcontent-%COMP%]:hover {\n background: var(--md-surface-container);\n border-color: var(--md-primary);\n color: var(--md-primary);\n}\n\n.mobile-filter-toggle.active[_ngcontent-%COMP%] {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.filter-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--md-corner-full);\n background: var(--md-error);\n color: var(--md-on-error);\n font-size: 0.6875rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n}\n\n\n\n\n\n.mobile-filter-dropdown[_ngcontent-%COMP%] {\n display: none;\n margin-top: 0.75rem;\n padding-top: 0.75rem;\n border-top: 1px solid var(--md-outline-variant);\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n}\n\n\n\n@media (max-width: 767px) {\n .mobile-filter-toggle[_ngcontent-%COMP%] {\n display: flex !important;\n }\n\n .mobile-filter-dropdown[_ngcontent-%COMP%] {\n display: block;\n }\n\n .desktop-filter-group[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n.mobile-filter-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.mobile-filter-content[_ngcontent-%COMP%] .mj-filter-group[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.mobile-filter-content[_ngcontent-%COMP%] .mj-filter-select[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.clear-filters-btn[_ngcontent-%COMP%] {\n align-self: flex-start;\n margin-top: 0.25rem;\n}\n\n\n\n\n\n\n\n\n.desktop-filter-group[_ngcontent-%COMP%] {\n display: none !important;\n}\n\n\n\n@media screen and (min-width: 768px) {\n .desktop-filter-group[_ngcontent-%COMP%] {\n display: flex !important;\n flex-direction: column;\n gap: 0.375rem;\n }\n\n .mobile-filter-toggle[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-filter-dropdown[_ngcontent-%COMP%] {\n display: none !important;\n }\n}\n\n.mj-filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n}\n\n@media (max-width: 767px) {\n .mj-filter-group[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 100px;\n }\n}\n\n.mj-filter-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface);\n text-transform: uppercase;\n letter-spacing: 0.05em;\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}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n border-radius: var(--md-corner-full);\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn-primary[_ngcontent-%COMP%] {\n background-color: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-filter-select[_ngcontent-%COMP%] {\n padding: 0.625rem 1rem;\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n background: var(--md-surface-container-low);\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--md-on-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 120px;\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-filter-select[_ngcontent-%COMP%]:hover {\n background: var(--md-surface-container);\n border-color: var(--md-primary);\n}\n\n@media (max-width: 767px) {\n .mj-filter-select[_ngcontent-%COMP%] {\n width: 100%;\n padding: 0.5rem 0.75rem;\n font-size: 0.8125rem;\n }\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\n\n\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n overflow: visible;\n position: relative;\n background: var(--md-surface);\n border-radius: var(--md-corner-large);\n box-shadow: var(--md-elevation-1);\n padding: 1rem;\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\n\n\n\n.users-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n\n\n.list-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-small);\n border: 1px solid var(--md-outline-variant);\n margin-bottom: 0.5rem;\n}\n\n.select-all-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n cursor: pointer;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n.select-all-text[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.selection-count[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--md-primary);\n background: var(--md-primary-container);\n padding: 0.25rem 0.75rem;\n border-radius: var(--md-corner-full);\n}\n\n\n\n.user-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.user-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.user-card.expanded[_ngcontent-%COMP%] {\n box-shadow: var(--md-elevation-3);\n border-color: var(--md-primary);\n}\n\n.user-card.selected[_ngcontent-%COMP%] {\n background: var(--md-primary-container);\n border-color: var(--md-primary);\n}\n\n.user-card.selected[_ngcontent-%COMP%] .user-header[_ngcontent-%COMP%] {\n background: transparent;\n}\n\n.user-card.selected[_ngcontent-%COMP%]:hover .user-header[_ngcontent-%COMP%] {\n background: rgba(0, 118, 182, 0.08);\n}\n\n\n\n.user-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n cursor: pointer;\n background: var(--md-surface-container-lowest);\n transition: background-color 0.2s ease;\n}\n\n.user-header[_ngcontent-%COMP%]:hover {\n background: var(--md-surface-container-low);\n}\n\n@media (max-width: 639px) {\n .user-header[_ngcontent-%COMP%] {\n padding: 0.875rem 1rem;\n gap: 0.625rem;\n }\n}\n\n\n\n.user-selection[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.checkbox[_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--md-primary);\n}\n\n\n\n.user-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex: 1;\n min-width: 0;\n}\n\n.user-avatar[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-full);\n background: linear-gradient(135deg, var(--md-primary) 0%, #3395C8 100%);\n color: var(--md-on-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .user-avatar[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 0.8125rem;\n }\n\n .user-details[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .user-name[_ngcontent-%COMP%] {\n font-size: 0.9375rem;\n font-weight: 600;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .user-email[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}\n\n.user-details[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.user-name[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.user-email[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n margin: 0.125rem 0 0 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n.user-meta[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 767px) {\n .user-meta[_ngcontent-%COMP%] .status-badge[_ngcontent-%COMP%], \n .user-meta[_ngcontent-%COMP%] .user-actions[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .user-meta[_ngcontent-%COMP%] {\n gap: 0;\n }\n}\n\n\n\n.desktop-only[_ngcontent-%COMP%] {\n display: none;\n}\n\n@media (min-width: 768px) {\n .desktop-only[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\n }\n}\n\n.user-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.25rem;\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 ease;\n border-radius: var(--md-corner-full);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\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%] i[_ngcontent-%COMP%] {\n transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n.user-card.expanded[_ngcontent-%COMP%] .expand-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n\n\n.user-content[_ngcontent-%COMP%] {\n padding: 1.25rem 1.5rem;\n background: var(--md-surface);\n border-top: 1px solid var(--md-outline-variant);\n animation: _ngcontent-%COMP%_slideDown 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n\n\n.mobile-actions-bar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 1rem;\n margin-bottom: 1rem;\n border-bottom: 1px solid var(--md-outline-variant);\n}\n\n@media (min-width: 768px) {\n .mobile-actions-bar[_ngcontent-%COMP%] {\n display: none;\n }\n}\n\n.mobile-action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n}\n\n.mobile-action-buttons[_ngcontent-%COMP%] .btn-label[_ngcontent-%COMP%] {\n margin-left: 0.375rem;\n}\n\n\n\n.status-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}\n\n.status-badge.status-active[_ngcontent-%COMP%] {\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n.status-badge.status-inactive[_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.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.625rem;\n}\n\n\n\n.user-stats[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin-bottom: 1rem;\n}\n\n.user-stats[_ngcontent-%COMP%] .stat-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n}\n\n.user-stats[_ngcontent-%COMP%] .stat-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-primary);\n font-size: 0.875rem;\n}\n\n.user-stats[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n color: var(--md-on-surface-variant);\n}\n\n.user-stats[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n color: var(--md-on-surface);\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.user-stats[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n}\n\n\n\n.roles-section[_ngcontent-%COMP%] {\n padding-top: 1rem;\n border-top: 1px solid var(--md-outline-variant);\n}\n\n.section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0 0 0.75rem 0;\n}\n\n.section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-primary);\n font-size: 1.125rem;\n}\n\n.roles-grid[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.role-item[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\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}\n\n.role-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.625rem;\n}\n\n.no-roles[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n\n\n\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 1.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 0 0.5rem 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.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\n\n\n\n.error-container[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n}\n\n.error-container[_ngcontent-%COMP%] .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: 1rem;\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.error-container[_ngcontent-%COMP%] .retry-button[_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 background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n min-height: 44px;\n}\n\n.error-container[_ngcontent-%COMP%] .retry-button[_ngcontent-%COMP%]:hover {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.error-container[_ngcontent-%COMP%] .retry-button[_ngcontent-%COMP%]:active {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n\n\n\n\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: var(--md-surface);\n border-radius: var(--md-corner-extra-large);\n box-shadow: var(--md-elevation-5);\n max-width: 500px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUp 0.3s ease;\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 var(--md-outline-variant);\n}\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.375rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.modal-header[_ngcontent-%COMP%] .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 min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n}\n\n.modal-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--md-on-surface);\n margin: 0 0 1rem 0;\n line-height: 1.5;\n}\n\n.modal-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.modal-body[_ngcontent-%COMP%] .text-muted[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid var(--md-outline-variant);\n background: var(--md-surface-container-low);\n}\n\n@media (max-width: 639px) {\n .modal-dialog[_ngcontent-%COMP%] {\n width: 95%;\n max-height: 85vh;\n }\n\n .modal-header[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .modal-header[_ngcontent-%COMP%] .modal-title[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n\n .modal-body[_ngcontent-%COMP%] {\n padding: 1rem;\n }\n\n .modal-body[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 0.9375rem;\n }\n\n .modal-footer[_ngcontent-%COMP%] {\n padding: 1rem;\n flex-wrap: wrap;\n }\n\n .modal-footer[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 100px;\n }\n}\n\n\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 1rem;\n}\n\n.form-field[_ngcontent-%COMP%] .field-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-bottom: 0.5rem;\n}\n\n.form-field[_ngcontent-%COMP%] .field-select[_ngcontent-%COMP%] {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid var(--md-outline);\n border-radius: var(--md-corner-small);\n background: var(--md-surface);\n font-size: 1rem;\n color: var(--md-on-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-field[_ngcontent-%COMP%] .field-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\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-height: 44px;\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 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 background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.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}\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-danger[_ngcontent-%COMP%] {\n background: var(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.mj-btn-danger[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #EF9A9A;\n transform: scale(0.98);\n}\n\n\n\n.mj-btn-sm[_ngcontent-%COMP%] {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n\n\n.mj-btn-ghost.mj-btn-danger[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--md-error);\n box-shadow: none;\n}\n\n.mj-btn-ghost.mj-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--md-error-container);\n color: var(--md-error);\n}\n\n\n\n\n\n.text-danger[_ngcontent-%COMP%] {\n color: var(--md-error);\n}\n\n.text-success[_ngcontent-%COMP%] {\n color: var(--md-tertiary);\n}\n\n.text-warning[_ngcontent-%COMP%] {\n color: var(--md-secondary);\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\n\n\n\n.mj-search-input[_ngcontent-%COMP%]:focus-visible, \n.mj-filter-select[_ngcontent-%COMP%]:focus-visible, \nbutton[_ngcontent-%COMP%]:focus-visible, \n.checkbox[_ngcontent-%COMP%]:focus-visible, \n.user-header[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\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}\n\n\n\n\n\n@media (min-width: 1440px) {\n .user-management-container[_ngcontent-%COMP%] {\n max-width: 1920px;\n margin: 0 auto;\n }\n\n .action-buttons[_ngcontent-%COMP%] {\n padding: 1.25rem 2rem;\n }\n\n .bulk-action-toolbar[_ngcontent-%COMP%] {\n padding: 1.25rem 2rem;\n }\n\n .mj-grid-4[_ngcontent-%COMP%] {\n gap: 1.5rem;\n padding: 0 2rem 1rem 2rem;\n }\n\n .filters-section[_ngcontent-%COMP%] {\n margin: 0 2rem 1rem 2rem;\n padding: 1rem 1.5rem;\n }\n\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 2rem;\n }\n}\n\n\n\n\n\n@media (max-width: 639px) {\n .sticky-header[_ngcontent-%COMP%] {\n padding-bottom: 0;\n }\n\n .mj-grid-4[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 0.75rem 0.5rem 0.75rem;\n }\n\n .mj-card[_ngcontent-%COMP%] {\n padding: 0.75rem;\n gap: 0.75rem;\n }\n\n .stat-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 1.125rem;\n }\n\n .stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n }\n\n .stat-content[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 0.6875rem;\n }\n\n .filters-section[_ngcontent-%COMP%] {\n margin: 0 0.75rem 0.5rem 0.75rem;\n padding: 0.75rem;\n }\n\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 0.75rem;\n }\n\n .content-area[_ngcontent-%COMP%] {\n padding: 0.875rem;\n border-radius: var(--md-corner-medium);\n }\n\n .list-header[_ngcontent-%COMP%] {\n padding: 0.625rem 0.75rem;\n }\n\n .empty-state[_ngcontent-%COMP%] {\n padding: 2rem 1rem;\n }\n\n .empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 3rem;\n }\n\n .empty-state[_ngcontent-%COMP%] .empty-text[_ngcontent-%COMP%] {\n font-size: 1.0625rem;\n }\n\n .empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n }\n}"] });
|
|
756
1281
|
};
|
|
757
1282
|
UserManagementComponent = __decorate([
|
|
758
1283
|
RegisterClass(BaseDashboard, 'UserManagement')
|
|
@@ -760,7 +1285,7 @@ UserManagementComponent = __decorate([
|
|
|
760
1285
|
export { UserManagementComponent };
|
|
761
1286
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UserManagementComponent, [{
|
|
762
1287
|
type: Component,
|
|
763
|
-
args: [{ selector: 'mj-user-management', template: "<div class=\"user-management-container\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\">\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 <button class=\"mj-btn mj-btn-secondary\" (click)=\"exportUsers()\">\n <i class=\"fa-solid fa-download\"></i>\n Export\n </button>\n <button class=\"mj-btn mj-btn-primary\" (click)=\"createNewUser()\">\n <i class=\"fa-solid fa-plus\"></i>\n Add User\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-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.totalUsers }}</div>\n <div class=\"stat-label\">Total Users</div>\n </div>\n </div>\n \n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-active\">\n <i class=\"fa-solid fa-user-check\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.activeUsers }}</div>\n <div class=\"stat-label\">Active Users</div>\n </div>\n </div>\n \n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-inactive\">\n <i class=\"fa-solid fa-user-xmark\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.inactiveUsers }}</div>\n <div class=\"stat-label\">Inactive Users</div>\n </div>\n </div>\n \n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-admin\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ stats.adminUsers }}</div>\n <div class=\"stat-label\">Owners</div>\n </div>\n </div>\n </div>\n\n <!-- Filters Section -->\n <div class=\"filters-section\">\n <div class=\"filters-row\">\n <!-- Search -->\n <div class=\"search-container\">\n <i class=\"fa-solid fa-search search-icon\"></i>\n <input \n type=\"text\" \n class=\"search-input\" \n placeholder=\"Search users by name or email...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"filters$.value.search\"\n />\n </div>\n \n <!-- Status Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">Status</label>\n <div class=\"filter-buttons\">\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.status === 'all'\"\n (click)=\"onStatusFilterChange('all')\"\n >\n All\n </button>\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.status === 'active'\"\n (click)=\"onStatusFilterChange('active')\"\n >\n Active\n </button>\n <button \n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.status === 'inactive'\"\n (click)=\"onStatusFilterChange('inactive')\"\n >\n Inactive\n </button>\n </div>\n </div>\n \n <!-- Role Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">Role</label>\n <select class=\"filter-select\" (change)=\"onRoleFilterChange($any($event.target).value)\">\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 \n <!-- View Toggle -->\n <div class=\"view-toggle\">\n <button \n class=\"mj-btn mj-btn-icon-only\"\n [class.mj-btn-primary]=\"viewMode === 'grid'\"\n [class.mj-btn-ghost]=\"viewMode !== 'grid'\"\n (click)=\"viewMode = 'grid'\"\n title=\"Grid View\"\n >\n <i class=\"fa-solid fa-table\"></i>\n </button>\n <button \n class=\"mj-btn mj-btn-icon-only\"\n [class.mj-btn-primary]=\"viewMode === 'cards'\"\n [class.mj-btn-ghost]=\"viewMode !== 'cards'\"\n (click)=\"viewMode = 'cards'\"\n title=\"Card View\"\n >\n <i class=\"fa-solid fa-th-large\"></i>\n </button>\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 users...</div>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button class=\"retry-button\" (click)=\"loadInitialData()\">\n <i class=\"fa-solid fa-refresh\"></i>\n Try Again\n </button>\n </div>\n </div>\n }\n\n <!-- Content Area -->\n @if (!isLoading && !error) {\n <div class=\"content-area\">\n <!-- Grid View -->\n @if (viewMode === 'grid') {\n <div class=\"users-table\">\n <table class=\"modern-table\">\n <thead>\n <tr>\n <th class=\"th-checkbox\">\n <input type=\"checkbox\" class=\"checkbox\" />\n </th>\n <th>User</th>\n <th>Email</th>\n <th>Type</th>\n <th>Status</th>\n <th>Last Updated</th>\n <th class=\"th-actions\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (user of filteredUsers; track user.ID) {\n <tr class=\"table-row\" (click)=\"selectUser(user)\">\n <td class=\"td-checkbox\" (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" class=\"checkbox\" />\n </td>\n <td>\n <div class=\"user-cell\">\n <div class=\"user-avatar\">\n {{ getUserInitials(user) }}\n </div>\n <div class=\"user-info\">\n <div class=\"user-name\">{{ user.Name }}</div>\n <div class=\"user-fullname\">\n {{ user.FirstName }} {{ user.LastName }}\n </div>\n </div>\n </div>\n </td>\n <td>{{ user.Email }}</td>\n <td>\n <div class=\"user-type\">\n <i [class]=\"'fa-solid ' + getUserTypeIcon(user)\"></i>\n {{ user.Type }}\n </div>\n </td>\n <td>\n <span class=\"status-badge\" [class]=\"getStatusClass(user)\">\n <i [class]=\"'fa-solid ' + getStatusIcon(user)\"></i>\n {{ user.IsActive ? 'Active' : 'Inactive' }}\n </span>\n </td>\n <td>\n <span class=\"last-login\">\n {{ user.__mj_UpdatedAt ? (user.__mj_UpdatedAt | date:'short') : 'Never' }}\n </span>\n </td>\n <td class=\"td-actions\" (click)=\"$event.stopPropagation()\">\n <button class=\"mj-btn mj-btn-ghost mj-btn-sm\" (click)=\"editUser(user)\" title=\"Edit\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button \n class=\"mj-btn mj-btn-ghost mj-btn-sm\" \n (click)=\"toggleUserStatus(user)\"\n [title]=\"user.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"user.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\"></i>\n </button>\n <button class=\"mj-btn mj-btn-ghost mj-btn-sm text-danger\" (click)=\"confirmDeleteUser(user)\" title=\"Delete\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n \n @if (filteredUsers.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-users-slash empty-icon\"></i>\n <p class=\"empty-text\">No users found</p>\n <p class=\"empty-subtext\">Try adjusting your filters or add a new user</p>\n </div>\n }\n </div>\n }\n\n <!-- Card View -->\n @if (viewMode === 'cards') {\n <div class=\"users-grid\">\n @for (user of filteredUsers; track user.ID) {\n <div class=\"user-card\" (click)=\"selectUser(user)\">\n <div class=\"card-header\">\n <div class=\"user-avatar-large\">\n {{ getUserInitials(user) }}\n </div>\n <div class=\"card-actions\">\n <button class=\"mj-btn mj-btn-ghost mj-btn-sm\" (click)=\"editUser(user); $event.stopPropagation()\" title=\"Edit\">\n <i class=\"fa-solid fa-edit\"></i>\n </button>\n <button class=\"mj-btn mj-btn-ghost mj-btn-sm text-danger\" (click)=\"confirmDeleteUser(user); $event.stopPropagation()\" title=\"Delete\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n </div>\n </div>\n \n <div class=\"card-body\">\n <h3 class=\"user-name\">{{ user.Name }}</h3>\n <p class=\"user-fullname\">{{ user.FirstName }} {{ user.LastName }}</p>\n <p class=\"user-email\">\n <i class=\"fa-solid fa-envelope\"></i>\n {{ user.Email }}\n </p>\n \n <div class=\"card-meta\">\n <div class=\"meta-item\">\n <i [class]=\"'fa-solid ' + getUserTypeIcon(user)\"></i>\n {{ user.Type }}\n </div>\n <span class=\"status-badge\" [class]=\"getStatusClass(user)\">\n <i [class]=\"'fa-solid ' + getStatusIcon(user)\"></i>\n {{ user.IsActive ? 'Active' : 'Inactive' }}\n </span>\n </div>\n \n <div class=\"card-footer\">\n <div class=\"last-login\">\n <i class=\"fa-solid fa-clock\"></i>\n Last updated: {{ user.__mj_UpdatedAt ? (user.__mj_UpdatedAt | date:'short') : 'Never' }}\n </div>\n </div>\n </div>\n </div>\n }\n \n @if (filteredUsers.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-users-slash empty-icon\"></i>\n <p class=\"empty-text\">No users found</p>\n <p class=\"empty-subtext\">Try adjusting your filters or add a new user</p>\n </div>\n }\n </div>\n }\n </div>\n }\n\n <!-- User Create/Edit Dialog -->\n <mj-user-dialog \n [data]=\"userDialogData\"\n [visible]=\"showUserDialog\"\n (result)=\"onUserDialogResult($event)\">\n </mj-user-dialog>\n\n <!-- Delete Confirmation Dialog -->\n @if (showDeleteConfirm && selectedUser) {\n <div class=\"modal-backdrop\" (click)=\"showDeleteConfirm = false\">\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">\n <i class=\"fa-solid fa-exclamation-triangle text-danger\"></i>\n Confirm Delete\n </h3>\n <button class=\"modal-close\" (click)=\"showDeleteConfirm = false\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <p>Are you sure you want to delete user <strong>{{ selectedUser.Name }}</strong>?</p>\n <p class=\"text-muted\">This action cannot be undone.</p>\n </div>\n <div class=\"modal-footer\">\n <button class=\"mj-btn mj-btn-secondary\" (click)=\"showDeleteConfirm = false\">Cancel</button>\n <button class=\"mj-btn mj-btn-primary text-danger\" (click)=\"deleteUser()\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete User\n </button>\n </div>\n </div>\n </div>\n }\n</div>", styles: ["@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.user-management-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n overflow: hidden;\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.action-buttons {\n flex-shrink: 0;\n position: sticky;\n top: 0;\n z-index: 10;\n background: inherit;\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n padding: 1rem 2rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n}\n@media (max-width: 768px) {\n .action-buttons {\n justify-content: center;\n flex-wrap: wrap;\n padding: 1rem;\n }\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.btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\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.btn-danger {\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: #f44336;\n color: white;\n}\n.btn-danger:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-danger i {\n font-size: 0.875rem;\n}\n.btn-danger:hover {\n background-color: #d32f2f;\n}\n\n.stats-grid {\n flex-shrink: 0;\n position: sticky;\n top: 0;\n z-index: 10;\n background: inherit;\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n padding: 1rem 2rem;\n background: white;\n border-bottom: 1px solid #e0e0e0;\n width: 100%;\n}\n@media (max-width: 768px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n padding: 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-active {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n}\n.stat-icon-inactive {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n}\n.stat-icon-admin {\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 flex-shrink: 0;\n position: sticky;\n top: 0;\n z-index: 10;\n background: inherit;\n background: white;\n padding: 1.5rem 2rem;\n border-bottom: 1px solid #e0e0e0;\n}\n@media (max-width: 768px) {\n .filters-section {\n padding: 1rem;\n }\n}\n\n.filters-row {\n display: flex;\n gap: 1.5rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n@media (max-width: 768px) {\n .filters-row {\n gap: 1rem;\n }\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.625rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: white;\n font-size: 0.875rem;\n color: #374151;\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.view-toggle {\n display: flex;\n background: #f3f4f6;\n border-radius: 8px;\n padding: 4px;\n}\n.view-toggle .view-btn {\n padding: 0.5rem 0.75rem;\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.view-toggle .view-btn:hover {\n color: #374151;\n}\n.view-toggle .view-btn.active {\n background: white;\n color: #2196f3;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 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 padding: 2rem;\n background: white;\n}\n@media (max-width: 768px) {\n .content-area {\n padding: 1rem;\n }\n}\n\n.users-table {\n width: 100%;\n overflow-x: auto;\n}\n\n.modern-table {\n width: 100%;\n border-collapse: collapse;\n}\n.modern-table thead {\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n.modern-table thead th {\n padding: 1rem;\n text-align: left;\n font-size: 0.875rem;\n font-weight: 600;\n color: #374151;\n white-space: nowrap;\n}\n.modern-table thead th.th-checkbox {\n width: 50px;\n}\n.modern-table thead th.th-actions {\n text-align: center;\n width: 150px;\n}\n.modern-table tbody tr {\n border-bottom: 1px solid #f3f4f6;\n transition: background-color 0.2s;\n cursor: pointer;\n}\n.modern-table tbody tr:hover {\n background-color: #f9fafb;\n}\n.modern-table tbody td {\n padding: 1rem;\n font-size: 0.875rem;\n color: #374151;\n}\n.modern-table tbody td.td-checkbox {\n width: 50px;\n}\n.modern-table tbody td.td-actions {\n text-align: center;\n}\n\n.checkbox {\n width: 18px;\n height: 18px;\n cursor: pointer;\n}\n\n.user-cell {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.user-avatar {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 0.875rem;\n}\n\n.user-avatar-large {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n font-size: 1.5rem;\n margin: 0 auto 1rem;\n}\n\n.user-info .user-name {\n font-weight: 600;\n color: #1f2937;\n}\n.user-info .user-fullname {\n font-size: 0.75rem;\n color: #6b7280;\n}\n\n.user-type {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n color: #4b5563;\n}\n.user-type i {\n font-size: 0.875rem;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n border-radius: 20px;\n font-size: 0.75rem;\n font-weight: 500;\n}\n.status-badge.status-active {\n background: rgba(76, 175, 80, 0.1);\n color: #388e3c;\n}\n.status-badge.status-inactive {\n background: rgba(244, 67, 54, 0.1);\n color: #d32f2f;\n}\n.status-badge i {\n font-size: 0.625rem;\n}\n\n.last-login {\n color: #6b7280;\n font-size: 0.875rem;\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: #f3f4f6;\n color: #2196f3;\n}\n.action-btn-danger:hover {\n color: #f44336;\n}\n\n.users-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n padding: 1.5rem;\n}\n@media (max-width: 768px) {\n .users-grid {\n grid-template-columns: 1fr;\n gap: 1rem;\n padding: 1rem;\n }\n}\n\n.user-card {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 12px;\n padding: 1.5rem;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n.user-card:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);\n transform: translateY(-2px);\n border-color: #2196f3;\n}\n\n.card-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 1rem;\n}\n\n.card-actions {\n display: flex;\n gap: 0.5rem;\n}\n\n.card-body {\n text-align: center;\n}\n.card-body .user-name {\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0 0 0.25rem 0;\n}\n.card-body .user-fullname {\n color: #6b7280;\n margin: 0 0 0.75rem 0;\n}\n.card-body .user-email {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n color: #4b5563;\n font-size: 0.875rem;\n margin-bottom: 1rem;\n}\n.card-body .user-email i {\n color: #6b7280;\n}\n\n.card-meta {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 1rem;\n padding: 1rem 0;\n border-top: 1px solid #f3f4f6;\n border-bottom: 1px solid #f3f4f6;\n margin-bottom: 1rem;\n}\n.card-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n color: #4b5563;\n font-size: 0.875rem;\n}\n\n.card-footer .last-login {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n color: #6b7280;\n font-size: 0.75rem;\n}\n.card-footer .last-login i {\n font-size: 0.875rem;\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 #4caf50 transparent transparent;\n animation-delay: -0.3s;\n}\n.loading-spinner .spinner-ring:nth-child(3) {\n border-color: transparent transparent #ff9800 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\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}\n.modal-body p {\n margin: 0 0 1rem 0;\n color: #374151;\n}\n.modal-body p:last-child {\n margin-bottom: 0;\n}\n.modal-body .text-muted {\n color: #6b7280;\n font-size: 0.875rem;\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@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.text-danger {\n color: #f44336;\n}\n"] }]
|
|
1288
|
+
args: [{ selector: 'mj-user-management', template: "<div class=\"user-management-container\">\n <!-- Sticky Header Section -->\n <div class=\"sticky-header\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\" role=\"toolbar\" aria-label=\"User management actions\">\n <button\n class=\"mj-btn mj-btn-secondary mj-btn-icon-mobile\"\n (click)=\"refreshData()\"\n [disabled]=\"isLoading\"\n aria-label=\"Refresh user list\"\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 <button\n class=\"mj-btn mj-btn-secondary mj-btn-icon-mobile\"\n (click)=\"exportUsers()\"\n aria-label=\"Export users to file\"\n >\n <i class=\"fa-solid fa-download\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Export</span>\n </button>\n <button\n class=\"mj-btn mj-btn-primary mj-btn-icon-mobile\"\n (click)=\"createNewUser()\"\n aria-label=\"Add new user\"\n >\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Add User</span>\n </button>\n </div>\n\n <!-- Bulk Action Toolbar -->\n @if (hasSelection) {\n <div class=\"bulk-action-toolbar\" role=\"toolbar\" aria-label=\"Bulk actions\">\n <div class=\"bulk-selection-info\">\n <i class=\"fa-solid fa-check-square\" aria-hidden=\"true\"></i>\n <span>{{ selectedCount }} user{{ selectedCount > 1 ? 's' : '' }} selected</span>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"clearSelection()\"\n aria-label=\"Clear selection\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n Clear\n </button>\n </div>\n <div class=\"bulk-action-buttons\">\n <button\n class=\"mj-btn mj-btn-secondary mj-btn-sm\"\n (click)=\"confirmBulkAction('enable')\"\n aria-label=\"Enable selected users\"\n >\n <i class=\"fa-solid fa-toggle-on\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Enable</span>\n </button>\n <button\n class=\"mj-btn mj-btn-secondary mj-btn-sm\"\n (click)=\"confirmBulkAction('disable')\"\n aria-label=\"Disable selected users\"\n >\n <i class=\"fa-solid fa-toggle-off\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Disable</span>\n </button>\n <button\n class=\"mj-btn mj-btn-secondary mj-btn-sm\"\n (click)=\"openBulkRoleAssign()\"\n aria-label=\"Assign role to selected users\"\n >\n <i class=\"fa-solid fa-user-tag\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Assign Role</span>\n </button>\n <button\n class=\"mj-btn mj-btn-danger mj-btn-sm\"\n (click)=\"confirmBulkAction('delete')\"\n aria-label=\"Delete selected users\"\n >\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n <span class=\"btn-text\">Delete</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Stats Cards -->\n <div class=\"mj-grid-4\" role=\"region\" aria-label=\"User statistics\">\n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-total\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-users\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Total users count\">{{ stats.totalUsers }}</div>\n <div class=\"stat-label\">Total Users</div>\n </div>\n </div>\n\n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-active\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-user-check\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Active users count\">{{ stats.activeUsers }}</div>\n <div class=\"stat-label\">Active Users</div>\n </div>\n </div>\n\n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-inactive\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-user-xmark\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Inactive users count\">{{ stats.inactiveUsers }}</div>\n <div class=\"stat-label\">Inactive Users</div>\n </div>\n </div>\n\n <div class=\"mj-card\">\n <div class=\"stat-icon stat-icon-admin\" aria-hidden=\"true\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" aria-label=\"Owner users count\">{{ stats.adminUsers }}</div>\n <div class=\"stat-label\">Owners</div>\n </div>\n </div>\n </div>\n\n <!-- Filters Section -->\n <div class=\"filters-section\" role=\"search\" aria-label=\"Filter users\">\n <div class=\"filters-row\">\n <!-- 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 users by name or email...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"filters$.value.search\"\n aria-label=\"Search users by name or email\"\n />\n </div>\n\n <!-- Mobile: Filter Toggle Button -->\n <button\n class=\"mobile-filter-toggle\"\n (click)=\"showMobileFilters = !showMobileFilters\"\n [class.active]=\"showMobileFilters\"\n [attr.aria-expanded]=\"showMobileFilters\"\n aria-label=\"Toggle filters\"\n >\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n @if (hasActiveFilters) {\n <span class=\"filter-badge\">{{ activeFilterCount }}</span>\n }\n </button>\n\n <!-- Desktop: Status Filter - Button group -->\n <div class=\"mj-filter-group desktop-filter-group\">\n <label class=\"mj-filter-label\" id=\"status-filter-label\">Status</label>\n <div class=\"mj-filter-buttons\" role=\"group\" aria-labelledby=\"status-filter-label\">\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.status === 'all'\"\n (click)=\"onStatusFilterChange('all')\"\n [attr.aria-pressed]=\"filters$.value.status === 'all'\"\n >\n All\n </button>\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.status === 'active'\"\n (click)=\"onStatusFilterChange('active')\"\n [attr.aria-pressed]=\"filters$.value.status === 'active'\"\n >\n Active\n </button>\n <button\n class=\"mj-btn mj-btn-ghost\"\n [class.mj-btn-primary]=\"filters$.value.status === 'inactive'\"\n (click)=\"onStatusFilterChange('inactive')\"\n [attr.aria-pressed]=\"filters$.value.status === 'inactive'\"\n >\n Inactive\n </button>\n </div>\n </div>\n\n <!-- Desktop: Role Filter -->\n <div class=\"mj-filter-group desktop-filter-group\">\n <label class=\"mj-filter-label\" for=\"role-filter\">Role</label>\n <select\n id=\"role-filter\"\n class=\"mj-filter-select\"\n (change)=\"onRoleFilterChange($any($event.target).value)\"\n aria-label=\"Filter 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\n <!-- Mobile: Filter Dropdown Panel -->\n @if (showMobileFilters) {\n <div class=\"mobile-filter-dropdown\">\n <div class=\"mobile-filter-content\">\n <!-- Status Filter -->\n <div class=\"mj-filter-group\">\n <label class=\"mj-filter-label\" id=\"status-filter-label-mobile\">Status</label>\n <select\n class=\"mj-filter-select\"\n [value]=\"filters$.value.status\"\n (change)=\"onStatusFilterChange($any($event.target).value)\"\n aria-labelledby=\"status-filter-label-mobile\"\n >\n <option value=\"all\">All Status</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n </select>\n </div>\n\n <!-- Role Filter -->\n <div class=\"mj-filter-group\">\n <label class=\"mj-filter-label\" for=\"role-filter-mobile\">Role</label>\n <select\n id=\"role-filter-mobile\"\n class=\"mj-filter-select\"\n (change)=\"onRoleFilterChange($any($event.target).value)\"\n aria-label=\"Filter 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\n <!-- Clear Filters Button -->\n @if (hasActiveFilters) {\n <button class=\"mj-btn mj-btn-ghost mj-btn-sm clear-filters-btn\" (click)=\"clearFilters()\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n Clear Filters\n </button>\n }\n </div>\n </div>\n }\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 users...\" 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 class=\"retry-button\" (click)=\"loadInitialData()\" aria-label=\"Retry loading users\">\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 <!-- Users List -->\n <div class=\"users-list\" role=\"list\" aria-label=\"Users list\">\n <!-- List Header with Select All -->\n <div class=\"list-header\">\n <label class=\"select-all-label\">\n <input\n type=\"checkbox\"\n class=\"checkbox\"\n [checked]=\"isAllSelected\"\n [indeterminate]=\"isIndeterminate\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all users\"\n />\n <span class=\"select-all-text\">Select All ({{ filteredUsers.length }})</span>\n </label>\n @if (hasSelection) {\n <span class=\"selection-count\">{{ selectedCount }} selected</span>\n }\n </div>\n\n @for (user of filteredUsers; track user.ID) {\n <div\n class=\"user-card\"\n [class.expanded]=\"isUserExpanded(user.ID)\"\n [class.selected]=\"isUserSelected(user.ID)\"\n role=\"listitem\"\n >\n <!-- User Card Header - Always Visible -->\n <div\n class=\"user-header\"\n (click)=\"toggleUserExpansion(user.ID)\"\n role=\"button\"\n [attr.aria-expanded]=\"isUserExpanded(user.ID)\"\n tabindex=\"0\"\n (keydown.enter)=\"toggleUserExpansion(user.ID)\"\n >\n <!-- Selection Checkbox -->\n <div class=\"user-selection\" (click)=\"$event.stopPropagation()\">\n <input\n type=\"checkbox\"\n class=\"checkbox\"\n [checked]=\"isUserSelected(user.ID)\"\n (change)=\"toggleUserSelection(user.ID, $event)\"\n [attr.aria-label]=\"'Select ' + user.Name\"\n />\n </div>\n\n <!-- User Info -->\n <div class=\"user-info\">\n <div class=\"user-avatar\" aria-hidden=\"true\">\n {{ getUserInitials(user) }}\n </div>\n <div class=\"user-details\">\n <h3 class=\"user-name\">{{ user.Name }}</h3>\n <p class=\"user-email\">{{ user.Email }}</p>\n </div>\n </div>\n\n <!-- User Meta -->\n <div class=\"user-meta\">\n <span class=\"status-badge\" [class]=\"getStatusClass(user)\">\n <i [class]=\"'fa-solid ' + getStatusIcon(user)\" aria-hidden=\"true\"></i>\n {{ user.IsActive ? 'Active' : 'Inactive' }}\n </span>\n <div class=\"user-actions desktop-only\" (click)=\"$event.stopPropagation()\">\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"editUser(user)\"\n [attr.aria-label]=\"'Edit ' + user.Name\"\n title=\"Edit\"\n >\n <i class=\"fa-solid fa-edit\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"toggleUserStatus(user)\"\n [attr.aria-label]=\"(user.IsActive ? 'Deactivate ' : 'Activate ') + user.Name\"\n [title]=\"user.IsActive ? 'Deactivate' : 'Activate'\"\n >\n <i [class]=\"user.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\" aria-hidden=\"true\"></i>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm mj-btn-danger\"\n (click)=\"confirmDeleteUser(user)\"\n [attr.aria-label]=\"'Delete ' + user.Name\"\n title=\"Delete\"\n >\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <button class=\"expand-btn\" aria-label=\"Toggle user details\">\n <i class=\"fa-solid fa-chevron-down\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- User Card Content - Expanded -->\n @if (isUserExpanded(user.ID)) {\n <div class=\"user-content\">\n <!-- Mobile Actions Bar -->\n <div class=\"mobile-actions-bar\" (click)=\"$event.stopPropagation()\">\n <span class=\"status-badge\" [class]=\"getStatusClass(user)\">\n <i [class]=\"'fa-solid ' + getStatusIcon(user)\" aria-hidden=\"true\"></i>\n {{ user.IsActive ? 'Active' : 'Inactive' }}\n </span>\n <div class=\"mobile-action-buttons\">\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"editUser(user)\"\n [attr.aria-label]=\"'Edit ' + user.Name\"\n >\n <i class=\"fa-solid fa-edit\" aria-hidden=\"true\"></i>\n <span class=\"btn-label\">Edit</span>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm\"\n (click)=\"toggleUserStatus(user)\"\n [attr.aria-label]=\"(user.IsActive ? 'Deactivate ' : 'Activate ') + user.Name\"\n >\n <i [class]=\"user.IsActive ? 'fa-solid fa-toggle-on' : 'fa-solid fa-toggle-off'\" aria-hidden=\"true\"></i>\n <span class=\"btn-label\">{{ user.IsActive ? 'Disable' : 'Enable' }}</span>\n </button>\n <button\n class=\"mj-btn mj-btn-ghost mj-btn-sm mj-btn-danger\"\n (click)=\"confirmDeleteUser(user)\"\n [attr.aria-label]=\"'Delete ' + user.Name\"\n >\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n <span class=\"btn-label\">Delete</span>\n </button>\n </div>\n </div>\n\n <!-- User Stats -->\n <div class=\"user-stats\">\n <div class=\"stat-item\">\n <i class=\"fa-solid fa-user-tag\" aria-hidden=\"true\"></i>\n <span class=\"stat-label\">Type:</span>\n <span class=\"stat-value\">\n <i [class]=\"'fa-solid ' + getUserTypeIcon(user)\" aria-hidden=\"true\"></i>\n {{ user.Type }}\n </span>\n </div>\n <div class=\"stat-item\">\n <i class=\"fa-solid fa-id-card\" aria-hidden=\"true\"></i>\n <span class=\"stat-label\">Full Name:</span>\n <span class=\"stat-value\">{{ user.FirstName }} {{ user.LastName }}</span>\n </div>\n <div class=\"stat-item\">\n <i class=\"fa-solid fa-calendar\" aria-hidden=\"true\"></i>\n <span class=\"stat-label\">Created:</span>\n <span class=\"stat-value\">{{ user.__mj_CreatedAt | date:'short' }}</span>\n </div>\n <div class=\"stat-item\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n <span class=\"stat-label\">Updated:</span>\n <span class=\"stat-value\">{{ user.__mj_UpdatedAt | date:'short' }}</span>\n </div>\n </div>\n\n <!-- User Roles Section -->\n <div class=\"roles-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-user-shield\" aria-hidden=\"true\"></i>\n Assigned Roles\n </h4>\n @if (getUserRoles(user.ID).length > 0) {\n <div class=\"roles-grid\">\n @for (role of getUserRoles(user.ID); track role.ID) {\n <div class=\"role-item\">\n <i class=\"fa-solid fa-shield\" aria-hidden=\"true\"></i>\n {{ role.Name }}\n </div>\n }\n </div>\n } @else {\n <p class=\"no-roles\">No roles assigned to this user</p>\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (filteredUsers.length === 0) {\n <div class=\"empty-state\" role=\"status\">\n <i class=\"fa-solid fa-users-slash empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">No users found</p>\n <p class=\"empty-subtext\">Try adjusting your filters or add a new user</p>\n </div>\n }\n </div>\n </div>\n }\n </div><!-- End Scrollable Content -->\n\n <!-- User Create/Edit Dialog -->\n <mj-user-dialog\n [data]=\"userDialogData\"\n [visible]=\"showUserDialog\"\n (result)=\"onUserDialogResult($event)\">\n </mj-user-dialog>\n\n <!-- Delete Confirmation Dialog -->\n @if (showDeleteConfirm && selectedUser) {\n <div\n class=\"modal-backdrop\"\n (click)=\"showDeleteConfirm = false\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"delete-dialog-title\"\n aria-describedby=\"delete-dialog-desc\"\n >\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"delete-dialog-title\">\n <i class=\"fa-solid fa-exclamation-triangle text-danger\" aria-hidden=\"true\"></i>\n Confirm Delete\n </h3>\n <button\n class=\"modal-close\"\n (click)=\"showDeleteConfirm = false\"\n aria-label=\"Close dialog\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"modal-body\" id=\"delete-dialog-desc\">\n <p>Are you sure you want to delete user <strong>{{ selectedUser.Name }}</strong>?</p>\n <p class=\"text-muted\">This action cannot be undone.</p>\n </div>\n <div class=\"modal-footer\">\n <button class=\"mj-btn mj-btn-danger\" (click)=\"deleteUser()\">\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n Delete User\n </button>\n <button class=\"mj-btn mj-btn-secondary\" (click)=\"showDeleteConfirm = false\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- Bulk Action Confirmation Dialog -->\n @if (showBulkActionConfirm) {\n <div\n class=\"modal-backdrop\"\n (click)=\"cancelBulkAction()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"bulk-action-dialog-title\"\n aria-describedby=\"bulk-action-dialog-desc\"\n >\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"bulk-action-dialog-title\">\n @if (bulkActionType === 'delete') {\n <i class=\"fa-solid fa-exclamation-triangle text-danger\" aria-hidden=\"true\"></i>\n } @else if (bulkActionType === 'enable') {\n <i class=\"fa-solid fa-toggle-on text-success\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-toggle-off text-warning\" aria-hidden=\"true\"></i>\n }\n {{ getBulkActionTitle() }}\n </h3>\n <button\n class=\"modal-close\"\n (click)=\"cancelBulkAction()\"\n aria-label=\"Close dialog\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"modal-body\" id=\"bulk-action-dialog-desc\">\n <p>{{ getBulkActionMessage() }}</p>\n @if (bulkActionType === 'delete') {\n <p class=\"text-muted\">This action cannot be undone.</p>\n }\n </div>\n <div class=\"modal-footer\">\n <button\n [class]=\"bulkActionType === 'delete' ? 'mj-btn mj-btn-danger' : 'mj-btn mj-btn-primary'\"\n (click)=\"executeBulkAction()\"\n [disabled]=\"isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Processing...\n } @else {\n @if (bulkActionType === 'delete') {\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n } @else if (bulkActionType === 'enable') {\n <i class=\"fa-solid fa-toggle-on\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-toggle-off\" aria-hidden=\"true\"></i>\n }\n {{ getBulkActionButtonText() }}\n }\n </button>\n <button class=\"mj-btn mj-btn-secondary\" (click)=\"cancelBulkAction()\" [disabled]=\"isLoading\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- Bulk Role Assignment Dialog -->\n @if (showBulkRoleAssign) {\n <div\n class=\"modal-backdrop\"\n (click)=\"cancelBulkRoleAssign()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"bulk-role-dialog-title\"\n aria-describedby=\"bulk-role-dialog-desc\"\n >\n <div class=\"modal-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"bulk-role-dialog-title\">\n <i class=\"fa-solid fa-user-tag\" aria-hidden=\"true\"></i>\n Assign Role to {{ selectedCount }} User{{ selectedCount > 1 ? 's' : '' }}\n </h3>\n <button\n class=\"modal-close\"\n (click)=\"cancelBulkRoleAssign()\"\n aria-label=\"Close dialog\"\n >\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"modal-body\" id=\"bulk-role-dialog-desc\">\n <p>Select a role to assign to the selected users:</p>\n <div class=\"form-field\">\n <label class=\"field-label\" for=\"bulk-role-select\">Role</label>\n <select\n id=\"bulk-role-select\"\n class=\"field-select\"\n [(ngModel)]=\"bulkRoleId\"\n aria-label=\"Select role to assign\"\n >\n <option value=\"\">Select a role...</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 class=\"modal-footer\">\n <button\n class=\"mj-btn mj-btn-primary\"\n (click)=\"executeBulkRoleAssign()\"\n [disabled]=\"!bulkRoleId || isLoading\"\n >\n @if (isLoading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Assigning...\n } @else {\n <i class=\"fa-solid fa-user-tag\" aria-hidden=\"true\"></i>\n Assign Role\n }\n </button>\n <button class=\"mj-btn mj-btn-secondary\" (click)=\"cancelBulkRoleAssign()\" [disabled]=\"isLoading\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* =============================================================================\n User Management Component - MD3 Design System\n Unified Expandable Card List Pattern\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n MD3 Design Tokens (Local)\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 Layout */\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.user-management-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n position: relative;\n width: 100%;\n background: var(--md-surface);\n}\n\n/* -----------------------------------------------------------------------------\n Sticky Header - Always visible controls\n ----------------------------------------------------------------------------- */\n.sticky-header {\n flex-shrink: 0;\n background: var(--md-surface);\n border-bottom: 1px solid var(--md-outline-variant);\n box-shadow: var(--md-elevation-1);\n z-index: 10;\n}\n\n/* -----------------------------------------------------------------------------\n Scrollable Content - Users list area\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-lowest);\n}\n\n@media (min-width: 768px) {\n .scrollable-content {\n padding: 1.5rem 2rem;\n }\n}\n\n@media (min-width: 1024px) {\n .scrollable-content {\n padding: 2rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons (In Sticky Header)\n ----------------------------------------------------------------------------- */\n.action-buttons {\n flex-shrink: 0;\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n padding: 0.75rem 1rem;\n background: var(--md-surface);\n}\n\n@media (min-width: 768px) {\n .action-buttons {\n padding: 1rem 1.5rem;\n }\n}\n\n@media (max-width: 639px) {\n .action-buttons {\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .mj-btn-icon-mobile .btn-text {\n display: none;\n }\n\n .mj-btn-icon-mobile {\n width: 48px;\n height: 48px;\n padding: 0;\n border-radius: var(--md-corner-full);\n min-width: 48px;\n min-height: 48px;\n }\n\n .mj-btn-icon-mobile i {\n font-size: 1.25rem;\n }\n\n .mj-btn-primary.mj-btn-icon-mobile {\n box-shadow: var(--md-elevation-2);\n }\n\n .mj-btn-primary.mj-btn-icon-mobile:hover {\n box-shadow: var(--md-elevation-3);\n transform: scale(1.05);\n }\n\n .mj-btn-secondary.mj-btn-icon-mobile {\n background: var(--md-surface);\n border: 1px solid var(--md-outline);\n }\n\n .mj-btn-secondary.mj-btn-icon-mobile:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n }\n}\n\n/* -----------------------------------------------------------------------------\n Bulk Action Toolbar\n ----------------------------------------------------------------------------- */\n.bulk-action-toolbar {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n background: var(--md-primary-container);\n border-bottom: 1px solid var(--md-outline-variant);\n animation: slideDown 0.2s ease;\n}\n\n@media (min-width: 768px) {\n .bulk-action-toolbar {\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding: 1rem 1.5rem;\n }\n}\n\n.bulk-selection-info {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-primary-container);\n}\n\n.bulk-selection-info i {\n font-size: 1.25rem;\n}\n\n.bulk-action-buttons {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n\n@media (max-width: 639px) {\n .bulk-action-buttons .btn-text {\n display: none;\n }\n\n .bulk-action-buttons .mj-btn-sm {\n padding: 0.5rem;\n min-width: 36px;\n }\n}\n\n@keyframes slideDown {\n from {\n transform: translateY(-10px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Statistics Cards - Static Display (Non-interactive)\n ----------------------------------------------------------------------------- */\n.mj-grid-4 {\n display: none;\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 1rem 0.75rem 1rem;\n background: var(--md-surface);\n}\n\n@media (min-width: 768px) {\n .mj-grid-4 {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n padding: 0 1.5rem 1rem 1.5rem;\n gap: 0.75rem;\n }\n}\n\n@media (min-width: 1024px) {\n .mj-grid-4 {\n gap: 1rem;\n }\n}\n\n/* Static Card - No hover effects */\n.mj-card {\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n padding: 1rem;\n box-shadow: none;\n display: flex;\n align-items: center;\n gap: 1rem;\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 {\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: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n}\n\n.stat-icon-total {\n background: var(--md-primary-container);\n color: var(--md-primary);\n}\n\n.stat-icon-active {\n background: var(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n.stat-icon-inactive {\n background: var(--md-error-container);\n color: var(--md-error);\n}\n\n.stat-icon-admin {\n background: var(--md-secondary-container);\n color: #B5751A;\n}\n\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: 2rem;\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 flex-shrink: 0;\n background: var(--md-surface-container);\n margin: 0 1rem 0.75rem 1rem;\n padding: 0.75rem;\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n}\n\n@media (min-width: 768px) {\n .filters-section {\n margin: 0 1.5rem 1rem 1.5rem;\n padding: 1rem 1.25rem;\n }\n}\n\n.filters-row {\n display: flex;\n gap: 1rem;\n align-items: flex-end;\n flex-wrap: wrap;\n}\n\n@media (min-width: 768px) {\n .filters-row {\n gap: 1.5rem;\n }\n}\n\n@media (max-width: 767px) {\n .filters-section {\n padding: 0.75rem;\n }\n\n .filters-row {\n display: flex;\n flex-direction: row;\n gap: 0.75rem;\n align-items: center;\n }\n\n .filters-row .mj-search {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Search Input\n ----------------------------------------------------------------------------- */\n.mj-search {\n position: relative;\n flex: 1;\n min-width: 200px;\n max-width: 100%;\n}\n\n@media (min-width: 640px) {\n .mj-search {\n min-width: 280px;\n max-width: 500px;\n }\n}\n\n@media (min-width: 768px) {\n .mj-search {\n min-width: 320px;\n max-width: 600px;\n }\n}\n\n@media (max-width: 767px) {\n .mj-search {\n width: 100%;\n max-width: none;\n min-width: 0;\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: 48px;\n}\n\n@media (min-width: 768px) {\n .mj-search .mj-search-input {\n padding: 1rem 1.25rem 1rem 3rem;\n min-height: 52px;\n font-size: 1.0625rem;\n }\n\n .mj-search .mj-search-icon {\n left: 1.125rem;\n font-size: 1.125rem;\n }\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/* -----------------------------------------------------------------------------\n Mobile Filter Toggle Button\n ----------------------------------------------------------------------------- */\n.mobile-filter-toggle {\n display: none;\n align-items: center;\n justify-content: center;\n position: relative;\n width: 48px;\n height: 48px;\n min-width: 48px;\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n background: var(--md-surface-container-low);\n color: var(--md-on-surface-variant);\n font-size: 1.125rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--md-elevation-1);\n flex-shrink: 0;\n}\n\n.mobile-filter-toggle:hover {\n background: var(--md-surface-container);\n border-color: var(--md-primary);\n color: var(--md-primary);\n}\n\n.mobile-filter-toggle.active {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.filter-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--md-corner-full);\n background: var(--md-error);\n color: var(--md-on-error);\n font-size: 0.6875rem;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n}\n\n/* -----------------------------------------------------------------------------\n Mobile Filter Dropdown Panel\n ----------------------------------------------------------------------------- */\n.mobile-filter-dropdown {\n display: none;\n margin-top: 0.75rem;\n padding-top: 0.75rem;\n border-top: 1px solid var(--md-outline-variant);\n animation: slideDown 0.2s ease;\n}\n\n/* Mobile only - show filter toggle and dropdown */\n@media (max-width: 767px) {\n .mobile-filter-toggle {\n display: flex !important;\n }\n\n .mobile-filter-dropdown {\n display: block;\n }\n\n .desktop-filter-group {\n display: none !important;\n }\n}\n\n.mobile-filter-content {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.mobile-filter-content .mj-filter-group {\n width: 100%;\n}\n\n.mobile-filter-content .mj-filter-select {\n width: 100%;\n}\n\n.clear-filters-btn {\n align-self: flex-start;\n margin-top: 0.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Filter Controls - Mobile/Desktop visibility\n ----------------------------------------------------------------------------- */\n\n/* Desktop filter groups - hidden by default, shown on desktop */\n.desktop-filter-group {\n display: none !important;\n}\n\n/* Desktop only - show filter groups, hide mobile toggle */\n@media screen and (min-width: 768px) {\n .desktop-filter-group {\n display: flex !important;\n flex-direction: column;\n gap: 0.375rem;\n }\n\n .mobile-filter-toggle {\n display: none !important;\n }\n\n .mobile-filter-dropdown {\n display: none !important;\n }\n}\n\n.mj-filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n}\n\n@media (max-width: 767px) {\n .mj-filter-group {\n flex: 1;\n min-width: 100px;\n }\n}\n\n.mj-filter-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface);\n text-transform: uppercase;\n letter-spacing: 0.05em;\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}\n\n.mj-filter-buttons .mj-btn {\n border-radius: var(--md-corner-full);\n}\n\n.mj-filter-buttons .mj-btn-primary {\n background-color: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-filter-select {\n padding: 0.625rem 1rem;\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\n background: var(--md-surface-container-low);\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--md-on-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 120px;\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-filter-select:hover {\n background: var(--md-surface-container);\n border-color: var(--md-primary);\n}\n\n@media (max-width: 767px) {\n .mj-filter-select {\n width: 100%;\n padding: 0.5rem 0.75rem;\n font-size: 0.8125rem;\n }\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/* -----------------------------------------------------------------------------\n Content Area\n ----------------------------------------------------------------------------- */\n.content-area {\n flex: 1 1 auto;\n overflow: visible;\n position: relative;\n background: var(--md-surface);\n border-radius: var(--md-corner-large);\n box-shadow: var(--md-elevation-1);\n padding: 1rem;\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/* -----------------------------------------------------------------------------\n Users List - Unified Expandable Card Pattern\n ----------------------------------------------------------------------------- */\n.users-list {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n/* List Header with Select All */\n.list-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-small);\n border: 1px solid var(--md-outline-variant);\n margin-bottom: 0.5rem;\n}\n\n.select-all-label {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n cursor: pointer;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n.select-all-text {\n font-weight: 500;\n}\n\n.selection-count {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--md-primary);\n background: var(--md-primary-container);\n padding: 0.25rem 0.75rem;\n border-radius: var(--md-corner-full);\n}\n\n/* User Card - Interactive */\n.user-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.user-card:hover {\n box-shadow: var(--md-elevation-2);\n border-color: var(--md-primary);\n}\n\n.user-card.expanded {\n box-shadow: var(--md-elevation-3);\n border-color: var(--md-primary);\n}\n\n.user-card.selected {\n background: var(--md-primary-container);\n border-color: var(--md-primary);\n}\n\n.user-card.selected .user-header {\n background: transparent;\n}\n\n.user-card.selected:hover .user-header {\n background: rgba(0, 118, 182, 0.08);\n}\n\n/* User Card Header */\n.user-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n cursor: pointer;\n background: var(--md-surface-container-lowest);\n transition: background-color 0.2s ease;\n}\n\n.user-header:hover {\n background: var(--md-surface-container-low);\n}\n\n@media (max-width: 639px) {\n .user-header {\n padding: 0.875rem 1rem;\n gap: 0.625rem;\n }\n}\n\n/* User Selection */\n.user-selection {\n flex-shrink: 0;\n}\n\n.checkbox {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--md-primary);\n}\n\n/* User Info */\n.user-info {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex: 1;\n min-width: 0;\n}\n\n.user-avatar {\n width: 48px;\n height: 48px;\n border-radius: var(--md-corner-full);\n background: linear-gradient(135deg, var(--md-primary) 0%, #3395C8 100%);\n color: var(--md-on-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .user-avatar {\n width: 40px;\n height: 40px;\n font-size: 0.8125rem;\n }\n\n .user-details {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .user-name {\n font-size: 0.9375rem;\n font-weight: 600;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .user-email {\n font-size: 0.8125rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}\n\n.user-details {\n flex: 1;\n min-width: 0;\n}\n\n.user-name {\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.user-email {\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n margin: 0.125rem 0 0 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* User Meta */\n.user-meta {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 767px) {\n .user-meta .status-badge,\n .user-meta .user-actions {\n display: none !important;\n }\n\n .user-meta {\n gap: 0;\n }\n}\n\n/* Desktop Actions */\n.desktop-only {\n display: none;\n}\n\n@media (min-width: 768px) {\n .desktop-only {\n display: flex;\n gap: 0.25rem;\n }\n}\n\n.user-actions {\n display: flex;\n gap: 0.25rem;\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 ease;\n border-radius: var(--md-corner-full);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.expand-btn:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.expand-btn i {\n transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n.user-card.expanded .expand-btn i {\n transform: rotate(180deg);\n}\n\n/* User Card Content - Expanded */\n.user-content {\n padding: 1.25rem 1.5rem;\n background: var(--md-surface);\n border-top: 1px solid var(--md-outline-variant);\n animation: slideDown 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* Mobile Actions Bar */\n.mobile-actions-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding-bottom: 1rem;\n margin-bottom: 1rem;\n border-bottom: 1px solid var(--md-outline-variant);\n}\n\n@media (min-width: 768px) {\n .mobile-actions-bar {\n display: none;\n }\n}\n\n.mobile-action-buttons {\n display: flex;\n gap: 0.5rem;\n}\n\n.mobile-action-buttons .btn-label {\n margin-left: 0.375rem;\n}\n\n/* Status Badge */\n.status-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}\n\n.status-badge.status-active {\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n.status-badge.status-inactive {\n background: var(--md-error-container);\n color: var(--md-on-error-container);\n border: 1px solid var(--md-error);\n}\n\n.status-badge i {\n font-size: 0.625rem;\n}\n\n/* User Stats in Expanded Content */\n.user-stats {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin-bottom: 1rem;\n}\n\n.user-stats .stat-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n}\n\n.user-stats .stat-item i {\n color: var(--md-primary);\n font-size: 0.875rem;\n}\n\n.user-stats .stat-label {\n color: var(--md-on-surface-variant);\n}\n\n.user-stats .stat-value {\n color: var(--md-on-surface);\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.user-stats .stat-value i {\n font-size: 0.75rem;\n}\n\n/* Roles Section */\n.roles-section {\n padding-top: 1rem;\n border-top: 1px solid var(--md-outline-variant);\n}\n\n.section-title {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0 0 0.75rem 0;\n}\n\n.section-title i {\n color: var(--md-primary);\n font-size: 1.125rem;\n}\n\n.roles-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n\n.role-item {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.375rem 0.875rem;\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\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}\n\n.role-item i {\n font-size: 0.625rem;\n}\n\n.no-roles {\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n/* -----------------------------------------------------------------------------\n Empty State\n ----------------------------------------------------------------------------- */\n.empty-state {\n text-align: center;\n padding: 4rem 2rem;\n}\n\n.empty-state .empty-icon {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 1.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 0 0.5rem 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 Loading State\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/* -----------------------------------------------------------------------------\n Error State\n ----------------------------------------------------------------------------- */\n.error-container {\n text-align: center;\n padding: 4rem 2rem;\n}\n\n.error-container .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: 1rem;\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.error-container .retry-button {\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 background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n min-height: 44px;\n}\n\n.error-container .retry-button:hover {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.error-container .retry-button:active {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n/* -----------------------------------------------------------------------------\n Modal Dialog\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 1rem;\n animation: fadeIn 0.2s ease;\n}\n\n.modal-dialog {\n background: var(--md-surface);\n border-radius: var(--md-corner-extra-large);\n box-shadow: var(--md-elevation-5);\n max-width: 500px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n animation: slideUp 0.3s ease;\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 var(--md-outline-variant);\n}\n\n.modal-header .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.modal-header .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 min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n}\n\n.modal-header .modal-close:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.modal-body {\n padding: 1.5rem;\n}\n\n.modal-body p {\n font-size: 1rem;\n color: var(--md-on-surface);\n margin: 0 0 1rem 0;\n line-height: 1.5;\n}\n\n.modal-body p:last-child {\n margin-bottom: 0;\n}\n\n.modal-body .text-muted {\n font-size: 0.875rem;\n color: var(--md-on-surface-variant);\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid var(--md-outline-variant);\n background: var(--md-surface-container-low);\n}\n\n@media (max-width: 639px) {\n .modal-dialog {\n width: 95%;\n max-height: 85vh;\n }\n\n .modal-header {\n padding: 1rem;\n }\n\n .modal-header .modal-title {\n font-size: 1.125rem;\n }\n\n .modal-body {\n padding: 1rem;\n }\n\n .modal-body p {\n font-size: 0.9375rem;\n }\n\n .modal-footer {\n padding: 1rem;\n flex-wrap: wrap;\n }\n\n .modal-footer .mj-btn {\n flex: 1;\n min-width: 100px;\n }\n}\n\n/* Form Field in Modal */\n.form-field {\n margin-bottom: 1rem;\n}\n\n.form-field .field-label {\n display: block;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-bottom: 0.5rem;\n}\n\n.form-field .field-select {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid var(--md-outline);\n border-radius: var(--md-corner-small);\n background: var(--md-surface);\n font-size: 1rem;\n color: var(--md-on-surface);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-field .field-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/* -----------------------------------------------------------------------------\n MJ Button System - MD3 Compliant\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-height: 44px;\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 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 background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.mj-btn-primary:active:not(:disabled) {\n background: #4BA5D4;\n transform: scale(0.98);\n}\n\n/* Secondary Button - Light, fills with primary 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 with primary on hover */\n.mj-btn-ghost {\n background: transparent;\n color: var(--md-on-surface-variant);\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/* Danger Button - Dark red, lightens on hover */\n.mj-btn-danger {\n background: var(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.mj-btn-danger:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.mj-btn-danger:active:not(:disabled) {\n background: #EF9A9A;\n transform: scale(0.98);\n}\n\n/* Small Button */\n.mj-btn-sm {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n/* Ghost Danger Button */\n.mj-btn-ghost.mj-btn-danger {\n background: transparent;\n color: var(--md-error);\n box-shadow: none;\n}\n\n.mj-btn-ghost.mj-btn-danger:hover:not(:disabled) {\n background: var(--md-error-container);\n color: var(--md-error);\n}\n\n/* -----------------------------------------------------------------------------\n Utility Classes\n ----------------------------------------------------------------------------- */\n.text-danger {\n color: var(--md-error);\n}\n\n.text-success {\n color: var(--md-tertiary);\n}\n\n.text-warning {\n color: var(--md-secondary);\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/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\n.mj-search-input:focus-visible,\n.mj-filter-select:focus-visible,\nbutton:focus-visible,\n.checkbox:focus-visible,\n.user-header:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Reduced Motion\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\n/* -----------------------------------------------------------------------------\n Large Desktop (1440px+)\n ----------------------------------------------------------------------------- */\n@media (min-width: 1440px) {\n .user-management-container {\n max-width: 1920px;\n margin: 0 auto;\n }\n\n .action-buttons {\n padding: 1.25rem 2rem;\n }\n\n .bulk-action-toolbar {\n padding: 1.25rem 2rem;\n }\n\n .mj-grid-4 {\n gap: 1.5rem;\n padding: 0 2rem 1rem 2rem;\n }\n\n .filters-section {\n margin: 0 2rem 1rem 2rem;\n padding: 1rem 1.5rem;\n }\n\n .scrollable-content {\n padding: 2rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Mobile (< 640px) - Compact adjustments\n ----------------------------------------------------------------------------- */\n@media (max-width: 639px) {\n .sticky-header {\n padding-bottom: 0;\n }\n\n .mj-grid-4 {\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 0.75rem 0.5rem 0.75rem;\n }\n\n .mj-card {\n padding: 0.75rem;\n gap: 0.75rem;\n }\n\n .stat-icon {\n width: 40px;\n height: 40px;\n font-size: 1.125rem;\n }\n\n .stat-content .stat-value {\n font-size: 1.5rem;\n }\n\n .stat-content .stat-label {\n font-size: 0.6875rem;\n }\n\n .filters-section {\n margin: 0 0.75rem 0.5rem 0.75rem;\n padding: 0.75rem;\n }\n\n .scrollable-content {\n padding: 0.75rem;\n }\n\n .content-area {\n padding: 0.875rem;\n border-radius: var(--md-corner-medium);\n }\n\n .list-header {\n padding: 0.625rem 0.75rem;\n }\n\n .empty-state {\n padding: 2rem 1rem;\n }\n\n .empty-state .empty-icon {\n font-size: 3rem;\n }\n\n .empty-state .empty-text {\n font-size: 1.0625rem;\n }\n\n .empty-state .empty-subtext {\n font-size: 0.875rem;\n }\n}\n"] }]
|
|
764
1289
|
}], () => [], null); })();
|
|
765
1290
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UserManagementComponent, { className: "UserManagementComponent", filePath: "src/lib/user-management/user-management.component.ts", lineNumber: 29 }); })();
|
|
766
1291
|
//# sourceMappingURL=user-management.component.js.map
|