@memberjunction/ng-explorer-settings 5.34.1 → 5.36.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-management.component.d.ts +0 -1
- package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-management.component.js +151 -206
- package/dist/lib/application-management/application-management.component.js.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts +8 -3
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.js +247 -411
- package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
- package/dist/lib/module.d.ts +1 -1
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/module.js +31 -4
- package/dist/lib/module.js.map +1 -1
- package/dist/lib/role-management/role-management.component.d.ts +0 -2
- package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-management.component.js +136 -259
- package/dist/lib/role-management/role-management.component.js.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.js +221 -224
- package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
- package/dist/lib/user-management/user-management.component.d.ts +12 -3
- package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-management.component.js +356 -463
- package/dist/lib/user-management/user-management.component.js.map +1 -1
- package/package.json +19 -19
|
@@ -18,11 +18,11 @@ import * as i4 from "@memberjunction/ng-shared-generic";
|
|
|
18
18
|
import * as i5 from "@memberjunction/ng-ui-components";
|
|
19
19
|
const _forTrack0 = ($index, $item) => $item.id;
|
|
20
20
|
const _forTrack1 = ($index, $item) => $item.value;
|
|
21
|
-
function
|
|
21
|
+
function SqlLoggingComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
22
22
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
23
|
-
i0.ɵɵelementStart(0, "button",
|
|
24
|
-
i0.ɵɵlistener("click", function
|
|
25
|
-
i0.ɵɵelement(1, "i",
|
|
23
|
+
i0.ɵɵelementStart(0, "button", 9);
|
|
24
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_3_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openStartSessionDialog()); });
|
|
25
|
+
i0.ɵɵelement(1, "i", 10);
|
|
26
26
|
i0.ɵɵtext(2, " Start New Session ");
|
|
27
27
|
i0.ɵɵelementEnd();
|
|
28
28
|
} if (rf & 2) {
|
|
@@ -30,55 +30,55 @@ function SqlLoggingComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
|
30
30
|
i0.ɵɵproperty("disabled", ctx_r1.loading || ctx_r1.activeSessions.length >= ((ctx_r1.sqlLoggingConfig == null ? null : ctx_r1.sqlLoggingConfig.maxActiveSessions) || 5));
|
|
31
31
|
i0.ɵɵattribute("aria-label", "Start new SQL logging session" + (ctx_r1.activeSessions.length >= ((ctx_r1.sqlLoggingConfig == null ? null : ctx_r1.sqlLoggingConfig.maxActiveSessions) || 5) ? " (maximum sessions reached)" : ""));
|
|
32
32
|
} }
|
|
33
|
-
function
|
|
33
|
+
function SqlLoggingComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
34
34
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
35
|
-
i0.ɵɵelementStart(0, "div",
|
|
36
|
-
i0.ɵɵlistener("click", function
|
|
37
|
-
i0.ɵɵelementStart(2, "div",
|
|
38
|
-
i0.ɵɵelement(4, "i",
|
|
35
|
+
i0.ɵɵelementStart(0, "div", 4)(1, "button", 11);
|
|
36
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_5_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStats = !ctx_r1.showStats); });
|
|
37
|
+
i0.ɵɵelementStart(2, "div", 12)(3, "div", 13);
|
|
38
|
+
i0.ɵɵelement(4, "i", 14);
|
|
39
39
|
i0.ɵɵelementEnd();
|
|
40
|
-
i0.ɵɵelementStart(5, "div",
|
|
40
|
+
i0.ɵɵelementStart(5, "div", 15)(6, "h3", 16);
|
|
41
41
|
i0.ɵɵtext(7, "Statistics");
|
|
42
42
|
i0.ɵɵelementEnd();
|
|
43
|
-
i0.ɵɵelementStart(8, "p",
|
|
43
|
+
i0.ɵɵelementStart(8, "p", 17);
|
|
44
44
|
i0.ɵɵtext(9, "View session statistics and metrics");
|
|
45
45
|
i0.ɵɵelementEnd()()();
|
|
46
|
-
i0.ɵɵelement(10, "i",
|
|
46
|
+
i0.ɵɵelement(10, "i", 18);
|
|
47
47
|
i0.ɵɵelementEnd();
|
|
48
|
-
i0.ɵɵelementStart(11, "div",
|
|
49
|
-
i0.ɵɵelement(14, "i",
|
|
48
|
+
i0.ɵɵelementStart(11, "div", 19)(12, "div", 20)(13, "div", 21);
|
|
49
|
+
i0.ɵɵelement(14, "i", 22);
|
|
50
50
|
i0.ɵɵelementEnd();
|
|
51
|
-
i0.ɵɵelementStart(15, "div",
|
|
51
|
+
i0.ɵɵelementStart(15, "div", 23)(16, "div", 24);
|
|
52
52
|
i0.ɵɵtext(17);
|
|
53
53
|
i0.ɵɵelementEnd();
|
|
54
|
-
i0.ɵɵelementStart(18, "div",
|
|
54
|
+
i0.ɵɵelementStart(18, "div", 25);
|
|
55
55
|
i0.ɵɵtext(19, "Status");
|
|
56
56
|
i0.ɵɵelementEnd()()();
|
|
57
|
-
i0.ɵɵelementStart(20, "div",
|
|
58
|
-
i0.ɵɵelement(22, "i",
|
|
57
|
+
i0.ɵɵelementStart(20, "div", 20)(21, "div", 26);
|
|
58
|
+
i0.ɵɵelement(22, "i", 27);
|
|
59
59
|
i0.ɵɵelementEnd();
|
|
60
|
-
i0.ɵɵelementStart(23, "div",
|
|
60
|
+
i0.ɵɵelementStart(23, "div", 23)(24, "div", 24);
|
|
61
61
|
i0.ɵɵtext(25);
|
|
62
62
|
i0.ɵɵelementEnd();
|
|
63
|
-
i0.ɵɵelementStart(26, "div",
|
|
63
|
+
i0.ɵɵelementStart(26, "div", 25);
|
|
64
64
|
i0.ɵɵtext(27, "Active Sessions");
|
|
65
65
|
i0.ɵɵelementEnd()()();
|
|
66
|
-
i0.ɵɵelementStart(28, "div",
|
|
67
|
-
i0.ɵɵelement(30, "i",
|
|
66
|
+
i0.ɵɵelementStart(28, "div", 20)(29, "div", 28);
|
|
67
|
+
i0.ɵɵelement(30, "i", 29);
|
|
68
68
|
i0.ɵɵelementEnd();
|
|
69
|
-
i0.ɵɵelementStart(31, "div",
|
|
69
|
+
i0.ɵɵelementStart(31, "div", 23)(32, "div", 24);
|
|
70
70
|
i0.ɵɵtext(33);
|
|
71
71
|
i0.ɵɵelementEnd();
|
|
72
|
-
i0.ɵɵelementStart(34, "div",
|
|
72
|
+
i0.ɵɵelementStart(34, "div", 25);
|
|
73
73
|
i0.ɵɵtext(35, "Max Sessions");
|
|
74
74
|
i0.ɵɵelementEnd()()();
|
|
75
|
-
i0.ɵɵelementStart(36, "div",
|
|
76
|
-
i0.ɵɵelement(38, "i",
|
|
75
|
+
i0.ɵɵelementStart(36, "div", 20)(37, "div", 30);
|
|
76
|
+
i0.ɵɵelement(38, "i", 31);
|
|
77
77
|
i0.ɵɵelementEnd();
|
|
78
|
-
i0.ɵɵelementStart(39, "div",
|
|
78
|
+
i0.ɵɵelementStart(39, "div", 23)(40, "div", 24);
|
|
79
79
|
i0.ɵɵtext(41);
|
|
80
80
|
i0.ɵɵelementEnd();
|
|
81
|
-
i0.ɵɵelementStart(42, "div",
|
|
81
|
+
i0.ɵɵelementStart(42, "div", 25);
|
|
82
82
|
i0.ɵɵtext(43, "Total Statements");
|
|
83
83
|
i0.ɵɵelementEnd()()()()();
|
|
84
84
|
} if (rf & 2) {
|
|
@@ -105,37 +105,37 @@ function SqlLoggingComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
|
105
105
|
i0.ɵɵadvance();
|
|
106
106
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.getTotalStatementCount(), " ");
|
|
107
107
|
} }
|
|
108
|
-
function
|
|
109
|
-
i0.ɵɵelementStart(0, "div",
|
|
110
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
108
|
+
function SqlLoggingComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
109
|
+
i0.ɵɵelementStart(0, "div", 5);
|
|
110
|
+
i0.ɵɵelement(1, "mj-loading", 32);
|
|
111
111
|
i0.ɵɵelementEnd();
|
|
112
112
|
} }
|
|
113
|
-
function
|
|
113
|
+
function SqlLoggingComponent_Conditional_7_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
114
114
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
115
|
-
i0.ɵɵelementStart(0, "div",
|
|
116
|
-
i0.ɵɵelement(1, "i",
|
|
117
|
-
i0.ɵɵelementStart(2, "p",
|
|
115
|
+
i0.ɵɵelementStart(0, "div", 33);
|
|
116
|
+
i0.ɵɵelement(1, "i", 36);
|
|
117
|
+
i0.ɵɵelementStart(2, "p", 37);
|
|
118
118
|
i0.ɵɵtext(3, "Access Denied");
|
|
119
119
|
i0.ɵɵelementEnd();
|
|
120
|
-
i0.ɵɵelementStart(4, "p",
|
|
120
|
+
i0.ɵɵelementStart(4, "p", 38);
|
|
121
121
|
i0.ɵɵtext(5, "SQL logging requires Owner privileges. Please contact your system administrator for access.");
|
|
122
122
|
i0.ɵɵelementEnd();
|
|
123
|
-
i0.ɵɵelementStart(6, "button",
|
|
124
|
-
i0.ɵɵlistener("click", function
|
|
125
|
-
i0.ɵɵelement(7, "i",
|
|
123
|
+
i0.ɵɵelementStart(6, "button", 39);
|
|
124
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_1_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.refreshUserPermissions()); });
|
|
125
|
+
i0.ɵɵelement(7, "i", 40);
|
|
126
126
|
i0.ɵɵtext(8, " Refresh Permissions ");
|
|
127
127
|
i0.ɵɵelementEnd()();
|
|
128
128
|
} }
|
|
129
|
-
function
|
|
130
|
-
i0.ɵɵelementStart(0, "div",
|
|
131
|
-
i0.ɵɵelement(1, "i",
|
|
132
|
-
i0.ɵɵelementStart(2, "p",
|
|
129
|
+
function SqlLoggingComponent_Conditional_7_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
130
|
+
i0.ɵɵelementStart(0, "div", 33);
|
|
131
|
+
i0.ɵɵelement(1, "i", 41);
|
|
132
|
+
i0.ɵɵelementStart(2, "p", 37);
|
|
133
133
|
i0.ɵɵtext(3, "SQL Logging Disabled");
|
|
134
134
|
i0.ɵɵelementEnd();
|
|
135
|
-
i0.ɵɵelementStart(4, "p",
|
|
135
|
+
i0.ɵɵelementStart(4, "p", 38);
|
|
136
136
|
i0.ɵɵtext(5, "SQL logging is not enabled in the server configuration.");
|
|
137
137
|
i0.ɵɵelementEnd();
|
|
138
|
-
i0.ɵɵelementStart(6, "div",
|
|
138
|
+
i0.ɵɵelementStart(6, "div", 42)(7, "h4");
|
|
139
139
|
i0.ɵɵtext(8, "To enable SQL logging:");
|
|
140
140
|
i0.ɵɵelementEnd();
|
|
141
141
|
i0.ɵɵelementStart(9, "ol")(10, "li");
|
|
@@ -152,68 +152,68 @@ function SqlLoggingComponent_Conditional_8_Conditional_2_Template(rf, ctx) { if
|
|
|
152
152
|
i0.ɵɵtext(18, "Refresh this page");
|
|
153
153
|
i0.ɵɵelementEnd()()()();
|
|
154
154
|
} }
|
|
155
|
-
function
|
|
155
|
+
function SqlLoggingComponent_Conditional_7_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
156
156
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
157
|
-
i0.ɵɵelementStart(0, "div",
|
|
158
|
-
i0.ɵɵelement(1, "i",
|
|
159
|
-
i0.ɵɵelementStart(2, "p",
|
|
157
|
+
i0.ɵɵelementStart(0, "div", 34);
|
|
158
|
+
i0.ɵɵelement(1, "i", 43);
|
|
159
|
+
i0.ɵɵelementStart(2, "p", 37);
|
|
160
160
|
i0.ɵɵtext(3, "No Active Sessions");
|
|
161
161
|
i0.ɵɵelementEnd();
|
|
162
|
-
i0.ɵɵelementStart(4, "p",
|
|
162
|
+
i0.ɵɵelementStart(4, "p", 38);
|
|
163
163
|
i0.ɵɵtext(5, "Start a new SQL logging session to begin capturing SQL statements.");
|
|
164
164
|
i0.ɵɵelementEnd();
|
|
165
|
-
i0.ɵɵelementStart(6, "button",
|
|
166
|
-
i0.ɵɵlistener("click", function
|
|
167
|
-
i0.ɵɵelement(7, "i",
|
|
165
|
+
i0.ɵɵelementStart(6, "button", 44);
|
|
166
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_3_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.openStartSessionDialog()); });
|
|
167
|
+
i0.ɵɵelement(7, "i", 10);
|
|
168
168
|
i0.ɵɵtext(8, " Start New Session ");
|
|
169
169
|
i0.ɵɵelementEnd()();
|
|
170
170
|
} }
|
|
171
|
-
function
|
|
171
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
172
172
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
173
|
-
i0.ɵɵelementStart(0, "button",
|
|
174
|
-
i0.ɵɵlistener("click", function
|
|
175
|
-
i0.ɵɵelement(1, "i",
|
|
173
|
+
i0.ɵɵelementStart(0, "button", 52);
|
|
174
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openStopAllSessionsConfirm()); });
|
|
175
|
+
i0.ɵɵelement(1, "i", 53);
|
|
176
176
|
i0.ɵɵtext(2, " Stop All ");
|
|
177
177
|
i0.ɵɵelementEnd();
|
|
178
178
|
} if (rf & 2) {
|
|
179
179
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
180
180
|
i0.ɵɵproperty("disabled", ctx_r1.loading);
|
|
181
181
|
} }
|
|
182
|
-
function
|
|
183
|
-
i0.ɵɵelementStart(0, "span",
|
|
184
|
-
i0.ɵɵelement(1, "i",
|
|
182
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
183
|
+
i0.ɵɵelementStart(0, "span", 63);
|
|
184
|
+
i0.ɵɵelement(1, "i", 66);
|
|
185
185
|
i0.ɵɵtext(2, " User Filtered ");
|
|
186
186
|
i0.ɵɵelementEnd();
|
|
187
187
|
} }
|
|
188
|
-
function
|
|
189
|
-
i0.ɵɵelementStart(0, "span",
|
|
190
|
-
i0.ɵɵelement(1, "i",
|
|
188
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
189
|
+
i0.ɵɵelementStart(0, "span", 64);
|
|
190
|
+
i0.ɵɵelement(1, "i", 67);
|
|
191
191
|
i0.ɵɵtext(2, " Migration ");
|
|
192
192
|
i0.ɵɵelementEnd();
|
|
193
193
|
} }
|
|
194
|
-
function
|
|
194
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
195
195
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
196
|
-
i0.ɵɵelementStart(0, "div",
|
|
197
|
-
i0.ɵɵlistener("click", function
|
|
198
|
-
i0.ɵɵelementStart(1, "div",
|
|
196
|
+
i0.ɵɵelementStart(0, "div", 54);
|
|
197
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Template_div_click_0_listener() { const session_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectSession(session_r8)); })("keydown.enter", function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Template_div_keydown_enter_0_listener() { const session_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.selectSession(session_r8)); })("keydown.space", function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Template_div_keydown_space_0_listener($event) { const session_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); ctx_r1.selectSession(session_r8); return i0.ɵɵresetView($event.preventDefault()); });
|
|
198
|
+
i0.ɵɵelementStart(1, "div", 55)(2, "div", 56)(3, "h4", 57);
|
|
199
199
|
i0.ɵɵtext(4);
|
|
200
200
|
i0.ɵɵelementEnd();
|
|
201
|
-
i0.ɵɵelementStart(5, "div",
|
|
202
|
-
i0.ɵɵelement(7, "i",
|
|
201
|
+
i0.ɵɵelementStart(5, "div", 58)(6, "span", 59);
|
|
202
|
+
i0.ɵɵelement(7, "i", 60);
|
|
203
203
|
i0.ɵɵtext(8);
|
|
204
204
|
i0.ɵɵelementEnd();
|
|
205
|
-
i0.ɵɵelementStart(9, "span",
|
|
206
|
-
i0.ɵɵelement(10, "i",
|
|
205
|
+
i0.ɵɵelementStart(9, "span", 59);
|
|
206
|
+
i0.ɵɵelement(10, "i", 31);
|
|
207
207
|
i0.ɵɵtext(11);
|
|
208
208
|
i0.ɵɵelementEnd()()();
|
|
209
|
-
i0.ɵɵelementStart(12, "button",
|
|
210
|
-
i0.ɵɵlistener("click", function
|
|
211
|
-
i0.ɵɵelement(13, "i",
|
|
209
|
+
i0.ɵɵelementStart(12, "button", 61);
|
|
210
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Template_button_click_12_listener($event) { const session_r8 = i0.ɵɵrestoreView(_r7).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openStopSessionConfirm(session_r8, $event)); });
|
|
211
|
+
i0.ɵɵelement(13, "i", 53);
|
|
212
212
|
i0.ɵɵelementEnd()();
|
|
213
|
-
i0.ɵɵelementStart(14, "div",
|
|
214
|
-
i0.ɵɵconditionalCreate(15,
|
|
215
|
-
i0.ɵɵconditionalCreate(16,
|
|
216
|
-
i0.ɵɵelementStart(17, "span",
|
|
213
|
+
i0.ɵɵelementStart(14, "div", 62);
|
|
214
|
+
i0.ɵɵconditionalCreate(15, SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Conditional_15_Template, 3, 0, "span", 63);
|
|
215
|
+
i0.ɵɵconditionalCreate(16, SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Conditional_16_Template, 3, 0, "span", 64);
|
|
216
|
+
i0.ɵɵelementStart(17, "span", 65);
|
|
217
217
|
i0.ɵɵtext(18);
|
|
218
218
|
i0.ɵɵelementEnd()()();
|
|
219
219
|
} if (rf & 2) {
|
|
@@ -236,26 +236,26 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template(rf, ctx)
|
|
|
236
236
|
i0.ɵɵadvance(2);
|
|
237
237
|
i0.ɵɵtextInterpolate1(" ", (session_r8.options == null ? null : session_r8.options.statementTypes) || "both", " ");
|
|
238
238
|
} }
|
|
239
|
-
function
|
|
239
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
240
240
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
241
|
-
i0.ɵɵelementStart(0, "div",
|
|
241
|
+
i0.ɵɵelementStart(0, "div", 46)(1, "h3", 47);
|
|
242
242
|
i0.ɵɵtext(2);
|
|
243
243
|
i0.ɵɵelementEnd();
|
|
244
|
-
i0.ɵɵelementStart(3, "div",
|
|
245
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
244
|
+
i0.ɵɵelementStart(3, "div", 68)(4, "label", 69)(5, "input", 70);
|
|
245
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_10_Template_input_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(3); i0.ɵɵtwoWayBindingSet(ctx_r1.autoRefresh, $event) || (ctx_r1.autoRefresh = $event); return i0.ɵɵresetView($event); });
|
|
246
246
|
i0.ɵɵelementEnd();
|
|
247
247
|
i0.ɵɵtext(6, " Auto-refresh ");
|
|
248
248
|
i0.ɵɵelementEnd();
|
|
249
|
-
i0.ɵɵelementStart(7, "button",
|
|
250
|
-
i0.ɵɵlistener("click", function
|
|
251
|
-
i0.ɵɵelement(8, "i",
|
|
249
|
+
i0.ɵɵelementStart(7, "button", 71);
|
|
250
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_10_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.loadSessionLog(ctx_r1.selectedSession)); });
|
|
251
|
+
i0.ɵɵelement(8, "i", 40);
|
|
252
252
|
i0.ɵɵelementEnd();
|
|
253
|
-
i0.ɵɵelementStart(9, "button",
|
|
254
|
-
i0.ɵɵlistener("click", function
|
|
255
|
-
i0.ɵɵelement(10, "i",
|
|
253
|
+
i0.ɵɵelementStart(9, "button", 72);
|
|
254
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_10_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleLogViewerExpand()); });
|
|
255
|
+
i0.ɵɵelement(10, "i", 73);
|
|
256
256
|
i0.ɵɵelementEnd()()();
|
|
257
|
-
i0.ɵɵelementStart(11, "div",
|
|
258
|
-
i0.ɵɵelement(12, "mj-code-editor",
|
|
257
|
+
i0.ɵɵelementStart(11, "div", 74);
|
|
258
|
+
i0.ɵɵelement(12, "mj-code-editor", 75);
|
|
259
259
|
i0.ɵɵelementEnd();
|
|
260
260
|
} if (rf & 2) {
|
|
261
261
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -272,27 +272,27 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template
|
|
|
272
272
|
i0.ɵɵadvance(2);
|
|
273
273
|
i0.ɵɵproperty("value", ctx_r1.logContent)("readonly", true)("disabled", true)("language", "sql")("setup", "basic")("lineWrapping", true)("highlightWhitespace", false);
|
|
274
274
|
} }
|
|
275
|
-
function
|
|
276
|
-
i0.ɵɵelementStart(0, "div",
|
|
277
|
-
i0.ɵɵelement(1, "i",
|
|
278
|
-
i0.ɵɵelementStart(2, "p",
|
|
275
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
276
|
+
i0.ɵɵelementStart(0, "div", 34);
|
|
277
|
+
i0.ɵɵelement(1, "i", 76);
|
|
278
|
+
i0.ɵɵelementStart(2, "p", 37);
|
|
279
279
|
i0.ɵɵtext(3, "Select a Session");
|
|
280
280
|
i0.ɵɵelementEnd();
|
|
281
|
-
i0.ɵɵelementStart(4, "p",
|
|
281
|
+
i0.ɵɵelementStart(4, "p", 38);
|
|
282
282
|
i0.ɵɵtext(5, "Choose a session from the list to view its SQL log.");
|
|
283
283
|
i0.ɵɵelementEnd()();
|
|
284
284
|
} }
|
|
285
|
-
function
|
|
286
|
-
i0.ɵɵelementStart(0, "div",
|
|
285
|
+
function SqlLoggingComponent_Conditional_7_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
286
|
+
i0.ɵɵelementStart(0, "div", 35)(1, "div", 45)(2, "div", 46)(3, "h3", 47);
|
|
287
287
|
i0.ɵɵtext(4, "Active Sessions");
|
|
288
288
|
i0.ɵɵelementEnd();
|
|
289
|
-
i0.ɵɵconditionalCreate(5,
|
|
289
|
+
i0.ɵɵconditionalCreate(5, SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_5_Template, 3, 1, "button", 48);
|
|
290
290
|
i0.ɵɵelementEnd();
|
|
291
|
-
i0.ɵɵelementStart(6, "div",
|
|
292
|
-
i0.ɵɵrepeaterCreate(7,
|
|
291
|
+
i0.ɵɵelementStart(6, "div", 49);
|
|
292
|
+
i0.ɵɵrepeaterCreate(7, SqlLoggingComponent_Conditional_7_Conditional_4_For_8_Template, 19, 11, "div", 50, _forTrack0);
|
|
293
293
|
i0.ɵɵelementEnd()();
|
|
294
|
-
i0.ɵɵelementStart(9, "div",
|
|
295
|
-
i0.ɵɵconditionalCreate(10,
|
|
294
|
+
i0.ɵɵelementStart(9, "div", 51);
|
|
295
|
+
i0.ɵɵconditionalCreate(10, SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_10_Template, 13, 17)(11, SqlLoggingComponent_Conditional_7_Conditional_4_Conditional_11_Template, 6, 0, "div", 34);
|
|
296
296
|
i0.ɵɵelementEnd()();
|
|
297
297
|
} if (rf & 2) {
|
|
298
298
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -305,17 +305,17 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if
|
|
|
305
305
|
i0.ɵɵadvance();
|
|
306
306
|
i0.ɵɵconditional(ctx_r1.selectedSession ? 10 : 11);
|
|
307
307
|
} }
|
|
308
|
-
function
|
|
309
|
-
i0.ɵɵelementStart(0, "div",
|
|
310
|
-
i0.ɵɵconditionalCreate(1,
|
|
308
|
+
function SqlLoggingComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
309
|
+
i0.ɵɵelementStart(0, "div", 6);
|
|
310
|
+
i0.ɵɵconditionalCreate(1, SqlLoggingComponent_Conditional_7_Conditional_1_Template, 9, 0, "div", 33)(2, SqlLoggingComponent_Conditional_7_Conditional_2_Template, 19, 0, "div", 33)(3, SqlLoggingComponent_Conditional_7_Conditional_3_Template, 9, 0, "div", 34)(4, SqlLoggingComponent_Conditional_7_Conditional_4_Template, 12, 4, "div", 35);
|
|
311
311
|
i0.ɵɵelementEnd();
|
|
312
312
|
} if (rf & 2) {
|
|
313
313
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
314
314
|
i0.ɵɵadvance();
|
|
315
315
|
i0.ɵɵconditional(!ctx_r1.isOwner ? 1 : !ctx_r1.configEnabled ? 2 : ctx_r1.activeSessions.length === 0 ? 3 : 4);
|
|
316
316
|
} }
|
|
317
|
-
function
|
|
318
|
-
i0.ɵɵelementStart(0, "option",
|
|
317
|
+
function SqlLoggingComponent_Conditional_8_For_29_Template(rf, ctx) { if (rf & 1) {
|
|
318
|
+
i0.ɵɵelementStart(0, "option", 95);
|
|
319
319
|
i0.ɵɵtext(1);
|
|
320
320
|
i0.ɵɵelementEnd();
|
|
321
321
|
} if (rf & 2) {
|
|
@@ -324,8 +324,8 @@ function SqlLoggingComponent_Conditional_9_For_29_Template(rf, ctx) { if (rf & 1
|
|
|
324
324
|
i0.ɵɵadvance();
|
|
325
325
|
i0.ɵɵtextInterpolate(option_r11.text);
|
|
326
326
|
} }
|
|
327
|
-
function
|
|
328
|
-
i0.ɵɵelementStart(0, "option",
|
|
327
|
+
function SqlLoggingComponent_Conditional_8_For_51_Template(rf, ctx) { if (rf & 1) {
|
|
328
|
+
i0.ɵɵelementStart(0, "option", 95);
|
|
329
329
|
i0.ɵɵtext(1);
|
|
330
330
|
i0.ɵɵelementEnd();
|
|
331
331
|
} if (rf & 2) {
|
|
@@ -334,15 +334,15 @@ function SqlLoggingComponent_Conditional_9_For_51_Template(rf, ctx) { if (rf & 1
|
|
|
334
334
|
i0.ɵɵadvance();
|
|
335
335
|
i0.ɵɵtextInterpolate(option_r12.text);
|
|
336
336
|
} }
|
|
337
|
-
function
|
|
337
|
+
function SqlLoggingComponent_Conditional_8_Conditional_64_Template(rf, ctx) { if (rf & 1) {
|
|
338
338
|
const _r13 = i0.ɵɵgetCurrentView();
|
|
339
|
-
i0.ɵɵelementStart(0, "div",
|
|
339
|
+
i0.ɵɵelementStart(0, "div", 86)(1, "label", 114);
|
|
340
340
|
i0.ɵɵtext(2, "Default Schema Name");
|
|
341
341
|
i0.ɵɵelementEnd();
|
|
342
|
-
i0.ɵɵelementStart(3, "input",
|
|
343
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
342
|
+
i0.ɵɵelementStart(3, "input", 115);
|
|
343
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Conditional_64_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.defaultSchemaName, $event) || (ctx_r1.newSessionOptions.defaultSchemaName = $event); return i0.ɵɵresetView($event); });
|
|
344
344
|
i0.ɵɵelementEnd();
|
|
345
|
-
i0.ɵɵelementStart(4, "div",
|
|
345
|
+
i0.ɵɵelementStart(4, "div", 116);
|
|
346
346
|
i0.ɵɵtext(5, "Schema name to replace with ${flyway:defaultSchema} placeholder.");
|
|
347
347
|
i0.ɵɵelementEnd()();
|
|
348
348
|
} if (rf & 2) {
|
|
@@ -350,117 +350,117 @@ function SqlLoggingComponent_Conditional_9_Conditional_64_Template(rf, ctx) { if
|
|
|
350
350
|
i0.ɵɵadvance(3);
|
|
351
351
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.defaultSchemaName);
|
|
352
352
|
} }
|
|
353
|
-
function
|
|
354
|
-
i0.ɵɵelement(0, "i",
|
|
353
|
+
function SqlLoggingComponent_Conditional_8_Conditional_73_Template(rf, ctx) { if (rf & 1) {
|
|
354
|
+
i0.ɵɵelement(0, "i", 117);
|
|
355
355
|
i0.ɵɵtext(1, " Starting... ");
|
|
356
356
|
} }
|
|
357
|
-
function
|
|
358
|
-
i0.ɵɵelement(0, "i",
|
|
357
|
+
function SqlLoggingComponent_Conditional_8_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
358
|
+
i0.ɵɵelement(0, "i", 10);
|
|
359
359
|
i0.ɵɵtext(1, " Start Session ");
|
|
360
360
|
} }
|
|
361
|
-
function
|
|
361
|
+
function SqlLoggingComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
362
362
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
363
|
-
i0.ɵɵelementStart(0, "div",
|
|
364
|
-
i0.ɵɵlistener("click", function
|
|
365
|
-
i0.ɵɵelementStart(1, "div",
|
|
366
|
-
i0.ɵɵlistener("click", function
|
|
367
|
-
i0.ɵɵelementStart(2, "div",
|
|
368
|
-
i0.ɵɵelement(4, "i",
|
|
363
|
+
i0.ɵɵelementStart(0, "div", 77);
|
|
364
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
|
|
365
|
+
i0.ɵɵelementStart(1, "div", 78);
|
|
366
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r10); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
367
|
+
i0.ɵɵelementStart(2, "div", 79)(3, "h3", 80);
|
|
368
|
+
i0.ɵɵelement(4, "i", 10);
|
|
369
369
|
i0.ɵɵtext(5, " Start SQL Logging Session ");
|
|
370
370
|
i0.ɵɵelementEnd();
|
|
371
|
-
i0.ɵɵelementStart(6, "div",
|
|
372
|
-
i0.ɵɵlistener("click", function
|
|
373
|
-
i0.ɵɵelement(8, "i",
|
|
371
|
+
i0.ɵɵelementStart(6, "div", 81)(7, "button", 82);
|
|
372
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleStartDialogFullscreen()); });
|
|
373
|
+
i0.ɵɵelement(8, "i", 73);
|
|
374
374
|
i0.ɵɵelementEnd();
|
|
375
|
-
i0.ɵɵelementStart(9, "button",
|
|
376
|
-
i0.ɵɵlistener("click", function
|
|
377
|
-
i0.ɵɵelement(10, "i",
|
|
375
|
+
i0.ɵɵelementStart(9, "button", 83);
|
|
376
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
|
|
377
|
+
i0.ɵɵelement(10, "i", 84);
|
|
378
378
|
i0.ɵɵelementEnd()()();
|
|
379
|
-
i0.ɵɵelementStart(11, "div",
|
|
379
|
+
i0.ɵɵelementStart(11, "div", 85)(12, "div", 86)(13, "label", 87);
|
|
380
380
|
i0.ɵɵtext(14, "Session Name");
|
|
381
381
|
i0.ɵɵelementEnd();
|
|
382
|
-
i0.ɵɵelementStart(15, "input",
|
|
383
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
382
|
+
i0.ɵɵelementStart(15, "input", 88);
|
|
383
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_input_ngModelChange_15_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.sessionName, $event) || (ctx_r1.newSessionOptions.sessionName = $event); return i0.ɵɵresetView($event); });
|
|
384
384
|
i0.ɵɵelementEnd();
|
|
385
|
-
i0.ɵɵelementStart(16, "div",
|
|
385
|
+
i0.ɵɵelementStart(16, "div", 89);
|
|
386
386
|
i0.ɵɵtext(17, "A descriptive name to identify this logging session");
|
|
387
387
|
i0.ɵɵelementEnd()();
|
|
388
|
-
i0.ɵɵelementStart(18, "div",
|
|
388
|
+
i0.ɵɵelementStart(18, "div", 86)(19, "label", 90);
|
|
389
389
|
i0.ɵɵtext(20, "File Name");
|
|
390
390
|
i0.ɵɵelementEnd();
|
|
391
|
-
i0.ɵɵelementStart(21, "input",
|
|
392
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
391
|
+
i0.ɵɵelementStart(21, "input", 91);
|
|
392
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_input_ngModelChange_21_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.fileName, $event) || (ctx_r1.newSessionOptions.fileName = $event); return i0.ɵɵresetView($event); });
|
|
393
393
|
i0.ɵɵelementEnd();
|
|
394
|
-
i0.ɵɵelementStart(22, "div",
|
|
394
|
+
i0.ɵɵelementStart(22, "div", 92);
|
|
395
395
|
i0.ɵɵtext(23, "The SQL log will be saved to this file");
|
|
396
396
|
i0.ɵɵelementEnd()();
|
|
397
|
-
i0.ɵɵelementStart(24, "div",
|
|
397
|
+
i0.ɵɵelementStart(24, "div", 86)(25, "label", 93);
|
|
398
398
|
i0.ɵɵtext(26, "Statement Types");
|
|
399
399
|
i0.ɵɵelementEnd();
|
|
400
|
-
i0.ɵɵelementStart(27, "select",
|
|
401
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
402
|
-
i0.ɵɵrepeaterCreate(28,
|
|
400
|
+
i0.ɵɵelementStart(27, "select", 94);
|
|
401
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_select_ngModelChange_27_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.statementTypes, $event) || (ctx_r1.newSessionOptions.statementTypes = $event); return i0.ɵɵresetView($event); });
|
|
402
|
+
i0.ɵɵrepeaterCreate(28, SqlLoggingComponent_Conditional_8_For_29_Template, 2, 2, "option", 95, _forTrack1);
|
|
403
403
|
i0.ɵɵelementEnd();
|
|
404
|
-
i0.ɵɵelementStart(30, "div",
|
|
404
|
+
i0.ɵɵelementStart(30, "div", 96);
|
|
405
405
|
i0.ɵɵtext(31, "Filter which types of SQL statements to capture");
|
|
406
406
|
i0.ɵɵelementEnd()();
|
|
407
|
-
i0.ɵɵelementStart(32, "div",
|
|
408
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
407
|
+
i0.ɵɵelementStart(32, "div", 97)(33, "label", 69)(34, "input", 98);
|
|
408
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_input_ngModelChange_34_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.filterToCurrentUser, $event) || (ctx_r1.newSessionOptions.filterToCurrentUser = $event); return i0.ɵɵresetView($event); });
|
|
409
409
|
i0.ɵɵelementEnd();
|
|
410
410
|
i0.ɵɵtext(35, " Filter to my SQL statements only ");
|
|
411
411
|
i0.ɵɵelementEnd();
|
|
412
|
-
i0.ɵɵelementStart(36, "label",
|
|
413
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
412
|
+
i0.ɵɵelementStart(36, "label", 69)(37, "input", 98);
|
|
413
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_input_ngModelChange_37_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.formatAsMigration, $event) || (ctx_r1.newSessionOptions.formatAsMigration = $event); return i0.ɵɵresetView($event); });
|
|
414
414
|
i0.ɵɵelementEnd();
|
|
415
415
|
i0.ɵɵtext(38, " Format as migration file ");
|
|
416
416
|
i0.ɵɵelementEnd();
|
|
417
|
-
i0.ɵɵelementStart(39, "label",
|
|
418
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
417
|
+
i0.ɵɵelementStart(39, "label", 69)(40, "input", 98);
|
|
418
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_input_ngModelChange_40_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.prettyPrint, $event) || (ctx_r1.newSessionOptions.prettyPrint = $event); return i0.ɵɵresetView($event); });
|
|
419
419
|
i0.ɵɵelementEnd();
|
|
420
420
|
i0.ɵɵtext(41, " Pretty print SQL statements ");
|
|
421
421
|
i0.ɵɵelementEnd()();
|
|
422
|
-
i0.ɵɵelementStart(42, "div",
|
|
423
|
-
i0.ɵɵelement(44, "i",
|
|
422
|
+
i0.ɵɵelementStart(42, "div", 99)(43, "h4", 100);
|
|
423
|
+
i0.ɵɵelement(44, "i", 101);
|
|
424
424
|
i0.ɵɵtext(45, " SQL Pattern Filtering ");
|
|
425
425
|
i0.ɵɵelementEnd();
|
|
426
|
-
i0.ɵɵelementStart(46, "div",
|
|
426
|
+
i0.ɵɵelementStart(46, "div", 86)(47, "label", 102);
|
|
427
427
|
i0.ɵɵtext(48, "Filter Mode");
|
|
428
428
|
i0.ɵɵelementEnd();
|
|
429
|
-
i0.ɵɵelementStart(49, "select",
|
|
430
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
431
|
-
i0.ɵɵrepeaterCreate(50,
|
|
429
|
+
i0.ɵɵelementStart(49, "select", 103);
|
|
430
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_select_ngModelChange_49_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.filterType, $event) || (ctx_r1.newSessionOptions.filterType = $event); return i0.ɵɵresetView($event); });
|
|
431
|
+
i0.ɵɵrepeaterCreate(50, SqlLoggingComponent_Conditional_8_For_51_Template, 2, 2, "option", 95, _forTrack1);
|
|
432
432
|
i0.ɵɵelementEnd();
|
|
433
|
-
i0.ɵɵelementStart(52, "div",
|
|
433
|
+
i0.ɵɵelementStart(52, "div", 104);
|
|
434
434
|
i0.ɵɵtext(53, "Exclude: Skip SQL matching any pattern. Include: Only log SQL matching a pattern.");
|
|
435
435
|
i0.ɵɵelementEnd()();
|
|
436
|
-
i0.ɵɵelementStart(54, "div",
|
|
436
|
+
i0.ɵɵelementStart(54, "div", 86)(55, "label", 105);
|
|
437
437
|
i0.ɵɵtext(56, "Filter Patterns (one per line or comma-separated)");
|
|
438
438
|
i0.ɵɵelementEnd();
|
|
439
|
-
i0.ɵɵelementStart(57, "textarea",
|
|
440
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
439
|
+
i0.ɵɵelementStart(57, "textarea", 106);
|
|
440
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_textarea_ngModelChange_57_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.filterPatterns, $event) || (ctx_r1.newSessionOptions.filterPatterns = $event); return i0.ɵɵresetView($event); });
|
|
441
441
|
i0.ɵɵelementEnd();
|
|
442
|
-
i0.ɵɵelementStart(58, "div",
|
|
442
|
+
i0.ɵɵelementStart(58, "div", 107);
|
|
443
443
|
i0.ɵɵtext(59, "Supports wildcards (*) and regex (/pattern/flags). Example: *spCreate* matches any SP starting with spCreate.");
|
|
444
444
|
i0.ɵɵelementEnd()()();
|
|
445
|
-
i0.ɵɵelementStart(60, "div",
|
|
446
|
-
i0.ɵɵelement(62, "i",
|
|
445
|
+
i0.ɵɵelementStart(60, "div", 99)(61, "h4", 100);
|
|
446
|
+
i0.ɵɵelement(62, "i", 108);
|
|
447
447
|
i0.ɵɵtext(63, " Advanced Options ");
|
|
448
448
|
i0.ɵɵelementEnd();
|
|
449
|
-
i0.ɵɵconditionalCreate(64,
|
|
450
|
-
i0.ɵɵelementStart(65, "div",
|
|
451
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
449
|
+
i0.ɵɵconditionalCreate(64, SqlLoggingComponent_Conditional_8_Conditional_64_Template, 6, 1, "div", 86);
|
|
450
|
+
i0.ɵɵelementStart(65, "div", 109)(66, "label", 69)(67, "input", 98);
|
|
451
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Template_input_ngModelChange_67_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.verboseOutput, $event) || (ctx_r1.newSessionOptions.verboseOutput = $event); return i0.ɵɵresetView($event); });
|
|
452
452
|
i0.ɵɵelementEnd();
|
|
453
453
|
i0.ɵɵtext(68, " Verbose Debug Output ");
|
|
454
454
|
i0.ɵɵelementEnd();
|
|
455
|
-
i0.ɵɵelementStart(69, "div",
|
|
455
|
+
i0.ɵɵelementStart(69, "div", 110);
|
|
456
456
|
i0.ɵɵtext(70, "Log detailed filter decisions to server console (for debugging).");
|
|
457
457
|
i0.ɵɵelementEnd()()()();
|
|
458
|
-
i0.ɵɵelementStart(71, "div",
|
|
459
|
-
i0.ɵɵlistener("click", function
|
|
460
|
-
i0.ɵɵconditionalCreate(73,
|
|
458
|
+
i0.ɵɵelementStart(71, "div", 111)(72, "button", 112);
|
|
459
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Template_button_click_72_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startNewSession()); });
|
|
460
|
+
i0.ɵɵconditionalCreate(73, SqlLoggingComponent_Conditional_8_Conditional_73_Template, 2, 0)(74, SqlLoggingComponent_Conditional_8_Conditional_74_Template, 2, 0);
|
|
461
461
|
i0.ɵɵelementEnd();
|
|
462
|
-
i0.ɵɵelementStart(75, "button",
|
|
463
|
-
i0.ɵɵlistener("click", function
|
|
462
|
+
i0.ɵɵelementStart(75, "button", 113);
|
|
463
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Template_button_click_75_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
|
|
464
464
|
i0.ɵɵtext(76, "Cancel");
|
|
465
465
|
i0.ɵɵelementEnd()()()();
|
|
466
466
|
} if (rf & 2) {
|
|
@@ -500,13 +500,13 @@ function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
|
500
500
|
i0.ɵɵadvance();
|
|
501
501
|
i0.ɵɵconditional(ctx_r1.loading ? 73 : 74);
|
|
502
502
|
} }
|
|
503
|
-
function
|
|
503
|
+
function SqlLoggingComponent_Conditional_9_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
504
504
|
i0.ɵɵtext(0, " Stop All Sessions? ");
|
|
505
505
|
} }
|
|
506
|
-
function
|
|
506
|
+
function SqlLoggingComponent_Conditional_9_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
507
507
|
i0.ɵɵtext(0, " Stop Session? ");
|
|
508
508
|
} }
|
|
509
|
-
function
|
|
509
|
+
function SqlLoggingComponent_Conditional_9_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
510
510
|
i0.ɵɵtext(0, " Are you sure you want to stop ");
|
|
511
511
|
i0.ɵɵelementStart(1, "strong");
|
|
512
512
|
i0.ɵɵtext(2);
|
|
@@ -517,13 +517,13 @@ function SqlLoggingComponent_Conditional_10_Conditional_9_Template(rf, ctx) { if
|
|
|
517
517
|
i0.ɵɵadvance(2);
|
|
518
518
|
i0.ɵɵtextInterpolate1("all ", ctx_r1.activeSessions.length, " active");
|
|
519
519
|
} }
|
|
520
|
-
function
|
|
520
|
+
function SqlLoggingComponent_Conditional_9_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
521
521
|
i0.ɵɵtext(0, " Are you sure you want to stop the session ");
|
|
522
522
|
i0.ɵɵelementStart(1, "strong");
|
|
523
523
|
i0.ɵɵtext(2);
|
|
524
524
|
i0.ɵɵelementEnd();
|
|
525
525
|
i0.ɵɵtext(3, "? ");
|
|
526
|
-
i0.ɵɵelementStart(4, "span",
|
|
526
|
+
i0.ɵɵelementStart(4, "span", 128);
|
|
527
527
|
i0.ɵɵtext(5);
|
|
528
528
|
i0.ɵɵelementEnd();
|
|
529
529
|
} if (rf & 2) {
|
|
@@ -533,45 +533,45 @@ function SqlLoggingComponent_Conditional_10_Conditional_10_Template(rf, ctx) { i
|
|
|
533
533
|
i0.ɵɵadvance(3);
|
|
534
534
|
i0.ɵɵtextInterpolate1(" This session has captured ", ctx_r1.sessionToStop.statementCount, " SQL statements. ");
|
|
535
535
|
} }
|
|
536
|
-
function
|
|
537
|
-
i0.ɵɵelement(0, "i",
|
|
536
|
+
function SqlLoggingComponent_Conditional_9_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
537
|
+
i0.ɵɵelement(0, "i", 117);
|
|
538
538
|
i0.ɵɵtext(1, " Stopping... ");
|
|
539
539
|
} }
|
|
540
|
-
function
|
|
540
|
+
function SqlLoggingComponent_Conditional_9_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
541
541
|
i0.ɵɵtext(0, " Stop All Sessions ");
|
|
542
542
|
} }
|
|
543
|
-
function
|
|
543
|
+
function SqlLoggingComponent_Conditional_9_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
544
544
|
i0.ɵɵtext(0, " Stop Session ");
|
|
545
545
|
} }
|
|
546
|
-
function
|
|
547
|
-
i0.ɵɵelement(0, "i",
|
|
548
|
-
i0.ɵɵconditionalCreate(1,
|
|
546
|
+
function SqlLoggingComponent_Conditional_9_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
547
|
+
i0.ɵɵelement(0, "i", 53);
|
|
548
|
+
i0.ɵɵconditionalCreate(1, SqlLoggingComponent_Conditional_9_Conditional_14_Conditional_1_Template, 1, 0)(2, SqlLoggingComponent_Conditional_9_Conditional_14_Conditional_2_Template, 1, 0);
|
|
549
549
|
} if (rf & 2) {
|
|
550
550
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
551
551
|
i0.ɵɵadvance();
|
|
552
552
|
i0.ɵɵconditional(ctx_r1.isStoppingAll ? 1 : 2);
|
|
553
553
|
} }
|
|
554
|
-
function
|
|
554
|
+
function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
555
555
|
const _r14 = i0.ɵɵgetCurrentView();
|
|
556
|
-
i0.ɵɵelementStart(0, "div",
|
|
557
|
-
i0.ɵɵlistener("click", function
|
|
558
|
-
i0.ɵɵelementStart(1, "div",
|
|
559
|
-
i0.ɵɵlistener("click", function
|
|
560
|
-
i0.ɵɵelementStart(2, "div",
|
|
561
|
-
i0.ɵɵelement(3, "i",
|
|
562
|
-
i0.ɵɵelementEnd();
|
|
563
|
-
i0.ɵɵelementStart(4, "div",
|
|
564
|
-
i0.ɵɵconditionalCreate(6,
|
|
565
|
-
i0.ɵɵelementEnd();
|
|
566
|
-
i0.ɵɵelementStart(8, "p",
|
|
567
|
-
i0.ɵɵconditionalCreate(9,
|
|
556
|
+
i0.ɵɵelementStart(0, "div", 118);
|
|
557
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelStopConfirm()); });
|
|
558
|
+
i0.ɵɵelementStart(1, "div", 119);
|
|
559
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r14); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
560
|
+
i0.ɵɵelementStart(2, "div", 120);
|
|
561
|
+
i0.ɵɵelement(3, "i", 121);
|
|
562
|
+
i0.ɵɵelementEnd();
|
|
563
|
+
i0.ɵɵelementStart(4, "div", 122)(5, "h3", 123);
|
|
564
|
+
i0.ɵɵconditionalCreate(6, SqlLoggingComponent_Conditional_9_Conditional_6_Template, 1, 0)(7, SqlLoggingComponent_Conditional_9_Conditional_7_Template, 1, 0);
|
|
565
|
+
i0.ɵɵelementEnd();
|
|
566
|
+
i0.ɵɵelementStart(8, "p", 124);
|
|
567
|
+
i0.ɵɵconditionalCreate(9, SqlLoggingComponent_Conditional_9_Conditional_9_Template, 4, 1)(10, SqlLoggingComponent_Conditional_9_Conditional_10_Template, 6, 2);
|
|
568
568
|
i0.ɵɵelementEnd()();
|
|
569
|
-
i0.ɵɵelementStart(11, "div",
|
|
570
|
-
i0.ɵɵlistener("click", function
|
|
571
|
-
i0.ɵɵconditionalCreate(13,
|
|
569
|
+
i0.ɵɵelementStart(11, "div", 125)(12, "button", 126);
|
|
570
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmStopSession()); });
|
|
571
|
+
i0.ɵɵconditionalCreate(13, SqlLoggingComponent_Conditional_9_Conditional_13_Template, 2, 0)(14, SqlLoggingComponent_Conditional_9_Conditional_14_Template, 3, 1);
|
|
572
572
|
i0.ɵɵelementEnd();
|
|
573
|
-
i0.ɵɵelementStart(15, "button",
|
|
574
|
-
i0.ɵɵlistener("click", function
|
|
573
|
+
i0.ɵɵelementStart(15, "button", 127);
|
|
574
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelStopConfirm()); });
|
|
575
575
|
i0.ɵɵtext(16, "Cancel");
|
|
576
576
|
i0.ɵɵelementEnd()()()();
|
|
577
577
|
} if (rf & 2) {
|
|
@@ -1245,38 +1245,35 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
1245
1245
|
static ɵfac = function SqlLoggingComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SqlLoggingComponent)(i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
1246
1246
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SqlLoggingComponent, selectors: [["mj-sql-logging"]], hostBindings: function SqlLoggingComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1247
1247
|
i0.ɵɵlistener("keydown.escape", function SqlLoggingComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, i0.ɵɵresolveDocument);
|
|
1248
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
1249
|
-
i0.ɵɵelementStart(0, "
|
|
1250
|
-
i0.ɵɵlistener("
|
|
1251
|
-
i0.ɵɵelement(3, "i", 3);
|
|
1252
|
-
i0.ɵɵtext(4, " Refresh ");
|
|
1248
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 10, vars: 7, consts: [["Role", "region", "AriaLabel", "SQL logging actions", "Title", "SQL Logging", "Subtitle", "Capture and download SQL statements executed by the API"], ["actions", ""], [3, "Clicked", "Loading"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "disabled"], [1, "stats-toggle-container"], ["role", "status", "aria-live", "polite", "aria-busy", "true", 1, "loading-container"], [1, "content-area"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "start-session-dialog-title", 1, "modal-backdrop"], ["role", "alertdialog", "aria-modal", "true", "aria-labelledby", "stop-dialog-title", "aria-describedby", "stop-dialog-desc", 1, "modal-backdrop"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-play"], ["aria-controls", "stats-grid-content", 1, "stats-toggle-button", 3, "click"], [1, "stats-toggle-left"], [1, "stats-toggle-icon"], ["aria-hidden", "true", 1, "fa-solid", "fa-chart-line"], [1, "stats-toggle-text"], [1, "stats-toggle-title"], [1, "stats-toggle-subtitle"], ["aria-hidden", "true", 1, "fa-solid", "fa-chevron-down", "stats-toggle-arrow"], ["id", "stats-grid-content", "role", "region", "aria-label", "SQL logging statistics", 1, "stats-grid"], [1, "stat-card"], [1, "stat-icon", "stat-icon-status"], ["aria-hidden", "true", 1, "fa-solid", "fa-power-off"], [1, "stat-content"], [1, "stat-value"], [1, "stat-label"], [1, "stat-icon", "stat-icon-active"], ["aria-hidden", "true", 1, "fa-solid", "fa-play-circle"], [1, "stat-icon", "stat-icon-limit"], ["aria-hidden", "true", 1, "fa-solid", "fa-gauge-high"], [1, "stat-icon", "stat-icon-total"], ["aria-hidden", "true", 1, "fa-solid", "fa-database"], ["text", "Loading SQL logging configuration...", "size", "medium"], ["role", "alert", 1, "empty-state"], ["role", "status", 1, "empty-state"], [1, "sessions-layout"], ["aria-hidden", "true", 1, "fa-solid", "fa-lock", "empty-icon"], [1, "empty-text"], [1, "empty-subtext"], ["mjButton", "", "variant", "secondary", "size", "md", "aria-label", "Refresh user permissions", 2, "margin-top", "1rem", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-sync"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "empty-icon", "warning"], [1, "info-box"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-code", "empty-icon"], ["mjButton", "", "variant", "primary", "size", "md", "aria-label", "Start a new SQL logging session", 2, "margin-top", "1rem", 3, "click"], ["role", "region", "aria-label", "Active sessions list", 1, "sessions-panel"], [1, "panel-header"], [1, "panel-title"], ["mjButton", "", "variant", "danger", "size", "sm", "aria-label", "Stop all active sessions", 3, "disabled"], ["role", "list", "aria-label", "SQL logging sessions", 1, "sessions-list"], ["role", "listitem", "tabindex", "0", 1, "session-card", 3, "selected"], ["role", "region", "aria-label", "SQL log viewer", 1, "log-viewer-panel"], ["mjButton", "", "variant", "danger", "size", "sm", "aria-label", "Stop all active sessions", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-stop"], ["role", "listitem", "tabindex", "0", 1, "session-card", 3, "click", "keydown.enter", "keydown.space"], [1, "session-header"], [1, "session-info"], [1, "session-title"], [1, "session-meta"], [1, "meta-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock"], ["mjButton", "", "variant", "danger", "size", "sm", 3, "click"], [1, "session-badges"], [1, "badge", "badge-user"], [1, "badge", "badge-migration"], [1, "badge", "badge-type"], ["aria-hidden", "true", 1, "fa-solid", "fa-user"], ["aria-hidden", "true", 1, "fa-solid", "fa-code-branch"], [1, "panel-actions"], [1, "checkbox-label"], ["type", "checkbox", "aria-label", "Enable auto-refresh", 3, "ngModelChange", "ngModel"], ["mjButton", "", "variant", "flat", "size", "sm", "aria-label", "Refresh log content", 3, "click"], ["mjButton", "", "variant", "flat", "size", "sm", 3, "click"], ["aria-hidden", "true", 1, "fa-solid"], [1, "log-content"], ["aria-label", "SQL log content", 2, "height", "100%", 3, "value", "readonly", "disabled", "language", "setup", "lineWrapping", "highlightWhitespace"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-left", "empty-icon"], ["role", "dialog", "aria-modal", "true", "aria-labelledby", "start-session-dialog-title", 1, "modal-backdrop", 3, "click"], [1, "modal-dialog", "modal-large", 3, "click"], [1, "modal-header"], ["id", "start-session-dialog-title", 1, "modal-title"], [1, "modal-header-actions"], ["type", "button", 1, "modal-action-btn", 3, "click"], ["aria-label", "Close dialog", 1, "modal-close", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], [1, "modal-body"], [1, "form-group"], ["for", "session-name", 1, "form-label"], ["type", "text", "id", "session-name", "placeholder", "Enter a descriptive name for this session", "aria-describedby", "session-name-hint", 1, "form-input", 3, "ngModelChange", "ngModel"], ["id", "session-name-hint", 1, "form-hint"], ["for", "file-name", 1, "form-label"], ["type", "text", "id", "file-name", "placeholder", "sql-log-2024-01-01.sql", "aria-describedby", "file-name-hint", 1, "form-input", 3, "ngModelChange", "ngModel"], ["id", "file-name-hint", 1, "form-hint"], ["for", "statement-types", 1, "form-label"], ["id", "statement-types", "aria-describedby", "statement-types-hint", 1, "form-select", 3, "ngModelChange", "ngModel"], [3, "value"], ["id", "statement-types-hint", 1, "form-hint"], ["role", "group", "aria-label", "Session options", 1, "form-checkboxes"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], [1, "form-section"], [1, "form-section-title"], ["aria-hidden", "true", 1, "fa-solid", "fa-filter"], ["for", "filter-type", 1, "form-label"], ["id", "filter-type", "aria-describedby", "filter-type-hint", 1, "form-select", 3, "ngModelChange", "ngModel"], ["id", "filter-type-hint", 1, "form-hint"], ["for", "filter-patterns", 1, "form-label"], ["id", "filter-patterns", "rows", "4", "placeholder", "Examples:\n*AIPrompt*\n/spCreate.*Run/i\nSELECT * FROM vwMetadata", "aria-describedby", "filter-patterns-hint", 1, "form-textarea", 3, "ngModelChange", "ngModel"], ["id", "filter-patterns-hint", 1, "form-hint"], ["aria-hidden", "true", 1, "fa-solid", "fa-cog"], [1, "form-checkboxes"], [1, "form-hint", 2, "margin-left", "1.75rem"], [1, "modal-footer"], ["mjButton", "", "variant", "primary", "size", "md", "aria-label", "Start the SQL logging session", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "md", "aria-label", "Cancel and close dialog", 3, "click"], ["for", "default-schema", 1, "form-label"], ["type", "text", "id", "default-schema", "placeholder", "__mj", "aria-describedby", "default-schema-hint", 1, "form-input", 3, "ngModelChange", "ngModel"], ["id", "default-schema-hint", 1, "form-hint"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["role", "alertdialog", "aria-modal", "true", "aria-labelledby", "stop-dialog-title", "aria-describedby", "stop-dialog-desc", 1, "modal-backdrop", 3, "click"], [1, "confirm-dialog", 3, "click"], [1, "confirm-dialog-icon"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle"], [1, "confirm-dialog-content"], ["id", "stop-dialog-title", 1, "confirm-dialog-title"], ["id", "stop-dialog-desc", 1, "confirm-dialog-message"], [1, "confirm-dialog-actions"], ["mjButton", "", "variant", "danger", "size", "md", 3, "click", "disabled"], ["mjButton", "", "variant", "secondary", "size", "md", "aria-label", "Cancel and keep sessions running", 3, "click", "disabled"], [1, "confirm-dialog-details"]], template: function SqlLoggingComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1249
|
+
i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "mj-refresh-button", 2);
|
|
1250
|
+
i0.ɵɵlistener("Clicked", function SqlLoggingComponent_Template_mj_refresh_button_Clicked_2_listener() { return ctx.loadActiveSessions(); });
|
|
1253
1251
|
i0.ɵɵelementEnd();
|
|
1254
|
-
i0.ɵɵconditionalCreate(
|
|
1255
|
-
i0.ɵɵelementEnd();
|
|
1256
|
-
i0.ɵɵ
|
|
1257
|
-
i0.ɵɵconditionalCreate(
|
|
1258
|
-
i0.ɵɵconditionalCreate(
|
|
1259
|
-
i0.ɵɵconditionalCreate(
|
|
1260
|
-
i0.ɵɵconditionalCreate(
|
|
1252
|
+
i0.ɵɵconditionalCreate(3, SqlLoggingComponent_Conditional_3_Template, 3, 2, "button", 3);
|
|
1253
|
+
i0.ɵɵelementEnd()();
|
|
1254
|
+
i0.ɵɵelementStart(4, "mj-page-body-interior");
|
|
1255
|
+
i0.ɵɵconditionalCreate(5, SqlLoggingComponent_Conditional_5_Template, 44, 13, "div", 4);
|
|
1256
|
+
i0.ɵɵconditionalCreate(6, SqlLoggingComponent_Conditional_6_Template, 2, 0, "div", 5);
|
|
1257
|
+
i0.ɵɵconditionalCreate(7, SqlLoggingComponent_Conditional_7_Template, 5, 1, "div", 6);
|
|
1258
|
+
i0.ɵɵconditionalCreate(8, SqlLoggingComponent_Conditional_8_Template, 77, 19, "div", 7);
|
|
1259
|
+
i0.ɵɵconditionalCreate(9, SqlLoggingComponent_Conditional_9_Template, 17, 6, "div", 8);
|
|
1261
1260
|
i0.ɵɵelementEnd();
|
|
1262
1261
|
} if (rf & 2) {
|
|
1263
1262
|
i0.ɵɵadvance(2);
|
|
1264
|
-
i0.ɵɵproperty("
|
|
1263
|
+
i0.ɵɵproperty("Loading", ctx.loading);
|
|
1265
1264
|
i0.ɵɵadvance();
|
|
1266
|
-
i0.ɵɵ
|
|
1265
|
+
i0.ɵɵconditional(ctx.isOwner && ctx.configEnabled ? 3 : -1);
|
|
1267
1266
|
i0.ɵɵadvance(2);
|
|
1268
1267
|
i0.ɵɵconditional(ctx.isOwner && ctx.configEnabled ? 5 : -1);
|
|
1269
1268
|
i0.ɵɵadvance();
|
|
1270
|
-
i0.ɵɵconditional(ctx.
|
|
1271
|
-
i0.ɵɵadvance();
|
|
1272
|
-
i0.ɵɵconditional(ctx.loading && !ctx.activeSessions.length ? 7 : -1);
|
|
1269
|
+
i0.ɵɵconditional(ctx.loading && !ctx.activeSessions.length ? 6 : -1);
|
|
1273
1270
|
i0.ɵɵadvance();
|
|
1274
|
-
i0.ɵɵconditional(!ctx.loading || ctx.activeSessions.length > 0 ?
|
|
1271
|
+
i0.ɵɵconditional(!ctx.loading || ctx.activeSessions.length > 0 ? 7 : -1);
|
|
1275
1272
|
i0.ɵɵadvance();
|
|
1276
|
-
i0.ɵɵconditional(ctx.showStartSessionDialog ?
|
|
1273
|
+
i0.ɵɵconditional(ctx.showStartSessionDialog ? 8 : -1);
|
|
1277
1274
|
i0.ɵɵadvance();
|
|
1278
|
-
i0.ɵɵconditional(ctx.showStopConfirmDialog ?
|
|
1279
|
-
} }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.LoadingComponent, i5.MJButtonDirective], styles: ["\n\n\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n\n.sticky-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\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(--mj-bg-surface-sunken);\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@media (min-width: 1440px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 2rem 2.5rem;\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(--mj-bg-page);\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 padding: 0.5rem 0.75rem;\n min-height: 40px;\n gap: 0;\n border-radius: var(--mj-radius-full);\n }\n\n .mj-btn-icon-mobile[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n}\n\n\n\n\n\n.mj-grid-4[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 1rem 0.75rem 1rem;\n background: var(--mj-bg-page);\n}\n\n@media (min-width: 768px) {\n .mj-grid-4[_ngcontent-%COMP%] {\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(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\n cursor: default;\n pointer-events: none;\n}\n\n@media (min-width: 768px) {\n .mj-card[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n\n\n\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .stat-icon[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--mj-color-accent-300);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-active[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n color: var(--mj-status-success);\n}\n\n\n\n\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--mj-text-primary);\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(--mj-text-secondary);\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(--mj-bg-surface-card);\n margin: 0 1rem 0.75rem 1rem;\n padding: 0.75rem;\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\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.mj-filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.mj-filter-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-full);\n padding: 4px;\n gap: 2px;\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n border-radius: var(--mj-radius-full);\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] .mj-btn-primary[_ngcontent-%COMP%] {\n background-color: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n\n\n\n\n.mj-search[_ngcontent-%COMP%] {\n position: relative;\n flex: 1;\n min-width: 200px;\n}\n\n@media (min-width: 640px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 280px;\n }\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 400px;\n max-width: 600px;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 500px;\n max-width: 800px;\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(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-icon[_ngcontent-%COMP%] {\n left: 1.25rem;\n font-size: 1.125rem;\n }\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(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem 1rem 3.25rem;\n font-size: 1.0625rem;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 1.125rem 1.5rem 1.125rem 3.5rem;\n }\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--mj-bg-page);\n}\n\n.mj-search[_ngcontent-%COMP%]:focus-within .mj-search-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\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(--mj-bg-page);\n border-radius: var(--mj-radius-xl);\n box-shadow: var(--mj-shadow-sm);\n padding: 1rem;\n border: 1px solid var(--mj-border-default);\n}\n\n@media (min-width: 768px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n\n\n\n\n.expand-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s ease;\n border-radius: var(--mj-radius-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(--mj-brand-primary);\n color: var(--mj-brand-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\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(--mj-radius-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(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success);\n}\n\n.status-badge.status-inactive[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error);\n}\n\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.625rem;\n}\n\n\n\n\n\n.mobile-actions-bar[_ngcontent-%COMP%] {\n display: none;\n}\n\n.mobile-action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\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(--mj-border-default);\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(--mj-text-primary);\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(--mj-text-secondary);\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(--mj-status-error);\n margin-bottom: 1rem;\n}\n\n.error-container[_ngcontent-%COMP%] .error-message[_ngcontent-%COMP%] {\n font-size: 1.0625rem;\n color: var(--mj-text-primary);\n margin: 0 0 1.5rem 0;\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 cubic-bezier(0, 0, 0.2, 1);\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 500px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\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(--mj-border-default);\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(--mj-text-primary);\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(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-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(--mj-text-primary);\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-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(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\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-footer[_ngcontent-%COMP%] {\n padding: 1rem;\n flex-direction: column;\n }\n\n .modal-footer[_ngcontent-%COMP%] .mj-btn[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n\n\n\n\n.mj-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n font-size: 0.875rem;\n font-weight: 600;\n border: none;\n border-radius: var(--mj-radius-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(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mj-btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.mj-btn-primary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-color-brand-400);\n transform: scale(0.98);\n}\n\n\n\n.mj-btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-color-neutral-400);\n}\n\n.mj-btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.mj-btn-secondary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n border-color: var(--mj-color-brand-700);\n}\n\n\n\n.mj-btn-ghost[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-text-secondary);\n}\n\n.mj-btn-ghost[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.mj-btn-ghost[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n}\n\n\n\n.mj-btn-danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mj-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-color-error-300);\n box-shadow: var(--mj-shadow-md);\n}\n\n.mj-btn-danger[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-color-error-200);\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-icon-only[_ngcontent-%COMP%] {\n padding: 0.625rem;\n min-width: 44px;\n min-height: 44px;\n}\n\n\n\n.mj-btn-icon-mobile[_ngcontent-%COMP%] {\n gap: 0.5rem;\n}\n\n.mj-btn-icon-mobile[_ngcontent-%COMP%] .btn-text[_ngcontent-%COMP%] {\n display: inline;\n}\n\n\n\n.mj-btn-ghost.mj-btn-danger[_ngcontent-%COMP%] {\n background: transparent;\n color: var(--mj-status-error);\n box-shadow: none;\n}\n\n.mj-btn-ghost.mj-btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n}\n\n\n\n\n\n.filter-button[_ngcontent-%COMP%] {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n border-radius: var(--mj-radius-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n min-width: 44px;\n}\n\n.filter-button[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.filter-button[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.filter-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n\n\n\n\n.filter-modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.filter-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl) var(--mj-radius-2xl) 0 0;\n box-shadow: var(--mj-shadow-2xl);\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.filter-modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.filter-modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.filter-modal-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 1.375rem;\n}\n\n.filter-modal-close[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.filter-modal-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.filter-modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n.filter-modal-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.filter-modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\n margin: 0;\n}\n\n\n\n.filter-options-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.filter-group-label[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.filter-group-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.filter-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.filter-option[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-option.selected[_ngcontent-%COMP%] {\n background: var(--mj-color-accent-300);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.filter-option[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%], \n.filter-option[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.filter-option-label[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 1rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.filter-option.selected[_ngcontent-%COMP%] .filter-option-label[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n\n\n\n\n.text-danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.text-warning[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.text-success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideUpFromBottom {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.mj-search-input[_ngcontent-%COMP%]:focus-visible, \nbutton[_ngcontent-%COMP%]:focus-visible, \n.mj-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-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\n\n\n\n[_nghost-%COMP%] {\n display: block;\n height: 100%;\n width: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n\n\n\n\n.sql-logging-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n width: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n position: relative;\n background: var(--mj-bg-page);\n padding: 1rem;\n}\n\n@media (min-width: 640px) {\n .sql-logging-container[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .sql-logging-container[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .sql-logging-container[_ngcontent-%COMP%] {\n padding: 2rem;\n }\n}\n\n@media (min-width: 1440px) {\n .sql-logging-container[_ngcontent-%COMP%] {\n padding: 2rem 2.5rem;\n max-width: 1920px;\n margin: 0 auto;\n }\n}\n\n\n\n\n\n.action-buttons[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n padding: 0;\n background: transparent;\n}\n\n@media (max-width: 639px) {\n .action-buttons[_ngcontent-%COMP%] {\n justify-content: center;\n }\n\n \n\n .action-buttons[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%], \n .action-buttons[_ngcontent-%COMP%] .btn-secondary[_ngcontent-%COMP%] {\n font-size: 0;\n padding: 0.75rem;\n min-width: 48px;\n min-height: 48px;\n gap: 0;\n }\n\n .action-buttons[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n .action-buttons[_ngcontent-%COMP%] .btn-secondary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n\n .stats-toggle-button[_ngcontent-%COMP%] {\n padding: 0.875rem 1rem;\n }\n\n .stats-toggle-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .stats-toggle-title[_ngcontent-%COMP%] {\n font-size: 0.9375rem;\n }\n\n .stats-toggle-subtitle[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n }\n\n .stats-toggle-arrow[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n}\n\n\n\n\n\n.btn-primary[_ngcontent-%COMP%], \n.btn-secondary[_ngcontent-%COMP%], \n.btn-danger[_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(--mj-radius-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 min-width: 44px;\n}\n\n\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-primary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-color-brand-300);\n transform: scale(0.98);\n}\n\n.btn-primary[_ngcontent-%COMP%]:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-border-strong);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-brand-primary-active);\n border-color: var(--mj-brand-primary-active);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-secondary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n\n\n.btn-danger[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-color-error-300);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-danger[_ngcontent-%COMP%]:active:not(:disabled) {\n background: var(--mj-color-error-200);\n transform: scale(0.98);\n}\n\n.btn-danger[_ngcontent-%COMP%]:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n.btn-danger.btn-small[_ngcontent-%COMP%] {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n\n\n\n\n.stats-toggle-container[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n}\n\n.stats-toggle-button[_ngcontent-%COMP%] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.stats-toggle-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n margin-bottom: 1rem;\n}\n\n.stats-toggle-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.stats-toggle-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-icon[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.stats-toggle-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.stats-toggle-title[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-title[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.stats-toggle-subtitle[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.stats-toggle-arrow[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-arrow[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n color: var(--mj-brand-primary);\n}\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n width: 100%;\n overflow: hidden;\n max-height: 0;\n opacity: 0;\n transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-grid.visible[_ngcontent-%COMP%] {\n max-height: 1000px;\n opacity: 1;\n margin-bottom: 1.5rem;\n}\n\n@media (min-width: 640px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .stats-toggle-button[_ngcontent-%COMP%] {\n display: none;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n max-height: none;\n opacity: 1;\n margin-bottom: 1.5rem;\n gap: 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(4, 1fr);\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1440px) {\n .stats-grid[_ngcontent-%COMP%] {\n gap: 2rem;\n }\n}\n\n\n\n.stat-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1.25rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\n cursor: default;\n}\n\n\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n font-size: 1.5rem;\n}\n\n@media (max-width: 639px) {\n .stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n}\n\n.stat-icon-status[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.stat-icon-active[_ngcontent-%COMP%] {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-limit[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n\n\n@media (max-width: 639px) {\n .stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n font-weight: 700;\n }\n}\n\n\n\n\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n box-shadow: none;\n}\n\n@media (min-width: 640px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n}\n\n\n\n\n\n.sessions-layout[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n min-height: 400px;\n overflow: visible;\n}\n\n@media (max-width: 767px) {\n .sessions-layout[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 1rem;\n min-height: auto;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-layout[_ngcontent-%COMP%] {\n gap: 1.25rem;\n }\n}\n\n\n\n\n\n.sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 380px;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n max-height: 600px;\n}\n\n@media (max-width: 767px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: none;\n max-height: 350px;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 320px;\n }\n}\n\n@media (min-width: 1440px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 420px;\n }\n}\n\n.panel-header[_ngcontent-%COMP%] {\n padding: 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n gap: 0.5rem;\n}\n\n@media (max-width: 639px) {\n .panel-header[_ngcontent-%COMP%] {\n padding: 0.75rem;\n flex-wrap: wrap;\n }\n}\n\n.panel-header[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex-shrink: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (max-width: 639px) {\n .panel-header[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n max-width: 50%;\n }\n}\n\n.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .panel-actions[_ngcontent-%COMP%] {\n gap: 0.25rem;\n }\n\n .panel-actions[_ngcontent-%COMP%] .checkbox-label[_ngcontent-%COMP%] {\n font-size: 0;\n gap: 0;\n min-height: 36px;\n padding: 0;\n }\n\n .panel-actions[_ngcontent-%COMP%] .checkbox-label[_ngcontent-%COMP%]::after {\n content: \"Auto\";\n font-size: 0.75rem;\n margin-left: 0.25rem;\n }\n}\n\n.sessions-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n min-height: 0;\n position: relative;\n padding: 0.75rem;\n}\n\n\n\n\n\n.session-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 1rem;\n margin-bottom: 0.75rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.session-card[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.session-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-sm);\n border-color: var(--mj-brand-primary);\n}\n\n.session-card.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-brand-accent-subtle);\n}\n\n.session-card[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.session-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.75rem;\n}\n\n.session-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.session-info[_ngcontent-%COMP%] .session-title[_ngcontent-%COMP%] {\n margin: 0 0 0.5rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.session-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n flex-wrap: wrap;\n}\n\n.session-meta[_ngcontent-%COMP%] .meta-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.session-badges[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n margin-top: 0.5rem;\n}\n\n\n\n\n\n.badge[_ngcontent-%COMP%] {\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.badge-user[_ngcontent-%COMP%] {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.badge-migration[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success);\n}\n\n.badge-type[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning);\n}\n\n\n\n\n\n.action-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.action-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-brand-on-primary);\n}\n\n\n\n\n\n.log-viewer-panel[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n min-height: 400px;\n}\n\n@media (max-width: 767px) {\n .log-viewer-panel[_ngcontent-%COMP%] {\n min-height: 350px;\n }\n}\n\n\n\n.log-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 300px;\n height: 100%;\n position: relative;\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-editor {\n height: 100%;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n font-size: 0.875rem;\n}\n\n.log-content[_ngcontent-%COMP%] .cm-scroller {\n font-family: inherit;\n}\n\n.log-content[_ngcontent-%COMP%] .cm-content {\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-gutters {\n background: var(--mj-text-primary);\n color: var(--mj-text-disabled);\n border-right: 1px solid var(--mj-text-secondary);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-activeLineGutter {\n background: var(--mj-text-primary);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-activeLine {\n background: rgba(255, 255, 255, 0.04);\n}\n\n\n\n.log-viewer-panel.expanded[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n border-radius: 0;\n margin: 0;\n max-height: none;\n height: 100vh;\n animation: _ngcontent-%COMP%_expandIn 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n.log-viewer-panel.expanded[_ngcontent-%COMP%] .panel-header[_ngcontent-%COMP%] {\n border-radius: 0;\n}\n\n.log-viewer-panel.expanded[_ngcontent-%COMP%] .log-content[_ngcontent-%COMP%] {\n max-height: calc(100vh - 60px);\n min-height: calc(100vh - 60px);\n}\n\n\n\n\n\n.empty-state[_ngcontent-%COMP%] .empty-icon.warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n max-width: 400px;\n}\n\n\n\n\n\n.info-box[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 1.5rem;\n margin-top: 1.5rem;\n text-align: left;\n max-width: 500px;\n border: 1px solid var(--mj-border-default);\n}\n\n.info-box[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.info-box[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n margin: 0;\n padding-left: 1.25rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n}\n\n.info-box[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n margin-bottom: 0.5rem;\n}\n\n.info-box[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-active);\n padding: 0.125rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.8125rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n color: var(--mj-text-primary);\n}\n\n\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n min-height: 300px;\n}\n\n.loading-text[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin-top: 1rem;\n}\n\n\n\n\n\n.modal-backdrop[_ngcontent-%COMP%] {\n background: var(--mj-bg-overlay);\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n width: 90%;\n display: flex;\n flex-direction: column;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.modal-dialog.modal-large[_ngcontent-%COMP%] {\n max-width: 700px;\n}\n\n\n\n.modal-dialog.fullscreen[_ngcontent-%COMP%] {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n@media (max-width: 639px) {\n .modal-dialog[_ngcontent-%COMP%] {\n width: 95%;\n max-height: 85vh;\n border-radius: var(--mj-radius-2xl);\n }\n\n .modal-dialog.fullscreen[_ngcontent-%COMP%] {\n border-radius: 0;\n max-height: 100vh;\n }\n}\n\n.modal-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-header[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n\n\n.modal-header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\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.modal-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.modal-action-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.modal-body[_ngcontent-%COMP%] {\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n@media (max-width: 639px) {\n .modal-body[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n justify-content: flex-end;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-footer[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n\n .modal-footer[_ngcontent-%COMP%] .btn-primary[_ngcontent-%COMP%], \n .modal-footer[_ngcontent-%COMP%] .btn-secondary[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n\n\n\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 0.5rem;\n}\n\n.form-input[_ngcontent-%COMP%], \n.form-select[_ngcontent-%COMP%], \n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n min-height: 44px;\n padding: 0.875rem 1rem;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-input[_ngcontent-%COMP%]:hover, \n.form-select[_ngcontent-%COMP%]:hover, \n.form-textarea[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.form-input[_ngcontent-%COMP%]:focus, \n.form-select[_ngcontent-%COMP%]:focus, \n.form-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-surface);\n}\n\n.form-input[_ngcontent-%COMP%]::placeholder, \n.form-textarea[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-secondary);\n opacity: 0.7;\n}\n\n.form-select[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin-top: 0.375rem;\n}\n\n.form-checkboxes[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n cursor: pointer;\n min-height: 44px;\n padding: 0.25rem 0;\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n\n\n.form-section[_ngcontent-%COMP%] {\n margin-top: 1.5rem;\n padding: 1.25rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface-sunken);\n}\n\n.form-section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 1.125rem;\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n resize: vertical;\n min-height: 100px;\n}\n\n\n\n\n\n.confirm-dialog[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 420px;\n width: 90%;\n padding: 2rem;\n text-align: center;\n animation: _ngcontent-%COMP%_dialogBounce 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n@media (max-width: 639px) {\n .confirm-dialog[_ngcontent-%COMP%] {\n padding: 1.5rem;\n border-radius: var(--mj-radius-2xl);\n }\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: var(--mj-status-warning-bg);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n color: var(--mj-status-warning-text);\n}\n\n.confirm-dialog-content[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n}\n\n.confirm-dialog-title[_ngcontent-%COMP%] {\n margin: 0 0 0.75rem 0;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n line-height: 1.6;\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.confirm-dialog-details[_ngcontent-%COMP%] {\n display: block;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n.confirm-dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: center;\n}\n\n@media (max-width: 639px) {\n .confirm-dialog-actions[_ngcontent-%COMP%] {\n flex-direction: column-reverse;\n }\n\n .confirm-dialog-actions[_ngcontent-%COMP%] .btn-danger[_ngcontent-%COMP%], \n .confirm-dialog-actions[_ngcontent-%COMP%] .btn-secondary[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n.confirm-dialog-actions[_ngcontent-%COMP%] .btn-danger[_ngcontent-%COMP%] {\n min-width: 140px;\n}\n\n.confirm-dialog-actions[_ngcontent-%COMP%] .btn-secondary[_ngcontent-%COMP%] {\n min-width: 100px;\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_expandIn {\n from {\n transform: scale(0.95);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_dialogBounce {\n 0% {\n transform: scale(0.9) translateY(10px);\n opacity: 0;\n }\n 70% {\n transform: scale(1.02) translateY(-5px);\n }\n 100% {\n transform: scale(1) translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.sr-only[_ngcontent-%COMP%] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}"] });
|
|
1275
|
+
i0.ɵɵconditional(ctx.showStopConfirmDialog ? 9 : -1);
|
|
1276
|
+
} }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.LoadingComponent, i5.MJButtonDirective, i5.MJPageHeaderInteriorComponent, i5.MJPageBodyInteriorComponent, i5.MJRefreshButtonComponent], styles: ["\n\n\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n\n.sticky-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\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(--mj-bg-surface-sunken);\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@media (min-width: 1440px) {\n .scrollable-content[_ngcontent-%COMP%] {\n padding: 2rem 2.5rem;\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(--mj-bg-page);\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\n\n\n\n\n.mj-grid-4[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 1rem 0.75rem 1rem;\n background: var(--mj-bg-page);\n}\n\n@media (min-width: 768px) {\n .mj-grid-4[_ngcontent-%COMP%] {\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(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\n cursor: default;\n pointer-events: none;\n}\n\n@media (min-width: 768px) {\n .mj-card[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n\n\n\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .stat-icon[_ngcontent-%COMP%] {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--mj-color-accent-300);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-active[_ngcontent-%COMP%] {\n background: var(--mj-color-success-100);\n color: var(--mj-status-success);\n}\n\n\n\n\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--mj-text-primary);\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(--mj-text-secondary);\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(--mj-bg-surface-card);\n margin: 0 1rem 0.75rem 1rem;\n padding: 0.75rem;\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\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.mj-filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.mj-filter-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.mj-filter-buttons[_ngcontent-%COMP%] {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-full);\n padding: 4px;\n gap: 2px;\n}\n\n\n\n\n\n.mj-search[_ngcontent-%COMP%] {\n position: relative;\n flex: 1;\n min-width: 200px;\n}\n\n@media (min-width: 640px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 280px;\n }\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 400px;\n max-width: 600px;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search[_ngcontent-%COMP%] {\n min-width: 500px;\n max-width: 800px;\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(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-icon[_ngcontent-%COMP%] {\n left: 1.25rem;\n font-size: 1.125rem;\n }\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(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n}\n\n@media (min-width: 1024px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem 1rem 3.25rem;\n font-size: 1.0625rem;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%] {\n padding: 1.125rem 1.5rem 1.125rem 3.5rem;\n }\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.mj-search[_ngcontent-%COMP%] .mj-search-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--mj-bg-page);\n}\n\n.mj-search[_ngcontent-%COMP%]:focus-within .mj-search-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\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(--mj-bg-page);\n border-radius: var(--mj-radius-xl);\n box-shadow: var(--mj-shadow-sm);\n padding: 1rem;\n border: 1px solid var(--mj-border-default);\n}\n\n@media (min-width: 768px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.5rem;\n }\n}\n\n\n\n\n\n.expand-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s ease;\n border-radius: var(--mj-radius-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(--mj-brand-primary);\n color: var(--mj-brand-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\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(--mj-radius-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(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success);\n}\n\n.status-badge.status-inactive[_ngcontent-%COMP%] {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error);\n}\n\n.status-badge[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.625rem;\n}\n\n\n\n\n\n.mobile-actions-bar[_ngcontent-%COMP%] {\n display: none;\n}\n\n.mobile-action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\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(--mj-border-default);\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(--mj-text-primary);\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(--mj-text-secondary);\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(--mj-status-error);\n margin-bottom: 1rem;\n}\n\n.error-container[_ngcontent-%COMP%] .error-message[_ngcontent-%COMP%] {\n font-size: 1.0625rem;\n color: var(--mj-text-primary);\n margin: 0 0 1.5rem 0;\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 cubic-bezier(0, 0, 0.2, 1);\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 500px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\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(--mj-border-default);\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(--mj-text-primary);\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(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-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(--mj-text-primary);\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-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(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\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-footer[_ngcontent-%COMP%] {\n padding: 1rem;\n flex-direction: column;\n }\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n.filter-button[_ngcontent-%COMP%] {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n border-radius: var(--mj-radius-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n min-width: 44px;\n}\n\n.filter-button[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.filter-button[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.filter-button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n\n\n\n\n.filter-modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.filter-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl) var(--mj-radius-2xl) 0 0;\n box-shadow: var(--mj-shadow-2xl);\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.filter-modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.filter-modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.filter-modal-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 1.375rem;\n}\n\n.filter-modal-close[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.filter-modal-close[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.filter-modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n.filter-modal-footer[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.filter-modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n flex: 1;\n margin: 0;\n}\n\n\n\n.filter-options-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.filter-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.filter-group-label[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.filter-group-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.filter-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.filter-option[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-option.selected[_ngcontent-%COMP%] {\n background: var(--mj-color-accent-300);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.filter-option[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%], \n.filter-option[_ngcontent-%COMP%] input[type=\"radio\"][_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.filter-option-label[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 1rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.filter-option.selected[_ngcontent-%COMP%] .filter-option-label[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n\n\n\n\n.text-danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.text-warning[_ngcontent-%COMP%] {\n color: var(--mj-color-warning-500);\n}\n\n.text-success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideUpFromBottom {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.mj-search-input[_ngcontent-%COMP%]:focus-visible, \nbutton[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-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\n\n\n\n\n\n\n\n\n\n\n@media (max-width: 639px) {\n .stats-toggle-button[_ngcontent-%COMP%] {\n padding: 0.875rem 1rem;\n }\n\n .stats-toggle-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .stats-toggle-title[_ngcontent-%COMP%] {\n font-size: 0.9375rem;\n }\n\n .stats-toggle-subtitle[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n }\n\n .stats-toggle-arrow[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n }\n}\n\n\n\n\n\n.stats-toggle-container[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n}\n\n.stats-toggle-button[_ngcontent-%COMP%] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.stats-toggle-button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n margin-bottom: 1rem;\n}\n\n.stats-toggle-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.stats-toggle-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-icon[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.stats-toggle-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.stats-toggle-title[_ngcontent-%COMP%] {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-title[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.stats-toggle-subtitle[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.stats-toggle-arrow[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-arrow[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n color: var(--mj-brand-primary);\n}\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n width: 100%;\n overflow: hidden;\n max-height: 0;\n opacity: 0;\n transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-grid.visible[_ngcontent-%COMP%] {\n max-height: 1000px;\n opacity: 1;\n margin-bottom: 1.5rem;\n}\n\n@media (min-width: 640px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .stats-toggle-button[_ngcontent-%COMP%] {\n display: none;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n max-height: none;\n opacity: 1;\n margin-bottom: 1.5rem;\n gap: 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(4, 1fr);\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1440px) {\n .stats-grid[_ngcontent-%COMP%] {\n gap: 2rem;\n }\n}\n\n\n\n.stat-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1.25rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\n cursor: default;\n}\n\n\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n font-size: 1.5rem;\n}\n\n@media (max-width: 639px) {\n .stat-icon[_ngcontent-%COMP%] {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n}\n\n.stat-icon-status[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.stat-icon-active[_ngcontent-%COMP%] {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-limit[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n\n\n@media (max-width: 639px) {\n .stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.5rem;\n font-weight: 700;\n }\n}\n\n\n\n\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n box-shadow: none;\n}\n\n@media (min-width: 640px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n}\n\n\n\n\n\n.sessions-layout[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n min-height: 400px;\n overflow: visible;\n}\n\n@media (max-width: 767px) {\n .sessions-layout[_ngcontent-%COMP%] {\n flex-direction: column;\n gap: 1rem;\n min-height: auto;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-layout[_ngcontent-%COMP%] {\n gap: 1.25rem;\n }\n}\n\n\n\n\n\n.sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 380px;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n max-height: 600px;\n}\n\n@media (max-width: 767px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: none;\n max-height: 350px;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 320px;\n }\n}\n\n@media (min-width: 1440px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 420px;\n }\n}\n\n.panel-header[_ngcontent-%COMP%] {\n padding: 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n gap: 0.5rem;\n}\n\n@media (max-width: 639px) {\n .panel-header[_ngcontent-%COMP%] {\n padding: 0.75rem;\n flex-wrap: wrap;\n }\n}\n\n.panel-header[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex-shrink: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (max-width: 639px) {\n .panel-header[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n max-width: 50%;\n }\n}\n\n.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .panel-actions[_ngcontent-%COMP%] {\n gap: 0.25rem;\n }\n\n .panel-actions[_ngcontent-%COMP%] .checkbox-label[_ngcontent-%COMP%] {\n font-size: 0;\n gap: 0;\n min-height: 36px;\n padding: 0;\n }\n\n .panel-actions[_ngcontent-%COMP%] .checkbox-label[_ngcontent-%COMP%]::after {\n content: \"Auto\";\n font-size: 0.75rem;\n margin-left: 0.25rem;\n }\n}\n\n.sessions-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n min-height: 0;\n position: relative;\n padding: 0.75rem;\n}\n\n\n\n\n\n.session-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 1rem;\n margin-bottom: 0.75rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.session-card[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.session-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-sm);\n border-color: var(--mj-brand-primary);\n}\n\n.session-card.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-brand-accent-subtle);\n}\n\n.session-card[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.session-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.75rem;\n}\n\n.session-info[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.session-info[_ngcontent-%COMP%] .session-title[_ngcontent-%COMP%] {\n margin: 0 0 0.5rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.session-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n flex-wrap: wrap;\n}\n\n.session-meta[_ngcontent-%COMP%] .meta-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.session-badges[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n margin-top: 0.5rem;\n}\n\n\n\n\n\n.badge[_ngcontent-%COMP%] {\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.badge-user[_ngcontent-%COMP%] {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.badge-migration[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success);\n}\n\n.badge-type[_ngcontent-%COMP%] {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning);\n}\n\n\n\n\n\n.action-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.action-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n background: var(--mj-status-error);\n color: var(--mj-brand-on-primary);\n}\n\n\n\n\n\n.log-viewer-panel[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n min-height: 400px;\n}\n\n@media (max-width: 767px) {\n .log-viewer-panel[_ngcontent-%COMP%] {\n min-height: 350px;\n }\n}\n\n\n\n.log-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 300px;\n height: 100%;\n position: relative;\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-editor {\n height: 100%;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n font-size: 0.875rem;\n}\n\n.log-content[_ngcontent-%COMP%] .cm-scroller {\n font-family: inherit;\n}\n\n.log-content[_ngcontent-%COMP%] .cm-content {\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-gutters {\n background: var(--mj-text-primary);\n color: var(--mj-text-disabled);\n border-right: 1px solid var(--mj-text-secondary);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-activeLineGutter {\n background: var(--mj-text-primary);\n}\n\n.log-content[_ngcontent-%COMP%] .cm-activeLine {\n background: rgba(255, 255, 255, 0.04);\n}\n\n\n\n.log-viewer-panel.expanded[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n border-radius: 0;\n margin: 0;\n max-height: none;\n height: 100vh;\n animation: _ngcontent-%COMP%_expandIn 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n.log-viewer-panel.expanded[_ngcontent-%COMP%] .panel-header[_ngcontent-%COMP%] {\n border-radius: 0;\n}\n\n.log-viewer-panel.expanded[_ngcontent-%COMP%] .log-content[_ngcontent-%COMP%] {\n max-height: calc(100vh - 60px);\n min-height: calc(100vh - 60px);\n}\n\n\n\n\n\n.empty-state[_ngcontent-%COMP%] .empty-icon.warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n max-width: 400px;\n}\n\n\n\n\n\n.info-box[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 1.5rem;\n margin-top: 1.5rem;\n text-align: left;\n max-width: 500px;\n border: 1px solid var(--mj-border-default);\n}\n\n.info-box[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.info-box[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n margin: 0;\n padding-left: 1.25rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n}\n\n.info-box[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n margin-bottom: 0.5rem;\n}\n\n.info-box[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-active);\n padding: 0.125rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.8125rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n color: var(--mj-text-primary);\n}\n\n\n\n\n\n.loading-container[_ngcontent-%COMP%] {\n min-height: 300px;\n}\n\n.loading-text[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin-top: 1rem;\n}\n\n\n\n\n\n.modal-backdrop[_ngcontent-%COMP%] {\n background: var(--mj-bg-overlay);\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n width: 90%;\n display: flex;\n flex-direction: column;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.modal-dialog.modal-large[_ngcontent-%COMP%] {\n max-width: 700px;\n}\n\n\n\n.modal-dialog.fullscreen[_ngcontent-%COMP%] {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n@media (max-width: 639px) {\n .modal-dialog[_ngcontent-%COMP%] {\n width: 95%;\n max-height: 85vh;\n border-radius: var(--mj-radius-2xl);\n }\n\n .modal-dialog.fullscreen[_ngcontent-%COMP%] {\n border-radius: 0;\n max-height: 100vh;\n }\n}\n\n.modal-header[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-header[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n\n\n.modal-header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\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.modal-action-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.modal-action-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.modal-body[_ngcontent-%COMP%] {\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n@media (max-width: 639px) {\n .modal-body[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n justify-content: flex-end;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-footer[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n\n \n\n .modal-footer[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n\n\n\n\n.form-group[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n}\n\n.form-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 0.5rem;\n}\n\n.form-input[_ngcontent-%COMP%], \n.form-select[_ngcontent-%COMP%], \n.form-textarea[_ngcontent-%COMP%] {\n width: 100%;\n min-height: 44px;\n padding: 0.875rem 1rem;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-input[_ngcontent-%COMP%]:hover, \n.form-select[_ngcontent-%COMP%]:hover, \n.form-textarea[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.form-input[_ngcontent-%COMP%]:focus, \n.form-select[_ngcontent-%COMP%]:focus, \n.form-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-surface);\n}\n\n.form-input[_ngcontent-%COMP%]::placeholder, \n.form-textarea[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-secondary);\n opacity: 0.7;\n}\n\n.form-select[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin-top: 0.375rem;\n}\n\n.form-checkboxes[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.checkbox-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n cursor: pointer;\n min-height: 44px;\n padding: 0.25rem 0;\n}\n\n.checkbox-label[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n\n\n.form-section[_ngcontent-%COMP%] {\n margin-top: 1.5rem;\n padding: 1.25rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface-sunken);\n}\n\n.form-section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 1.125rem;\n}\n\n.form-textarea[_ngcontent-%COMP%] {\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n resize: vertical;\n min-height: 100px;\n}\n\n\n\n\n\n.confirm-dialog[_ngcontent-%COMP%] {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 420px;\n width: 90%;\n padding: 2rem;\n text-align: center;\n animation: _ngcontent-%COMP%_dialogBounce 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n@media (max-width: 639px) {\n .confirm-dialog[_ngcontent-%COMP%] {\n padding: 1.5rem;\n border-radius: var(--mj-radius-2xl);\n }\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: var(--mj-status-warning-bg);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n color: var(--mj-status-warning-text);\n}\n\n.confirm-dialog-content[_ngcontent-%COMP%] {\n margin-bottom: 1.5rem;\n}\n\n.confirm-dialog-title[_ngcontent-%COMP%] {\n margin: 0 0 0.75rem 0;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n line-height: 1.6;\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.confirm-dialog-details[_ngcontent-%COMP%] {\n display: block;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n.confirm-dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: center;\n}\n\n@media (max-width: 639px) {\n .confirm-dialog-actions[_ngcontent-%COMP%] {\n flex-direction: column-reverse;\n }\n\n \n\n .confirm-dialog-actions[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n }\n}\n\n\n\n\n\n@keyframes _ngcontent-%COMP%_expandIn {\n from {\n transform: scale(0.95);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n@keyframes _ngcontent-%COMP%_dialogBounce {\n 0% {\n transform: scale(0.9) translateY(10px);\n opacity: 0;\n }\n 70% {\n transform: scale(1.02) translateY(-5px);\n }\n 100% {\n transform: scale(1) translateY(0);\n opacity: 1;\n }\n}\n\n\n\n\n\n.sr-only[_ngcontent-%COMP%] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}"] });
|
|
1280
1277
|
};
|
|
1281
1278
|
SqlLoggingComponent = __decorate([
|
|
1282
1279
|
RegisterClass(BaseDashboard, 'SqlLogging')
|
|
@@ -1284,7 +1281,7 @@ SqlLoggingComponent = __decorate([
|
|
|
1284
1281
|
export { SqlLoggingComponent };
|
|
1285
1282
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SqlLoggingComponent, [{
|
|
1286
1283
|
type: Component,
|
|
1287
|
-
args: [{ standalone: false, selector: 'mj-sql-logging', template: "<div class=\"sql-logging-container\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\" role=\"toolbar\" aria-label=\"SQL logging actions\">\n <button\n class=\"btn-secondary\"\n (click)=\"loadActiveSessions()\"\n [disabled]=\"loading\"\n aria-label=\"Refresh sessions\"\n >\n <i class=\"fa-solid fa-refresh\" [class.fa-spin]=\"loading\" aria-hidden=\"true\"></i>\n Refresh\n </button>\n @if (isOwner && configEnabled) {\n <button\n class=\"btn-primary\"\n [disabled]=\"loading || activeSessions.length >= (sqlLoggingConfig?.maxActiveSessions || 5)\"\n (click)=\"openStartSessionDialog()\"\n [attr.aria-label]=\"'Start new SQL logging session' + (activeSessions.length >= (sqlLoggingConfig?.maxActiveSessions || 5) ? ' (maximum sessions reached)' : '')\"\n >\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start New Session\n </button>\n }\n </div>\n\n <!-- Stats Cards with Toggle -->\n @if (isOwner && configEnabled) {\n <div class=\"stats-toggle-container\">\n <!-- Toggle Button -->\n <button\n class=\"stats-toggle-button\"\n [class.expanded]=\"showStats\"\n (click)=\"showStats = !showStats\"\n [attr.aria-expanded]=\"showStats\"\n aria-controls=\"stats-grid-content\"\n >\n <div class=\"stats-toggle-left\">\n <div class=\"stats-toggle-icon\">\n <i class=\"fa-solid fa-chart-line\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stats-toggle-text\">\n <h3 class=\"stats-toggle-title\">Statistics</h3>\n <p class=\"stats-toggle-subtitle\">View session statistics and metrics</p>\n </div>\n </div>\n <i class=\"fa-solid fa-chevron-down stats-toggle-arrow\" aria-hidden=\"true\"></i>\n </button>\n\n <!-- Stats Grid (Collapsible) -->\n <div\n id=\"stats-grid-content\"\n class=\"stats-grid\"\n [class.visible]=\"showStats\"\n role=\"region\"\n aria-label=\"SQL logging statistics\"\n >\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-status\">\n <i class=\"fa-solid fa-power-off\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"'Status: ' + (configEnabled ? 'Enabled' : 'Disabled')\">\n {{ configEnabled ? \"Enabled\" : \"Disabled\" }}\n </div>\n <div class=\"stat-label\">Status</div>\n </div>\n </div>\n\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-active\">\n <i class=\"fa-solid fa-play-circle\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"activeSessions.length + ' active sessions'\">\n {{ activeSessions.length }}\n </div>\n <div class=\"stat-label\">Active Sessions</div>\n </div>\n </div>\n\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-limit\">\n <i class=\"fa-solid fa-gauge-high\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"(sqlLoggingConfig?.maxActiveSessions || 5) + ' maximum sessions allowed'\">\n {{ sqlLoggingConfig?.maxActiveSessions || 5 }}\n </div>\n <div class=\"stat-label\">Max Sessions</div>\n </div>\n </div>\n\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-total\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"getTotalStatementCount() + ' total SQL statements captured'\">\n {{ getTotalStatementCount() }}\n </div>\n <div class=\"stat-label\">Total Statements</div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Loading State -->\n @if (loading && !activeSessions.length) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n <mj-loading text=\"Loading SQL logging configuration...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Content Area -->\n @if (!loading || activeSessions.length > 0) {\n <div class=\"content-area\">\n @if (!isOwner) {\n <!-- Not authorized -->\n <div class=\"empty-state\" role=\"alert\">\n <i class=\"fa-solid fa-lock empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">Access Denied</p>\n <p class=\"empty-subtext\">SQL logging requires Owner privileges. Please contact your system administrator for access.</p>\n <button class=\"btn-secondary\" (click)=\"refreshUserPermissions()\" style=\"margin-top: 1rem\" aria-label=\"Refresh user permissions\">\n <i class=\"fa-solid fa-sync\" aria-hidden=\"true\"></i>\n Refresh Permissions\n </button>\n </div>\n } @else if (!configEnabled) {\n <!-- Not enabled in config -->\n <div class=\"empty-state\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-triangle empty-icon warning\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">SQL Logging Disabled</p>\n <p class=\"empty-subtext\">SQL logging is not enabled in the server configuration.</p>\n <div class=\"info-box\">\n <h4>To enable SQL logging:</h4>\n <ol>\n <li>Set <code>sqlLogging.enabled = true</code> in mj.config.cjs</li>\n <li>Restart the MJ API server</li>\n <li>Refresh this page</li>\n </ol>\n </div>\n </div>\n } @else if (activeSessions.length === 0) {\n <!-- No active sessions -->\n <div class=\"empty-state\" role=\"status\">\n <i class=\"fa-solid fa-file-code empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">No Active Sessions</p>\n <p class=\"empty-subtext\">Start a new SQL logging session to begin capturing SQL statements.</p>\n <button class=\"btn-primary\" (click)=\"openStartSessionDialog()\" style=\"margin-top: 1rem\" aria-label=\"Start a new SQL logging session\">\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start New Session\n </button>\n </div>\n } @else {\n <!-- Sessions layout -->\n <div class=\"sessions-layout\">\n <!-- Sessions panel -->\n <div class=\"sessions-panel\" role=\"region\" aria-label=\"Active sessions list\">\n <div class=\"panel-header\">\n <h3 class=\"panel-title\">Active Sessions</h3>\n @if (activeSessions.length > 0) {\n <button\n class=\"btn-danger btn-small\"\n (click)=\"openStopAllSessionsConfirm()\"\n [disabled]=\"loading\"\n aria-label=\"Stop all active sessions\"\n >\n <i class=\"fa-solid fa-stop\" aria-hidden=\"true\"></i>\n Stop All\n </button>\n }\n </div>\n <div class=\"sessions-list\" role=\"list\" aria-label=\"SQL logging sessions\">\n @for (session of activeSessions; track session.id) {\n <div\n class=\"session-card\"\n [class.selected]=\"selectedSession?.id === session.id\"\n (click)=\"selectSession(session)\"\n role=\"listitem\"\n tabindex=\"0\"\n (keydown.enter)=\"selectSession(session)\"\n (keydown.space)=\"selectSession(session); $event.preventDefault()\"\n [attr.aria-label]=\"'Session: ' + session.sessionName + ', ' + session.statementCount + ' statements, duration ' + getSessionDuration(session.startTime)\"\n [attr.aria-selected]=\"selectedSession?.id === session.id\"\n >\n <div class=\"session-header\">\n <div class=\"session-info\">\n <h4 class=\"session-title\">{{ session.sessionName }}</h4>\n <div class=\"session-meta\">\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n {{ getSessionDuration(session.startTime) }}\n </span>\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n {{ session.statementCount }} statements\n </span>\n </div>\n </div>\n <button mjButton\n variant=\"danger\"\n size=\"sm\"\n (click)=\"openStopSessionConfirm(session, $event)\"\n [attr.aria-label]=\"'Stop session ' + session.sessionName\"\n >\n <i class=\"fa-solid fa-stop\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"session-badges\">\n @if (session.filterByUserId) {\n <span class=\"badge badge-user\">\n <i class=\"fa-solid fa-user\" aria-hidden=\"true\"></i>\n User Filtered\n </span>\n }\n @if (session.options?.formatAsMigration) {\n <span class=\"badge badge-migration\">\n <i class=\"fa-solid fa-code-branch\" aria-hidden=\"true\"></i>\n Migration\n </span>\n }\n <span class=\"badge badge-type\">\n {{ session.options?.statementTypes || \"both\" }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Log viewer panel -->\n <div class=\"log-viewer-panel\" [class.expanded]=\"isLogViewerExpanded\" role=\"region\" aria-label=\"SQL log viewer\">\n @if (selectedSession) {\n <div class=\"panel-header\">\n <h3 class=\"panel-title\">{{ selectedSession.sessionName }}</h3>\n <div class=\"panel-actions\">\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"autoRefresh\"\n aria-label=\"Enable auto-refresh\"\n />\n Auto-refresh\n </label>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"loadSessionLog(selectedSession)\"\n aria-label=\"Refresh log content\"\n >\n <i class=\"fa-solid fa-sync\" [class.fa-spin]=\"loading\" aria-hidden=\"true\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"toggleLogViewerExpand()\"\n [attr.aria-label]=\"isLogViewerExpanded ? 'Collapse log viewer' : 'Expand log viewer to fullscreen'\"\n [attr.aria-expanded]=\"isLogViewerExpanded\"\n >\n <i class=\"fa-solid\" [class.fa-expand]=\"!isLogViewerExpanded\" [class.fa-compress]=\"isLogViewerExpanded\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n <div class=\"log-content\">\n <mj-code-editor\n [value]=\"logContent\"\n [readonly]=\"true\"\n [disabled]=\"true\"\n [language]=\"'sql'\"\n [setup]=\"'basic'\"\n [lineWrapping]=\"true\"\n [highlightWhitespace]=\"false\"\n style=\"height: 100%\"\n aria-label=\"SQL log content\"\n ></mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-state\" role=\"status\">\n <i class=\"fa-solid fa-arrow-left empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">Select a Session</p>\n <p class=\"empty-subtext\">Choose a session from the list to view its SQL log.</p>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Start Session Dialog -->\n @if (showStartSessionDialog) {\n <div\n class=\"modal-backdrop\"\n (click)=\"showStartSessionDialog = false\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"start-session-dialog-title\"\n >\n <div class=\"modal-dialog modal-large\" [class.fullscreen]=\"isStartDialogFullscreen\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"start-session-dialog-title\">\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start SQL Logging Session\n </h3>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleStartDialogFullscreen()\"\n [attr.aria-label]=\"isStartDialogFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isStartDialogFullscreen\" [class.fa-expand]=\"!isStartDialogFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button class=\"modal-close\" (click)=\"showStartSessionDialog = false\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n <div class=\"modal-body\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"session-name\">Session Name</label>\n <input\n type=\"text\"\n id=\"session-name\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.sessionName\"\n placeholder=\"Enter a descriptive name for this session\"\n aria-describedby=\"session-name-hint\"\n />\n <div id=\"session-name-hint\" class=\"form-hint\">A descriptive name to identify this logging session</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"file-name\">File Name</label>\n <input\n type=\"text\"\n id=\"file-name\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.fileName\"\n placeholder=\"sql-log-2024-01-01.sql\"\n aria-describedby=\"file-name-hint\"\n />\n <div id=\"file-name-hint\" class=\"form-hint\">The SQL log will be saved to this file</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"statement-types\">Statement Types</label>\n <select\n id=\"statement-types\"\n class=\"form-select\"\n [(ngModel)]=\"newSessionOptions.statementTypes\"\n aria-describedby=\"statement-types-hint\"\n >\n @for (option of statementTypeOptions; track option.value) {\n <option [value]=\"option.value\">{{ option.text }}</option>\n }\n </select>\n <div id=\"statement-types-hint\" class=\"form-hint\">Filter which types of SQL statements to capture</div>\n </div>\n\n <div class=\"form-checkboxes\" role=\"group\" aria-label=\"Session options\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.filterToCurrentUser\" />\n Filter to my SQL statements only\n </label>\n\n\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.formatAsMigration\" />\n Format as migration file\n </label>\n\n\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.prettyPrint\" />\n Pretty print SQL statements\n </label>\n </div>\n\n <!-- SQL Pattern Filtering Section -->\n <div class=\"form-section\">\n <h4 class=\"form-section-title\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n SQL Pattern Filtering\n </h4>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"filter-type\">Filter Mode</label>\n <select\n id=\"filter-type\"\n class=\"form-select\"\n [(ngModel)]=\"newSessionOptions.filterType\"\n aria-describedby=\"filter-type-hint\"\n >\n @for (option of filterTypeOptions; track option.value) {\n <option [value]=\"option.value\">{{ option.text }}</option>\n }\n </select>\n <div id=\"filter-type-hint\" class=\"form-hint\">Exclude: Skip SQL matching any pattern. Include: Only log SQL matching a pattern.</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"filter-patterns\">Filter Patterns (one per line or comma-separated)</label>\n <textarea\n id=\"filter-patterns\"\n class=\"form-textarea\"\n [(ngModel)]=\"newSessionOptions.filterPatterns\"\n rows=\"4\"\n placeholder=\"Examples: *AIPrompt* /spCreate.*Run/i SELECT * FROM vwMetadata\"\n aria-describedby=\"filter-patterns-hint\"\n ></textarea>\n <div id=\"filter-patterns-hint\" class=\"form-hint\">Supports wildcards (*) and regex (/pattern/flags). Example: *spCreate* matches any SP starting with spCreate.</div>\n </div>\n </div>\n\n <!-- Advanced Options Section -->\n <div class=\"form-section\">\n <h4 class=\"form-section-title\">\n <i class=\"fa-solid fa-cog\" aria-hidden=\"true\"></i>\n Advanced Options\n </h4>\n\n @if (newSessionOptions.formatAsMigration) {\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"default-schema\">Default Schema Name</label>\n <input\n type=\"text\"\n id=\"default-schema\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.defaultSchemaName\"\n placeholder=\"__mj\"\n aria-describedby=\"default-schema-hint\"\n />\n <div id=\"default-schema-hint\" class=\"form-hint\">Schema name to replace with ${flyway:defaultSchema} placeholder.</div>\n </div>\n }\n\n <div class=\"form-checkboxes\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.verboseOutput\" />\n Verbose Debug Output\n </label>\n <div class=\"form-hint\" style=\"margin-left: 1.75rem\">Log detailed filter decisions to server console (for debugging).</div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button class=\"btn-primary\" (click)=\"startNewSession()\" [disabled]=\"loading\" aria-label=\"Start the SQL logging session\">\n @if (loading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Starting...\n } @else {\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start Session\n }\n </button>\n <button class=\"btn-secondary\" (click)=\"showStartSessionDialog = false\" aria-label=\"Cancel and close dialog\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- Stop Session Confirmation Dialog -->\n @if (showStopConfirmDialog) {\n <div\n class=\"modal-backdrop\"\n (click)=\"cancelStopConfirm()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"stop-dialog-title\"\n aria-describedby=\"stop-dialog-desc\"\n >\n <div class=\"confirm-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"confirm-dialog-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"confirm-dialog-content\">\n <h3 class=\"confirm-dialog-title\" id=\"stop-dialog-title\">\n @if (isStoppingAll) {\n Stop All Sessions?\n } @else {\n Stop Session?\n }\n </h3>\n <p class=\"confirm-dialog-message\" id=\"stop-dialog-desc\">\n @if (isStoppingAll) {\n Are you sure you want to stop <strong>all {{ activeSessions.length }} active</strong> SQL logging sessions? This action cannot be undone.\n } @else if (sessionToStop) {\n Are you sure you want to stop the session <strong>\"{{ sessionToStop.sessionName }}\"</strong>?\n <span class=\"confirm-dialog-details\"> This session has captured {{ sessionToStop.statementCount }} SQL statements. </span>\n }\n </p>\n </div>\n <div class=\"confirm-dialog-actions\">\n <button class=\"btn-danger\" (click)=\"confirmStopSession()\" [disabled]=\"loading\" [attr.aria-label]=\"isStoppingAll ? 'Confirm stop all sessions' : 'Confirm stop session'\">\n @if (loading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Stopping...\n } @else {\n <i class=\"fa-solid fa-stop\" aria-hidden=\"true\"></i>\n @if (isStoppingAll) {\n Stop All Sessions\n } @else {\n Stop Session\n }\n }\n </button>\n <button class=\"btn-secondary\" (click)=\"cancelStopConfirm()\" [disabled]=\"loading\" aria-label=\"Cancel and keep sessions running\">Cancel</button>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: ["/* =============================================================================\n Shared Admin Patterns - MJ Design System\n Common styles shared across all admin settings components.\n Component-specific CSS files override these values where needed.\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n Host & Container\n ----------------------------------------------------------------------------- */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n/* -----------------------------------------------------------------------------\n Sticky Header\n ----------------------------------------------------------------------------- */\n.sticky-header {\n flex-shrink: 0;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n}\n\n/* -----------------------------------------------------------------------------\n Scrollable Content\n ----------------------------------------------------------------------------- */\n.scrollable-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n padding: 1rem;\n background: var(--mj-bg-surface-sunken);\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@media (min-width: 1440px) {\n .scrollable-content {\n padding: 2rem 2.5rem;\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(--mj-bg-page);\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 padding: 0.5rem 0.75rem;\n min-height: 40px;\n gap: 0;\n border-radius: var(--mj-radius-full);\n }\n\n .mj-btn-icon-mobile i {\n font-size: 1.125rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Statistics Cards Grid - Static Display (Non-interactive)\n ----------------------------------------------------------------------------- */\n.mj-grid-4 {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 1rem 0.75rem 1rem;\n background: var(--mj-bg-page);\n}\n\n@media (min-width: 768px) {\n .mj-grid-4 {\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(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\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/* -----------------------------------------------------------------------------\n Stat Icon Containers\n ----------------------------------------------------------------------------- */\n.stat-icon {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .stat-icon {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n.stat-icon-total {\n background: var(--mj-color-accent-300);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-active {\n background: var(--mj-color-success-100);\n color: var(--mj-status-success);\n}\n\n/* -----------------------------------------------------------------------------\n Stat Content Typography\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(--mj-text-primary);\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(--mj-text-secondary);\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(--mj-bg-surface-card);\n margin: 0 1rem 0.75rem 1rem;\n padding: 0.75rem;\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\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.mj-filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.mj-filter-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.mj-filter-buttons {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-full);\n padding: 4px;\n gap: 2px;\n}\n\n.mj-filter-buttons .mj-btn {\n border-radius: var(--mj-radius-full);\n}\n\n.mj-filter-buttons .mj-btn-primary {\n background-color: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n/* -----------------------------------------------------------------------------\n Search Input\n ----------------------------------------------------------------------------- */\n.mj-search {\n position: relative;\n flex: 1;\n min-width: 200px;\n}\n\n@media (min-width: 640px) {\n .mj-search {\n min-width: 280px;\n }\n}\n\n@media (min-width: 1024px) {\n .mj-search {\n min-width: 400px;\n max-width: 600px;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search {\n min-width: 500px;\n max-width: 800px;\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(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 1024px) {\n .mj-search .mj-search-icon {\n left: 1.25rem;\n font-size: 1.125rem;\n }\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(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n}\n\n@media (min-width: 1024px) {\n .mj-search .mj-search-input {\n padding: 1rem 1.25rem 1rem 3.25rem;\n font-size: 1.0625rem;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search .mj-search-input {\n padding: 1.125rem 1.5rem 1.125rem 3.5rem;\n }\n}\n\n.mj-search .mj-search-input::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.mj-search .mj-search-input:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.mj-search .mj-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--mj-bg-page);\n}\n\n.mj-search:focus-within .mj-search-icon {\n color: var(--mj-brand-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Content Area\n ----------------------------------------------------------------------------- */\n.content-area {\n flex: 1 1 auto;\n overflow: visible;\n position: relative;\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-xl);\n box-shadow: var(--mj-shadow-sm);\n padding: 1rem;\n border: 1px solid var(--mj-border-default);\n}\n\n@media (min-width: 768px) {\n .content-area {\n padding: 1.5rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Expand Button\n ----------------------------------------------------------------------------- */\n.expand-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s ease;\n border-radius: var(--mj-radius-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(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.expand-btn i {\n transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Status Badge\n ----------------------------------------------------------------------------- */\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(--mj-radius-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(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success);\n}\n\n.status-badge.status-inactive {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error);\n}\n\n.status-badge i {\n font-size: 0.625rem;\n}\n\n/* -----------------------------------------------------------------------------\n Mobile Actions Bar\n ----------------------------------------------------------------------------- */\n.mobile-actions-bar {\n display: none;\n}\n\n.mobile-action-buttons {\n display: flex;\n gap: 0.5rem;\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(--mj-border-default);\n margin-bottom: 1.5rem;\n}\n\n.empty-state .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 0.5rem 0;\n}\n\n.empty-state .empty-subtext {\n font-size: 1rem;\n color: var(--mj-text-secondary);\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(--mj-status-error);\n margin-bottom: 1rem;\n}\n\n.error-container .error-message {\n font-size: 1.0625rem;\n color: var(--mj-text-primary);\n margin: 0 0 1.5rem 0;\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 cubic-bezier(0, 0, 0.2, 1);\n}\n\n.modal-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 500px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n animation: slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\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(--mj-border-default);\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(--mj-text-primary);\n margin: 0;\n}\n\n.modal-header .modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.modal-header .modal-close:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.modal-body {\n padding: 1.5rem;\n}\n\n.modal-body p {\n font-size: 1rem;\n color: var(--mj-text-primary);\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-footer {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\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-footer {\n padding: 1rem;\n flex-direction: column;\n }\n\n .modal-footer .mj-btn {\n width: 100%;\n justify-content: center;\n }\n}\n\n/* -----------------------------------------------------------------------------\n MJ Button System\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(--mj-radius-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 */\n.mj-btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mj-btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.mj-btn-primary:active:not(:disabled) {\n background: var(--mj-color-brand-400);\n transform: scale(0.98);\n}\n\n/* Secondary Button */\n.mj-btn-secondary {\n background: var(--mj-bg-page);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-color-neutral-400);\n}\n\n.mj-btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.mj-btn-secondary:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n border-color: var(--mj-color-brand-700);\n}\n\n/* Ghost Button */\n.mj-btn-ghost {\n background: transparent;\n color: var(--mj-text-secondary);\n}\n\n.mj-btn-ghost:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.mj-btn-ghost:active:not(:disabled) {\n background: var(--mj-color-brand-700);\n}\n\n/* Danger Button */\n.mj-btn-danger {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mj-btn-danger:hover:not(:disabled) {\n background: var(--mj-color-error-300);\n box-shadow: var(--mj-shadow-md);\n}\n\n.mj-btn-danger:active:not(:disabled) {\n background: var(--mj-color-error-200);\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/* Icon-only Button */\n.mj-btn-icon-only {\n padding: 0.625rem;\n min-width: 44px;\n min-height: 44px;\n}\n\n/* Icon-mobile Button (text hidden on small screens) */\n.mj-btn-icon-mobile {\n gap: 0.5rem;\n}\n\n.mj-btn-icon-mobile .btn-text {\n display: inline;\n}\n\n/* Ghost Danger Button */\n.mj-btn-ghost.mj-btn-danger {\n background: transparent;\n color: var(--mj-status-error);\n box-shadow: none;\n}\n\n.mj-btn-ghost.mj-btn-danger:hover:not(:disabled) {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n}\n\n/* -----------------------------------------------------------------------------\n Filter Button (Mobile Only)\n ----------------------------------------------------------------------------- */\n.filter-button {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n border-radius: var(--mj-radius-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n min-width: 44px;\n}\n\n.filter-button:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.filter-button:active {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.filter-button i {\n font-size: 1rem;\n}\n\n/* -----------------------------------------------------------------------------\n Filter Modal (Mobile Bottom Sheet)\n ----------------------------------------------------------------------------- */\n.filter-modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.filter-modal {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl) var(--mj-radius-2xl) 0 0;\n box-shadow: var(--mj-shadow-2xl);\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n animation: slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.filter-modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.filter-modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.filter-modal-title i {\n color: var(--mj-brand-primary);\n font-size: 1.375rem;\n}\n\n.filter-modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.filter-modal-close:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.filter-modal-body {\n padding: 1.5rem;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n.filter-modal-footer {\n display: flex;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.filter-modal-footer button {\n flex: 1;\n margin: 0;\n}\n\n/* Filter Options Container (Inside Modal) */\n.filter-options-container {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.filter-group-label {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.filter-group-options {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.filter-option {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.filter-option:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-option.selected {\n background: var(--mj-color-accent-300);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.filter-option input[type=\"checkbox\"],\n.filter-option input[type=\"radio\"] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.filter-option-label {\n flex: 1;\n font-size: 1rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.filter-option.selected .filter-option-label {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n/* -----------------------------------------------------------------------------\n Utility Classes\n ----------------------------------------------------------------------------- */\n.text-danger {\n color: var(--mj-status-error);\n}\n\n.text-warning {\n color: var(--mj-color-warning-500);\n}\n\n.text-success {\n color: var(--mj-status-success);\n}\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes slideUpFromBottom {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\n.mj-search-input:focus-visible,\nbutton:focus-visible,\n.mj-btn:focus-visible {\n outline: 2px solid var(--mj-brand-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 SQL Logging Component - Component-Specific Styles\n Shared patterns are in ../shared/styles/_admin-patterns.css\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n Host Override - SQL Logging uses block/scroll layout instead of flex\n ----------------------------------------------------------------------------- */\n:host {\n display: block;\n height: 100%;\n width: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* -----------------------------------------------------------------------------\n Container & Layout\n ----------------------------------------------------------------------------- */\n.sql-logging-container {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n width: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n position: relative;\n background: var(--mj-bg-page);\n padding: 1rem;\n}\n\n@media (min-width: 640px) {\n .sql-logging-container {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .sql-logging-container {\n padding: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .sql-logging-container {\n padding: 2rem;\n }\n}\n\n@media (min-width: 1440px) {\n .sql-logging-container {\n padding: 2rem 2.5rem;\n max-width: 1920px;\n margin: 0 auto;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons Override - Different layout (margin-bottom, no padding/bg)\n ----------------------------------------------------------------------------- */\n.action-buttons {\n margin-bottom: 1.5rem;\n padding: 0;\n background: transparent;\n}\n\n@media (max-width: 639px) {\n .action-buttons {\n justify-content: center;\n }\n\n /* Icon-only buttons on mobile */\n .action-buttons .btn-primary,\n .action-buttons .btn-secondary {\n font-size: 0;\n padding: 0.75rem;\n min-width: 48px;\n min-height: 48px;\n gap: 0;\n }\n\n .action-buttons .btn-primary i,\n .action-buttons .btn-secondary i {\n font-size: 1.125rem;\n }\n\n .stats-toggle-button {\n padding: 0.875rem 1rem;\n }\n\n .stats-toggle-icon {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .stats-toggle-title {\n font-size: 0.9375rem;\n }\n\n .stats-toggle-subtitle {\n font-size: 0.75rem;\n }\n\n .stats-toggle-arrow {\n font-size: 1.125rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Button System - SQL Logging uses .btn-* instead of .mj-btn-*\n ----------------------------------------------------------------------------- */\n.btn-primary,\n.btn-secondary,\n.btn-danger {\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(--mj-radius-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 min-width: 44px;\n}\n\n/* Primary Button */\n.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-light);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-primary:active:not(:disabled) {\n background: var(--mj-color-brand-300);\n transform: scale(0.98);\n}\n\n.btn-primary:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-primary i {\n font-size: 0.875rem;\n}\n\n/* Secondary Button */\n.btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-border-strong);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.btn-secondary:active:not(:disabled) {\n background: var(--mj-brand-primary-active);\n border-color: var(--mj-brand-primary-active);\n}\n\n.btn-secondary:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-secondary i {\n font-size: 0.875rem;\n}\n\n/* Danger Button */\n.btn-danger {\n background: var(--mj-status-error);\n color: var(--mj-brand-on-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.btn-danger:hover:not(:disabled) {\n background: var(--mj-color-error-300);\n box-shadow: var(--mj-shadow-md);\n}\n\n.btn-danger:active:not(:disabled) {\n background: var(--mj-color-error-200);\n transform: scale(0.98);\n}\n\n.btn-danger:disabled {\n opacity: 0.38;\n cursor: not-allowed;\n}\n\n.btn-danger i {\n font-size: 0.875rem;\n}\n\n.btn-danger.btn-small {\n padding: 0.5rem 0.875rem;\n font-size: 0.8125rem;\n min-height: 36px;\n}\n\n/* -----------------------------------------------------------------------------\n Statistics Grid - Collapsible Cards\n ----------------------------------------------------------------------------- */\n.stats-toggle-container {\n margin-bottom: 1.5rem;\n}\n\n.stats-toggle-button {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.stats-toggle-button:hover {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.stats-toggle-button.expanded {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n margin-bottom: 1rem;\n}\n\n.stats-toggle-left {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.stats-toggle-icon {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n.stats-toggle-button.expanded .stats-toggle-icon {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.stats-toggle-text {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.stats-toggle-title {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.stats-toggle-button.expanded .stats-toggle-title {\n color: var(--mj-brand-primary);\n}\n\n.stats-toggle-subtitle {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.stats-toggle-arrow {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-toggle-button.expanded .stats-toggle-arrow {\n transform: rotate(180deg);\n color: var(--mj-brand-primary);\n}\n\n.stats-grid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n width: 100%;\n overflow: hidden;\n max-height: 0;\n opacity: 0;\n transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-grid.visible {\n max-height: 1000px;\n opacity: 1;\n margin-bottom: 1.5rem;\n}\n\n@media (min-width: 640px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .stats-toggle-button {\n display: none;\n }\n\n .stats-grid {\n max-height: none;\n opacity: 1;\n margin-bottom: 1.5rem;\n gap: 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .stats-grid {\n grid-template-columns: repeat(4, 1fr);\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1440px) {\n .stats-grid {\n gap: 2rem;\n }\n}\n\n/* Static Display Card */\n.stat-card {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1.25rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\n cursor: default;\n}\n\n/* Stat Icon Override - Different sizes */\n.stat-icon {\n width: 56px;\n height: 56px;\n font-size: 1.5rem;\n}\n\n@media (max-width: 639px) {\n .stat-icon {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n}\n\n.stat-icon-status {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.stat-icon-active {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-limit {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.stat-icon-total {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n/* Stat Value Override for mobile */\n@media (max-width: 639px) {\n .stat-content .stat-value {\n font-size: 1.5rem;\n font-weight: 700;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Content Area Override - Different styling\n ----------------------------------------------------------------------------- */\n.content-area {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n box-shadow: none;\n}\n\n@media (min-width: 640px) {\n .content-area {\n padding: 1.25rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Sessions Layout - Two-panel design\n ----------------------------------------------------------------------------- */\n.sessions-layout {\n display: flex;\n gap: 1.5rem;\n min-height: 400px;\n overflow: visible;\n}\n\n@media (max-width: 767px) {\n .sessions-layout {\n flex-direction: column;\n gap: 1rem;\n min-height: auto;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-layout {\n gap: 1.25rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Sessions Panel\n ----------------------------------------------------------------------------- */\n.sessions-panel {\n flex: 0 0 380px;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n max-height: 600px;\n}\n\n@media (max-width: 767px) {\n .sessions-panel {\n flex: none;\n max-height: 350px;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-panel {\n flex: 0 0 320px;\n }\n}\n\n@media (min-width: 1440px) {\n .sessions-panel {\n flex: 0 0 420px;\n }\n}\n\n.panel-header {\n padding: 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n gap: 0.5rem;\n}\n\n@media (max-width: 639px) {\n .panel-header {\n padding: 0.75rem;\n flex-wrap: wrap;\n }\n}\n\n.panel-header .panel-title {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex-shrink: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (max-width: 639px) {\n .panel-header .panel-title {\n font-size: 0.875rem;\n max-width: 50%;\n }\n}\n\n.panel-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .panel-actions {\n gap: 0.25rem;\n }\n\n .panel-actions .checkbox-label {\n font-size: 0;\n gap: 0;\n min-height: 36px;\n padding: 0;\n }\n\n .panel-actions .checkbox-label::after {\n content: \"Auto\";\n font-size: 0.75rem;\n margin-left: 0.25rem;\n }\n}\n\n.sessions-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n min-height: 0;\n position: relative;\n padding: 0.75rem;\n}\n\n/* -----------------------------------------------------------------------------\n Session Cards\n ----------------------------------------------------------------------------- */\n.session-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 1rem;\n margin-bottom: 0.75rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.session-card:last-child {\n margin-bottom: 0;\n}\n\n.session-card:hover {\n box-shadow: var(--mj-shadow-sm);\n border-color: var(--mj-brand-primary);\n}\n\n.session-card.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-brand-accent-subtle);\n}\n\n.session-card:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.session-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.75rem;\n}\n\n.session-info {\n flex: 1;\n min-width: 0;\n}\n\n.session-info .session-title {\n margin: 0 0 0.5rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.session-meta {\n display: flex;\n gap: 1rem;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n flex-wrap: wrap;\n}\n\n.session-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.session-badges {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n margin-top: 0.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Badges - Chips\n ----------------------------------------------------------------------------- */\n.badge {\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.badge-user {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.badge-migration {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success);\n}\n\n.badge-type {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning);\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons (Icon buttons)\n ----------------------------------------------------------------------------- */\n.action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.action-btn-danger:hover {\n background: var(--mj-status-error);\n color: var(--mj-brand-on-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Log Viewer Panel\n ----------------------------------------------------------------------------- */\n.log-viewer-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n min-height: 400px;\n}\n\n@media (max-width: 767px) {\n .log-viewer-panel {\n min-height: 350px;\n }\n}\n\n/* Code editor keeps its dark theme for readability (intentionally hardcoded for code syntax) */\n.log-content {\n flex: 1;\n overflow: hidden;\n min-height: 300px;\n height: 100%;\n position: relative;\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content ::ng-deep .cm-editor {\n height: 100%;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n font-size: 0.875rem;\n}\n\n.log-content ::ng-deep .cm-scroller {\n font-family: inherit;\n}\n\n.log-content ::ng-deep .cm-content {\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content ::ng-deep .cm-gutters {\n background: var(--mj-text-primary);\n color: var(--mj-text-disabled);\n border-right: 1px solid var(--mj-text-secondary);\n}\n\n.log-content ::ng-deep .cm-activeLineGutter {\n background: var(--mj-text-primary);\n}\n\n.log-content ::ng-deep .cm-activeLine {\n background: rgba(255, 255, 255, 0.04);\n}\n\n/* Expanded Log Viewer */\n.log-viewer-panel.expanded {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n border-radius: 0;\n margin: 0;\n max-height: none;\n height: 100vh;\n animation: expandIn 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n.log-viewer-panel.expanded .panel-header {\n border-radius: 0;\n}\n\n.log-viewer-panel.expanded .log-content {\n max-height: calc(100vh - 60px);\n min-height: calc(100vh - 60px);\n}\n\n/* -----------------------------------------------------------------------------\n Empty State Override - Different icon.warning styling\n ----------------------------------------------------------------------------- */\n.empty-state .empty-icon.warning {\n color: var(--mj-status-warning);\n}\n\n.empty-state .empty-subtext {\n max-width: 400px;\n}\n\n/* -----------------------------------------------------------------------------\n Info Box\n ----------------------------------------------------------------------------- */\n.info-box {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 1.5rem;\n margin-top: 1.5rem;\n text-align: left;\n max-width: 500px;\n border: 1px solid var(--mj-border-default);\n}\n\n.info-box h4 {\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.info-box ol {\n margin: 0;\n padding-left: 1.25rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n}\n\n.info-box ol li {\n margin-bottom: 0.5rem;\n}\n\n.info-box code {\n background: var(--mj-bg-surface-active);\n padding: 0.125rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.8125rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n color: var(--mj-text-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Loading Container Override\n ----------------------------------------------------------------------------- */\n.loading-container {\n min-height: 300px;\n}\n\n.loading-text {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin-top: 1rem;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Dialog Overrides - SQL Logging has its own modal patterns\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n background: var(--mj-bg-overlay);\n}\n\n.modal-dialog {\n width: 90%;\n display: flex;\n flex-direction: column;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.modal-dialog.modal-large {\n max-width: 700px;\n}\n\n/* Fullscreen mode */\n.modal-dialog.fullscreen {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n@media (max-width: 639px) {\n .modal-dialog {\n width: 95%;\n max-height: 85vh;\n border-radius: var(--mj-radius-2xl);\n }\n\n .modal-dialog.fullscreen {\n border-radius: 0;\n max-height: 100vh;\n }\n}\n\n.modal-header {\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-header {\n padding: 1rem 1.25rem;\n }\n}\n\n/* Modal Header Actions */\n.modal-header-actions {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\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.modal-action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.modal-action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.modal-body {\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n@media (max-width: 639px) {\n .modal-body {\n padding: 1rem 1.25rem;\n }\n}\n\n.modal-footer {\n justify-content: flex-end;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-footer {\n padding: 1rem 1.25rem;\n }\n\n .modal-footer .btn-primary,\n .modal-footer .btn-secondary {\n width: 100%;\n justify-content: center;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Form Elements\n ----------------------------------------------------------------------------- */\n.form-group {\n margin-bottom: 1.5rem;\n}\n\n.form-label {\n display: block;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 0.5rem;\n}\n\n.form-input,\n.form-select,\n.form-textarea {\n width: 100%;\n min-height: 44px;\n padding: 0.875rem 1rem;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-input:hover,\n.form-select:hover,\n.form-textarea:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.form-input:focus,\n.form-select:focus,\n.form-textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-surface);\n}\n\n.form-input::placeholder,\n.form-textarea::placeholder {\n color: var(--mj-text-secondary);\n opacity: 0.7;\n}\n\n.form-select {\n cursor: pointer;\n}\n\n.form-hint {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin-top: 0.375rem;\n}\n\n.form-checkboxes {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.checkbox-label {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n cursor: pointer;\n min-height: 44px;\n padding: 0.25rem 0;\n}\n\n.checkbox-label input[type=\"checkbox\"] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n/* Form Section */\n.form-section {\n margin-top: 1.5rem;\n padding: 1.25rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface-sunken);\n}\n\n.form-section-title {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-section-title i {\n color: var(--mj-brand-primary);\n font-size: 1.125rem;\n}\n\n.form-textarea {\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n resize: vertical;\n min-height: 100px;\n}\n\n/* -----------------------------------------------------------------------------\n Confirmation Dialog\n ----------------------------------------------------------------------------- */\n.confirm-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 420px;\n width: 90%;\n padding: 2rem;\n text-align: center;\n animation: dialogBounce 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n@media (max-width: 639px) {\n .confirm-dialog {\n padding: 1.5rem;\n border-radius: var(--mj-radius-2xl);\n }\n}\n\n.confirm-dialog-icon {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: var(--mj-status-warning-bg);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n}\n\n.confirm-dialog-icon i {\n font-size: 1.75rem;\n color: var(--mj-status-warning-text);\n}\n\n.confirm-dialog-content {\n margin-bottom: 1.5rem;\n}\n\n.confirm-dialog-title {\n margin: 0 0 0.75rem 0;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.confirm-dialog-message {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n line-height: 1.6;\n}\n\n.confirm-dialog-message strong {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.confirm-dialog-details {\n display: block;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n.confirm-dialog-actions {\n display: flex;\n gap: 0.75rem;\n justify-content: center;\n}\n\n@media (max-width: 639px) {\n .confirm-dialog-actions {\n flex-direction: column-reverse;\n }\n\n .confirm-dialog-actions .btn-danger,\n .confirm-dialog-actions .btn-secondary {\n width: 100%;\n justify-content: center;\n }\n}\n\n.confirm-dialog-actions .btn-danger {\n min-width: 140px;\n}\n\n.confirm-dialog-actions .btn-secondary {\n min-width: 100px;\n}\n\n/* -----------------------------------------------------------------------------\n SQL-Logging-specific Animations\n ----------------------------------------------------------------------------- */\n@keyframes expandIn {\n from {\n transform: scale(0.95);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n@keyframes dialogBounce {\n 0% {\n transform: scale(0.9) translateY(10px);\n opacity: 0;\n }\n 70% {\n transform: scale(1.02) translateY(-5px);\n }\n 100% {\n transform: scale(1) translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Screen Reader Only\n ----------------------------------------------------------------------------- */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n"] }]
|
|
1284
|
+
args: [{ standalone: false, selector: 'mj-sql-logging', template: "<!--\n Interior chrome \u2014 sub-page of Admin's Monitoring left-nav shell. Single section\n (no L2 tab nav) so [toolbar] is empty; actions land in [actions]. See Section 10\n of plans/explorer-chrome-conventions.md.\n-->\n<mj-page-header-interior\n Role=\"region\"\n AriaLabel=\"SQL logging actions\"\n Title=\"SQL Logging\"\n Subtitle=\"Capture and download SQL statements executed by the API\">\n <div actions>\n <mj-refresh-button\n [Loading]=\"loading\"\n (Clicked)=\"loadActiveSessions()\">\n </mj-refresh-button>\n @if (isOwner && configEnabled) {\n <button mjButton\n variant=\"primary\"\n size=\"sm\"\n [disabled]=\"loading || activeSessions.length >= (sqlLoggingConfig?.maxActiveSessions || 5)\"\n (click)=\"openStartSessionDialog()\"\n [attr.aria-label]=\"'Start new SQL logging session' + (activeSessions.length >= (sqlLoggingConfig?.maxActiveSessions || 5) ? ' (maximum sessions reached)' : '')\">\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start New Session\n </button>\n }\n </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior>\n\n <!-- Stats Cards with Toggle -->\n @if (isOwner && configEnabled) {\n <div class=\"stats-toggle-container\">\n <!-- Toggle Button -->\n <button\n class=\"stats-toggle-button\"\n [class.expanded]=\"showStats\"\n (click)=\"showStats = !showStats\"\n [attr.aria-expanded]=\"showStats\"\n aria-controls=\"stats-grid-content\"\n >\n <div class=\"stats-toggle-left\">\n <div class=\"stats-toggle-icon\">\n <i class=\"fa-solid fa-chart-line\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stats-toggle-text\">\n <h3 class=\"stats-toggle-title\">Statistics</h3>\n <p class=\"stats-toggle-subtitle\">View session statistics and metrics</p>\n </div>\n </div>\n <i class=\"fa-solid fa-chevron-down stats-toggle-arrow\" aria-hidden=\"true\"></i>\n </button>\n\n <!-- Stats Grid (Collapsible) -->\n <div\n id=\"stats-grid-content\"\n class=\"stats-grid\"\n [class.visible]=\"showStats\"\n role=\"region\"\n aria-label=\"SQL logging statistics\"\n >\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-status\">\n <i class=\"fa-solid fa-power-off\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"'Status: ' + (configEnabled ? 'Enabled' : 'Disabled')\">\n {{ configEnabled ? \"Enabled\" : \"Disabled\" }}\n </div>\n <div class=\"stat-label\">Status</div>\n </div>\n </div>\n\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-active\">\n <i class=\"fa-solid fa-play-circle\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"activeSessions.length + ' active sessions'\">\n {{ activeSessions.length }}\n </div>\n <div class=\"stat-label\">Active Sessions</div>\n </div>\n </div>\n\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-limit\">\n <i class=\"fa-solid fa-gauge-high\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"(sqlLoggingConfig?.maxActiveSessions || 5) + ' maximum sessions allowed'\">\n {{ sqlLoggingConfig?.maxActiveSessions || 5 }}\n </div>\n <div class=\"stat-label\">Max Sessions</div>\n </div>\n </div>\n\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-total\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\" [attr.aria-label]=\"getTotalStatementCount() + ' total SQL statements captured'\">\n {{ getTotalStatementCount() }}\n </div>\n <div class=\"stat-label\">Total Statements</div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Loading State -->\n @if (loading && !activeSessions.length) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n <mj-loading text=\"Loading SQL logging configuration...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- Content Area -->\n @if (!loading || activeSessions.length > 0) {\n <div class=\"content-area\">\n @if (!isOwner) {\n <!-- Not authorized -->\n <div class=\"empty-state\" role=\"alert\">\n <i class=\"fa-solid fa-lock empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">Access Denied</p>\n <p class=\"empty-subtext\">SQL logging requires Owner privileges. Please contact your system administrator for access.</p>\n <button mjButton variant=\"secondary\" size=\"md\" (click)=\"refreshUserPermissions()\" style=\"margin-top: 1rem\" aria-label=\"Refresh user permissions\">\n <i class=\"fa-solid fa-sync\" aria-hidden=\"true\"></i>\n Refresh Permissions\n </button>\n </div>\n } @else if (!configEnabled) {\n <!-- Not enabled in config -->\n <div class=\"empty-state\" role=\"alert\">\n <i class=\"fa-solid fa-exclamation-triangle empty-icon warning\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">SQL Logging Disabled</p>\n <p class=\"empty-subtext\">SQL logging is not enabled in the server configuration.</p>\n <div class=\"info-box\">\n <h4>To enable SQL logging:</h4>\n <ol>\n <li>Set <code>sqlLogging.enabled = true</code> in mj.config.cjs</li>\n <li>Restart the MJ API server</li>\n <li>Refresh this page</li>\n </ol>\n </div>\n </div>\n } @else if (activeSessions.length === 0) {\n <!-- No active sessions -->\n <div class=\"empty-state\" role=\"status\">\n <i class=\"fa-solid fa-file-code empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">No Active Sessions</p>\n <p class=\"empty-subtext\">Start a new SQL logging session to begin capturing SQL statements.</p>\n <button mjButton variant=\"primary\" size=\"md\" (click)=\"openStartSessionDialog()\" style=\"margin-top: 1rem\" aria-label=\"Start a new SQL logging session\">\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start New Session\n </button>\n </div>\n } @else {\n <!-- Sessions layout -->\n <div class=\"sessions-layout\">\n <!-- Sessions panel -->\n <div class=\"sessions-panel\" role=\"region\" aria-label=\"Active sessions list\">\n <div class=\"panel-header\">\n <h3 class=\"panel-title\">Active Sessions</h3>\n @if (activeSessions.length > 0) {\n <button mjButton\n variant=\"danger\"\n size=\"sm\"\n (click)=\"openStopAllSessionsConfirm()\"\n [disabled]=\"loading\"\n aria-label=\"Stop all active sessions\"\n >\n <i class=\"fa-solid fa-stop\" aria-hidden=\"true\"></i>\n Stop All\n </button>\n }\n </div>\n <div class=\"sessions-list\" role=\"list\" aria-label=\"SQL logging sessions\">\n @for (session of activeSessions; track session.id) {\n <div\n class=\"session-card\"\n [class.selected]=\"selectedSession?.id === session.id\"\n (click)=\"selectSession(session)\"\n role=\"listitem\"\n tabindex=\"0\"\n (keydown.enter)=\"selectSession(session)\"\n (keydown.space)=\"selectSession(session); $event.preventDefault()\"\n [attr.aria-label]=\"'Session: ' + session.sessionName + ', ' + session.statementCount + ' statements, duration ' + getSessionDuration(session.startTime)\"\n [attr.aria-selected]=\"selectedSession?.id === session.id\"\n >\n <div class=\"session-header\">\n <div class=\"session-info\">\n <h4 class=\"session-title\">{{ session.sessionName }}</h4>\n <div class=\"session-meta\">\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-clock\" aria-hidden=\"true\"></i>\n {{ getSessionDuration(session.startTime) }}\n </span>\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n {{ session.statementCount }} statements\n </span>\n </div>\n </div>\n <button mjButton\n variant=\"danger\"\n size=\"sm\"\n (click)=\"openStopSessionConfirm(session, $event)\"\n [attr.aria-label]=\"'Stop session ' + session.sessionName\"\n >\n <i class=\"fa-solid fa-stop\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"session-badges\">\n @if (session.filterByUserId) {\n <span class=\"badge badge-user\">\n <i class=\"fa-solid fa-user\" aria-hidden=\"true\"></i>\n User Filtered\n </span>\n }\n @if (session.options?.formatAsMigration) {\n <span class=\"badge badge-migration\">\n <i class=\"fa-solid fa-code-branch\" aria-hidden=\"true\"></i>\n Migration\n </span>\n }\n <span class=\"badge badge-type\">\n {{ session.options?.statementTypes || \"both\" }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Log viewer panel -->\n <div class=\"log-viewer-panel\" [class.expanded]=\"isLogViewerExpanded\" role=\"region\" aria-label=\"SQL log viewer\">\n @if (selectedSession) {\n <div class=\"panel-header\">\n <h3 class=\"panel-title\">{{ selectedSession.sessionName }}</h3>\n <div class=\"panel-actions\">\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"autoRefresh\"\n aria-label=\"Enable auto-refresh\"\n />\n Auto-refresh\n </label>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"loadSessionLog(selectedSession)\"\n aria-label=\"Refresh log content\"\n >\n <i class=\"fa-solid fa-sync\" [class.fa-spin]=\"loading\" aria-hidden=\"true\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"toggleLogViewerExpand()\"\n [attr.aria-label]=\"isLogViewerExpanded ? 'Collapse log viewer' : 'Expand log viewer to fullscreen'\"\n [attr.aria-expanded]=\"isLogViewerExpanded\"\n >\n <i class=\"fa-solid\" [class.fa-expand]=\"!isLogViewerExpanded\" [class.fa-compress]=\"isLogViewerExpanded\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n <div class=\"log-content\">\n <mj-code-editor\n [value]=\"logContent\"\n [readonly]=\"true\"\n [disabled]=\"true\"\n [language]=\"'sql'\"\n [setup]=\"'basic'\"\n [lineWrapping]=\"true\"\n [highlightWhitespace]=\"false\"\n style=\"height: 100%\"\n aria-label=\"SQL log content\"\n ></mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-state\" role=\"status\">\n <i class=\"fa-solid fa-arrow-left empty-icon\" aria-hidden=\"true\"></i>\n <p class=\"empty-text\">Select a Session</p>\n <p class=\"empty-subtext\">Choose a session from the list to view its SQL log.</p>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Start Session Dialog -->\n @if (showStartSessionDialog) {\n <div\n class=\"modal-backdrop\"\n (click)=\"showStartSessionDialog = false\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"start-session-dialog-title\"\n >\n <div class=\"modal-dialog modal-large\" [class.fullscreen]=\"isStartDialogFullscreen\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\" id=\"start-session-dialog-title\">\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start SQL Logging Session\n </h3>\n <div class=\"modal-header-actions\">\n <button\n class=\"modal-action-btn\"\n (click)=\"toggleStartDialogFullscreen()\"\n [attr.aria-label]=\"isStartDialogFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n type=\"button\"\n >\n <i class=\"fa-solid\" [class.fa-compress]=\"isStartDialogFullscreen\" [class.fa-expand]=\"!isStartDialogFullscreen\" aria-hidden=\"true\"></i>\n </button>\n <button class=\"modal-close\" (click)=\"showStartSessionDialog = false\" aria-label=\"Close dialog\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n <div class=\"modal-body\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"session-name\">Session Name</label>\n <input\n type=\"text\"\n id=\"session-name\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.sessionName\"\n placeholder=\"Enter a descriptive name for this session\"\n aria-describedby=\"session-name-hint\"\n />\n <div id=\"session-name-hint\" class=\"form-hint\">A descriptive name to identify this logging session</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"file-name\">File Name</label>\n <input\n type=\"text\"\n id=\"file-name\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.fileName\"\n placeholder=\"sql-log-2024-01-01.sql\"\n aria-describedby=\"file-name-hint\"\n />\n <div id=\"file-name-hint\" class=\"form-hint\">The SQL log will be saved to this file</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"statement-types\">Statement Types</label>\n <select\n id=\"statement-types\"\n class=\"form-select\"\n [(ngModel)]=\"newSessionOptions.statementTypes\"\n aria-describedby=\"statement-types-hint\"\n >\n @for (option of statementTypeOptions; track option.value) {\n <option [value]=\"option.value\">{{ option.text }}</option>\n }\n </select>\n <div id=\"statement-types-hint\" class=\"form-hint\">Filter which types of SQL statements to capture</div>\n </div>\n\n <div class=\"form-checkboxes\" role=\"group\" aria-label=\"Session options\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.filterToCurrentUser\" />\n Filter to my SQL statements only\n </label>\n\n\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.formatAsMigration\" />\n Format as migration file\n </label>\n\n\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.prettyPrint\" />\n Pretty print SQL statements\n </label>\n </div>\n\n <!-- SQL Pattern Filtering Section -->\n <div class=\"form-section\">\n <h4 class=\"form-section-title\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n SQL Pattern Filtering\n </h4>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"filter-type\">Filter Mode</label>\n <select\n id=\"filter-type\"\n class=\"form-select\"\n [(ngModel)]=\"newSessionOptions.filterType\"\n aria-describedby=\"filter-type-hint\"\n >\n @for (option of filterTypeOptions; track option.value) {\n <option [value]=\"option.value\">{{ option.text }}</option>\n }\n </select>\n <div id=\"filter-type-hint\" class=\"form-hint\">Exclude: Skip SQL matching any pattern. Include: Only log SQL matching a pattern.</div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"filter-patterns\">Filter Patterns (one per line or comma-separated)</label>\n <textarea\n id=\"filter-patterns\"\n class=\"form-textarea\"\n [(ngModel)]=\"newSessionOptions.filterPatterns\"\n rows=\"4\"\n placeholder=\"Examples: *AIPrompt* /spCreate.*Run/i SELECT * FROM vwMetadata\"\n aria-describedby=\"filter-patterns-hint\"\n ></textarea>\n <div id=\"filter-patterns-hint\" class=\"form-hint\">Supports wildcards (*) and regex (/pattern/flags). Example: *spCreate* matches any SP starting with spCreate.</div>\n </div>\n </div>\n\n <!-- Advanced Options Section -->\n <div class=\"form-section\">\n <h4 class=\"form-section-title\">\n <i class=\"fa-solid fa-cog\" aria-hidden=\"true\"></i>\n Advanced Options\n </h4>\n\n @if (newSessionOptions.formatAsMigration) {\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"default-schema\">Default Schema Name</label>\n <input\n type=\"text\"\n id=\"default-schema\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.defaultSchemaName\"\n placeholder=\"__mj\"\n aria-describedby=\"default-schema-hint\"\n />\n <div id=\"default-schema-hint\" class=\"form-hint\">Schema name to replace with ${flyway:defaultSchema} placeholder.</div>\n </div>\n }\n\n <div class=\"form-checkboxes\">\n <label class=\"checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"newSessionOptions.verboseOutput\" />\n Verbose Debug Output\n </label>\n <div class=\"form-hint\" style=\"margin-left: 1.75rem\">Log detailed filter decisions to server console (for debugging).</div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button mjButton variant=\"primary\" size=\"md\" (click)=\"startNewSession()\" [disabled]=\"loading\" aria-label=\"Start the SQL logging session\">\n @if (loading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Starting...\n } @else {\n <i class=\"fa-solid fa-play\" aria-hidden=\"true\"></i>\n Start Session\n }\n </button>\n <button mjButton variant=\"secondary\" size=\"md\" (click)=\"showStartSessionDialog = false\" aria-label=\"Cancel and close dialog\">Cancel</button>\n </div>\n </div>\n </div>\n }\n\n <!-- Stop Session Confirmation Dialog -->\n @if (showStopConfirmDialog) {\n <div\n class=\"modal-backdrop\"\n (click)=\"cancelStopConfirm()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"stop-dialog-title\"\n aria-describedby=\"stop-dialog-desc\"\n >\n <div class=\"confirm-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"confirm-dialog-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"confirm-dialog-content\">\n <h3 class=\"confirm-dialog-title\" id=\"stop-dialog-title\">\n @if (isStoppingAll) {\n Stop All Sessions?\n } @else {\n Stop Session?\n }\n </h3>\n <p class=\"confirm-dialog-message\" id=\"stop-dialog-desc\">\n @if (isStoppingAll) {\n Are you sure you want to stop <strong>all {{ activeSessions.length }} active</strong> SQL logging sessions? This action cannot be undone.\n } @else if (sessionToStop) {\n Are you sure you want to stop the session <strong>\"{{ sessionToStop.sessionName }}\"</strong>?\n <span class=\"confirm-dialog-details\"> This session has captured {{ sessionToStop.statementCount }} SQL statements. </span>\n }\n </p>\n </div>\n <div class=\"confirm-dialog-actions\">\n <button mjButton variant=\"danger\" size=\"md\" (click)=\"confirmStopSession()\" [disabled]=\"loading\" [attr.aria-label]=\"isStoppingAll ? 'Confirm stop all sessions' : 'Confirm stop session'\">\n @if (loading) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n Stopping...\n } @else {\n <i class=\"fa-solid fa-stop\" aria-hidden=\"true\"></i>\n @if (isStoppingAll) {\n Stop All Sessions\n } @else {\n Stop Session\n }\n }\n </button>\n <button mjButton variant=\"secondary\" size=\"md\" (click)=\"cancelStopConfirm()\" [disabled]=\"loading\" aria-label=\"Cancel and keep sessions running\">Cancel</button>\n </div>\n </div>\n </div>\n }\n</mj-page-body-interior>\n", styles: ["/* =============================================================================\n Shared Admin Patterns - MJ Design System\n Common styles shared across all admin settings components.\n Component-specific CSS files override these values where needed.\n ============================================================================= */\n\n/* -----------------------------------------------------------------------------\n Host & Container\n ----------------------------------------------------------------------------- */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n/* -----------------------------------------------------------------------------\n Sticky Header\n ----------------------------------------------------------------------------- */\n.sticky-header {\n flex-shrink: 0;\n background: var(--mj-bg-page);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n}\n\n/* -----------------------------------------------------------------------------\n Scrollable Content\n ----------------------------------------------------------------------------- */\n.scrollable-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n padding: 1rem;\n background: var(--mj-bg-surface-sunken);\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@media (min-width: 1440px) {\n .scrollable-content {\n padding: 2rem 2.5rem;\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(--mj-bg-page);\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\n/* -----------------------------------------------------------------------------\n Statistics Cards Grid - Static Display (Non-interactive)\n ----------------------------------------------------------------------------- */\n.mj-grid-4 {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 0.5rem;\n padding: 0 1rem 0.75rem 1rem;\n background: var(--mj-bg-page);\n}\n\n@media (min-width: 768px) {\n .mj-grid-4 {\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(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\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/* -----------------------------------------------------------------------------\n Stat Icon Containers\n ----------------------------------------------------------------------------- */\n.stat-icon {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n@media (min-width: 768px) {\n .stat-icon {\n width: 52px;\n height: 52px;\n font-size: 1.375rem;\n }\n}\n\n.stat-icon-total {\n background: var(--mj-color-accent-300);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-active {\n background: var(--mj-color-success-100);\n color: var(--mj-status-success);\n}\n\n/* -----------------------------------------------------------------------------\n Stat Content Typography\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(--mj-text-primary);\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(--mj-text-secondary);\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(--mj-bg-surface-card);\n margin: 0 1rem 0.75rem 1rem;\n padding: 0.75rem;\n border-radius: var(--mj-radius-lg);\n border: 1px solid var(--mj-border-default);\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.mj-filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.mj-filter-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.mj-filter-buttons {\n display: flex;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-full);\n padding: 4px;\n gap: 2px;\n}\n\n/* -----------------------------------------------------------------------------\n Search Input\n ----------------------------------------------------------------------------- */\n.mj-search {\n position: relative;\n flex: 1;\n min-width: 200px;\n}\n\n@media (min-width: 640px) {\n .mj-search {\n min-width: 280px;\n }\n}\n\n@media (min-width: 1024px) {\n .mj-search {\n min-width: 400px;\n max-width: 600px;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search {\n min-width: 500px;\n max-width: 800px;\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(--mj-text-secondary);\n font-size: 1rem;\n pointer-events: none;\n transition: color 0.2s ease;\n}\n\n@media (min-width: 1024px) {\n .mj-search .mj-search-icon {\n left: 1.25rem;\n font-size: 1.125rem;\n }\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(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: 1rem;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n}\n\n@media (min-width: 1024px) {\n .mj-search .mj-search-input {\n padding: 1rem 1.25rem 1rem 3.25rem;\n font-size: 1.0625rem;\n }\n}\n\n@media (min-width: 1440px) {\n .mj-search .mj-search-input {\n padding: 1.125rem 1.5rem 1.125rem 3.5rem;\n }\n}\n\n.mj-search .mj-search-input::placeholder {\n color: var(--mj-text-secondary);\n}\n\n.mj-search .mj-search-input:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.mj-search .mj-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--mj-bg-page);\n}\n\n.mj-search:focus-within .mj-search-icon {\n color: var(--mj-brand-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Content Area\n ----------------------------------------------------------------------------- */\n.content-area {\n flex: 1 1 auto;\n overflow: visible;\n position: relative;\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-xl);\n box-shadow: var(--mj-shadow-sm);\n padding: 1rem;\n border: 1px solid var(--mj-border-default);\n}\n\n@media (min-width: 768px) {\n .content-area {\n padding: 1.5rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Expand Button\n ----------------------------------------------------------------------------- */\n.expand-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s ease;\n border-radius: var(--mj-radius-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(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.expand-btn i {\n transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n/* -----------------------------------------------------------------------------\n Status Badge\n ----------------------------------------------------------------------------- */\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(--mj-radius-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(--mj-color-success-100);\n color: var(--mj-color-success-800);\n border: 1px solid var(--mj-status-success);\n}\n\n.status-badge.status-inactive {\n background: var(--mj-color-error-100);\n color: var(--mj-status-error);\n border: 1px solid var(--mj-status-error);\n}\n\n.status-badge i {\n font-size: 0.625rem;\n}\n\n/* -----------------------------------------------------------------------------\n Mobile Actions Bar\n ----------------------------------------------------------------------------- */\n.mobile-actions-bar {\n display: none;\n}\n\n.mobile-action-buttons {\n display: flex;\n gap: 0.5rem;\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(--mj-border-default);\n margin-bottom: 1.5rem;\n}\n\n.empty-state .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 0.5rem 0;\n}\n\n.empty-state .empty-subtext {\n font-size: 1rem;\n color: var(--mj-text-secondary);\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(--mj-status-error);\n margin-bottom: 1rem;\n}\n\n.error-container .error-message {\n font-size: 1.0625rem;\n color: var(--mj-text-primary);\n margin: 0 0 1.5rem 0;\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 cubic-bezier(0, 0, 0.2, 1);\n}\n\n.modal-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 500px;\n width: 100%;\n max-height: 90vh;\n overflow: hidden;\n animation: slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\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(--mj-border-default);\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(--mj-text-primary);\n margin: 0;\n}\n\n.modal-header .modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.modal-header .modal-close:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.modal-body {\n padding: 1.5rem;\n}\n\n.modal-body p {\n font-size: 1rem;\n color: var(--mj-text-primary);\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-footer {\n display: flex;\n justify-content: flex-start;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\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-footer {\n padding: 1rem;\n flex-direction: column;\n }\n\n}\n\n/* The legacy \"MJ Button System\" rule block (.mj-btn / .mj-btn-primary /\n .mj-btn-secondary / .mj-btn-ghost / .mj-btn-danger / .mj-btn-sm /\n .mj-btn-icon-only / .mj-btn-icon-mobile) was removed 2026-05-19. These\n rules pre-dated the mjButton directive standardization (the directive\n uses BEM modifiers like .mj-btn--primary, single-dash names like\n .mj-btn-primary don't match it anyway). The base .mj-btn rule WAS active\n though \u2014 its component-scoped specificity outranked button.scss's global\n directive styles, so admin sub-page buttons rendered pill-shaped + 44px\n regardless of the variant/size requested via mjButton inputs. Removing the\n rule lets every sub-page fall back to the directive's intended look. */\n\n/* -----------------------------------------------------------------------------\n Filter Button (Mobile Only)\n ----------------------------------------------------------------------------- */\n.filter-button {\n display: none;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n border-radius: var(--mj-radius-full);\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 44px;\n min-width: 44px;\n}\n\n.filter-button:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.filter-button:active {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.filter-button i {\n font-size: 1rem;\n}\n\n/* -----------------------------------------------------------------------------\n Filter Modal (Mobile Bottom Sheet)\n ----------------------------------------------------------------------------- */\n.filter-modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: flex-end;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n padding: 0;\n}\n\n.filter-modal {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl) var(--mj-radius-2xl) 0 0;\n box-shadow: var(--mj-shadow-2xl);\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n animation: slideUpFromBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n display: flex;\n flex-direction: column;\n}\n\n.filter-modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.filter-modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.filter-modal-title i {\n color: var(--mj-brand-primary);\n font-size: 1.375rem;\n}\n\n.filter-modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s ease;\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.filter-modal-close:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.filter-modal-body {\n padding: 1.5rem;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n.filter-modal-footer {\n display: flex;\n gap: 0.75rem;\n padding: 1.25rem 1.5rem;\n border-top: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.filter-modal-footer button {\n flex: 1;\n margin: 0;\n}\n\n/* Filter Options Container (Inside Modal) */\n.filter-options-container {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.filter-group {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.filter-group-label {\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0;\n}\n\n.filter-group-options {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.filter-option {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.875rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.filter-option:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-option.selected {\n background: var(--mj-color-accent-300);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.filter-option input[type=\"checkbox\"],\n.filter-option input[type=\"radio\"] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n.filter-option-label {\n flex: 1;\n font-size: 1rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n}\n\n.filter-option.selected .filter-option-label {\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n/* -----------------------------------------------------------------------------\n Utility Classes\n ----------------------------------------------------------------------------- */\n.text-danger {\n color: var(--mj-status-error);\n}\n\n.text-warning {\n color: var(--mj-color-warning-500);\n}\n\n.text-success {\n color: var(--mj-status-success);\n}\n\n/* -----------------------------------------------------------------------------\n Animations\n ----------------------------------------------------------------------------- */\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes slideUpFromBottom {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Accessibility: Focus Indicators\n ----------------------------------------------------------------------------- */\n.mj-search-input:focus-visible,\nbutton:focus-visible {\n outline: 2px solid var(--mj-brand-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 SQL Logging Component - Component-Specific Styles\n Shared patterns are in ../shared/styles/_admin-patterns.css\n ============================================================================= */\n\n/*\n Layout \u2014 host is flex column (from _admin-patterns.css :host).\n <mj-page-header-interior> sits pinned at the top; .scrollable-content\n (also from _admin-patterns) fills the rest with responsive padding.\n Buttons in this component use the mjButton directive \u2014 see Section 10\n of plans/explorer-chrome-conventions.md.\n*/\n\n/* Small-viewport adjustments for the collapsible stats toggle. */\n@media (max-width: 639px) {\n .stats-toggle-button {\n padding: 0.875rem 1rem;\n }\n\n .stats-toggle-icon {\n width: 40px;\n height: 40px;\n font-size: 1rem;\n }\n\n .stats-toggle-title {\n font-size: 0.9375rem;\n }\n\n .stats-toggle-subtitle {\n font-size: 0.75rem;\n }\n\n .stats-toggle-arrow {\n font-size: 1.125rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Statistics Grid - Collapsible Cards\n ----------------------------------------------------------------------------- */\n.stats-toggle-container {\n margin-bottom: 1.5rem;\n}\n\n.stats-toggle-button {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 1.5rem;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.stats-toggle-button:hover {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.stats-toggle-button.expanded {\n border-color: var(--mj-brand-primary);\n background: var(--mj-brand-accent-subtle);\n margin-bottom: 1rem;\n}\n\n.stats-toggle-left {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.stats-toggle-icon {\n width: 48px;\n height: 48px;\n border-radius: var(--mj-radius-lg);\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.25rem;\n flex-shrink: 0;\n}\n\n.stats-toggle-button.expanded .stats-toggle-icon {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.stats-toggle-text {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.stats-toggle-title {\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.stats-toggle-button.expanded .stats-toggle-title {\n color: var(--mj-brand-primary);\n}\n\n.stats-toggle-subtitle {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n.stats-toggle-arrow {\n font-size: 1.25rem;\n color: var(--mj-text-secondary);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-toggle-button.expanded .stats-toggle-arrow {\n transform: rotate(180deg);\n color: var(--mj-brand-primary);\n}\n\n.stats-grid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.75rem;\n width: 100%;\n overflow: hidden;\n max-height: 0;\n opacity: 0;\n transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.stats-grid.visible {\n max-height: 1000px;\n opacity: 1;\n margin-bottom: 1.5rem;\n}\n\n@media (min-width: 640px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n@media (min-width: 768px) {\n .stats-toggle-button {\n display: none;\n }\n\n .stats-grid {\n max-height: none;\n opacity: 1;\n margin-bottom: 1.5rem;\n gap: 1.25rem;\n }\n}\n\n@media (min-width: 1024px) {\n .stats-grid {\n grid-template-columns: repeat(4, 1fr);\n gap: 1.5rem;\n }\n}\n\n@media (min-width: 1440px) {\n .stats-grid {\n gap: 2rem;\n }\n}\n\n/* Static Display Card */\n.stat-card {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n padding: 1.25rem;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--mj-border-default);\n cursor: default;\n}\n\n/* Stat Icon Override - Different sizes */\n.stat-icon {\n width: 56px;\n height: 56px;\n font-size: 1.5rem;\n}\n\n@media (max-width: 639px) {\n .stat-icon {\n width: 48px;\n height: 48px;\n font-size: 1.25rem;\n }\n}\n\n.stat-icon-status {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n.stat-icon-active {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n}\n\n.stat-icon-limit {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n}\n\n.stat-icon-total {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success);\n}\n\n/* Stat Value Override for mobile */\n@media (max-width: 639px) {\n .stat-content .stat-value {\n font-size: 1.5rem;\n font-weight: 700;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Content Area Override - Different styling\n ----------------------------------------------------------------------------- */\n.content-area {\n flex: 1;\n min-height: 0;\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-lg);\n box-shadow: none;\n}\n\n@media (min-width: 640px) {\n .content-area {\n padding: 1.25rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Sessions Layout - Two-panel design\n ----------------------------------------------------------------------------- */\n.sessions-layout {\n display: flex;\n gap: 1.5rem;\n min-height: 400px;\n overflow: visible;\n}\n\n@media (max-width: 767px) {\n .sessions-layout {\n flex-direction: column;\n gap: 1rem;\n min-height: auto;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-layout {\n gap: 1.25rem;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Sessions Panel\n ----------------------------------------------------------------------------- */\n.sessions-panel {\n flex: 0 0 380px;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n max-height: 600px;\n}\n\n@media (max-width: 767px) {\n .sessions-panel {\n flex: none;\n max-height: 350px;\n }\n}\n\n@media (min-width: 768px) and (max-width: 1023px) {\n .sessions-panel {\n flex: 0 0 320px;\n }\n}\n\n@media (min-width: 1440px) {\n .sessions-panel {\n flex: 0 0 420px;\n }\n}\n\n.panel-header {\n padding: 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n gap: 0.5rem;\n}\n\n@media (max-width: 639px) {\n .panel-header {\n padding: 0.75rem;\n flex-wrap: wrap;\n }\n}\n\n.panel-header .panel-title {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex-shrink: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (max-width: 639px) {\n .panel-header .panel-title {\n font-size: 0.875rem;\n max-width: 50%;\n }\n}\n\n.panel-actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .panel-actions {\n gap: 0.25rem;\n }\n\n .panel-actions .checkbox-label {\n font-size: 0;\n gap: 0;\n min-height: 36px;\n padding: 0;\n }\n\n .panel-actions .checkbox-label::after {\n content: \"Auto\";\n font-size: 0.75rem;\n margin-left: 0.25rem;\n }\n}\n\n.sessions-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n min-height: 0;\n position: relative;\n padding: 0.75rem;\n}\n\n/* -----------------------------------------------------------------------------\n Session Cards\n ----------------------------------------------------------------------------- */\n.session-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: 1rem;\n margin-bottom: 0.75rem;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.session-card:last-child {\n margin-bottom: 0;\n}\n\n.session-card:hover {\n box-shadow: var(--mj-shadow-sm);\n border-color: var(--mj-brand-primary);\n}\n\n.session-card.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-brand-accent-subtle);\n}\n\n.session-card:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.session-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.75rem;\n}\n\n.session-info {\n flex: 1;\n min-width: 0;\n}\n\n.session-info .session-title {\n margin: 0 0 0.5rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.session-meta {\n display: flex;\n gap: 1rem;\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n flex-wrap: wrap;\n}\n\n.session-meta .meta-item {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.session-badges {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n margin-top: 0.5rem;\n}\n\n/* -----------------------------------------------------------------------------\n Badges - Chips\n ----------------------------------------------------------------------------- */\n.badge {\n padding: 0.375rem 0.875rem;\n border-radius: var(--mj-radius-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.badge-user {\n background: var(--mj-brand-accent-subtle);\n color: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n}\n\n.badge-migration {\n background: var(--mj-status-success-bg);\n color: var(--mj-status-success-text);\n border: 1px solid var(--mj-status-success);\n}\n\n.badge-type {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border: 1px solid var(--mj-status-warning);\n}\n\n/* -----------------------------------------------------------------------------\n Action Buttons (Icon buttons)\n ----------------------------------------------------------------------------- */\n.action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1rem;\n border-radius: var(--mj-radius-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-width: 44px;\n min-height: 44px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.action-btn-danger:hover {\n background: var(--mj-status-error);\n color: var(--mj-brand-on-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Log Viewer Panel\n ----------------------------------------------------------------------------- */\n.log-viewer-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n overflow: hidden;\n background: var(--mj-bg-surface);\n min-height: 400px;\n}\n\n@media (max-width: 767px) {\n .log-viewer-panel {\n min-height: 350px;\n }\n}\n\n/* Code editor keeps its dark theme for readability (intentionally hardcoded for code syntax) */\n.log-content {\n flex: 1;\n overflow: hidden;\n min-height: 300px;\n height: 100%;\n position: relative;\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content ::ng-deep .cm-editor {\n height: 100%;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n font-size: 0.875rem;\n}\n\n.log-content ::ng-deep .cm-scroller {\n font-family: inherit;\n}\n\n.log-content ::ng-deep .cm-content {\n background: var(--mj-text-primary);\n color: var(--mj-border-strong);\n}\n\n.log-content ::ng-deep .cm-gutters {\n background: var(--mj-text-primary);\n color: var(--mj-text-disabled);\n border-right: 1px solid var(--mj-text-secondary);\n}\n\n.log-content ::ng-deep .cm-activeLineGutter {\n background: var(--mj-text-primary);\n}\n\n.log-content ::ng-deep .cm-activeLine {\n background: rgba(255, 255, 255, 0.04);\n}\n\n/* Expanded Log Viewer */\n.log-viewer-panel.expanded {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 999;\n border-radius: 0;\n margin: 0;\n max-height: none;\n height: 100vh;\n animation: expandIn 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n.log-viewer-panel.expanded .panel-header {\n border-radius: 0;\n}\n\n.log-viewer-panel.expanded .log-content {\n max-height: calc(100vh - 60px);\n min-height: calc(100vh - 60px);\n}\n\n/* -----------------------------------------------------------------------------\n Empty State Override - Different icon.warning styling\n ----------------------------------------------------------------------------- */\n.empty-state .empty-icon.warning {\n color: var(--mj-status-warning);\n}\n\n.empty-state .empty-subtext {\n max-width: 400px;\n}\n\n/* -----------------------------------------------------------------------------\n Info Box\n ----------------------------------------------------------------------------- */\n.info-box {\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-lg);\n padding: 1.5rem;\n margin-top: 1.5rem;\n text-align: left;\n max-width: 500px;\n border: 1px solid var(--mj-border-default);\n}\n\n.info-box h4 {\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.info-box ol {\n margin: 0;\n padding-left: 1.25rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n}\n\n.info-box ol li {\n margin-bottom: 0.5rem;\n}\n\n.info-box code {\n background: var(--mj-bg-surface-active);\n padding: 0.125rem 0.5rem;\n border-radius: var(--mj-radius-sm);\n font-size: 0.8125rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n color: var(--mj-text-primary);\n}\n\n/* -----------------------------------------------------------------------------\n Loading Container Override\n ----------------------------------------------------------------------------- */\n.loading-container {\n min-height: 300px;\n}\n\n.loading-text {\n font-size: 1rem;\n color: var(--mj-text-secondary);\n margin-top: 1rem;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Dialog Overrides - SQL Logging has its own modal patterns\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n background: var(--mj-bg-overlay);\n}\n\n.modal-dialog {\n width: 90%;\n display: flex;\n flex-direction: column;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.modal-dialog.modal-large {\n max-width: 700px;\n}\n\n/* Fullscreen mode */\n.modal-dialog.fullscreen {\n max-width: 100vw;\n width: 100vw;\n max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n margin: 0;\n}\n\n@media (max-width: 639px) {\n .modal-dialog {\n width: 95%;\n max-height: 85vh;\n border-radius: var(--mj-radius-2xl);\n }\n\n .modal-dialog.fullscreen {\n border-radius: 0;\n max-height: 100vh;\n }\n}\n\n.modal-header {\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-header {\n padding: 1rem 1.25rem;\n }\n}\n\n/* Modal Header Actions */\n.modal-header-actions {\n display: flex;\n gap: 0.5rem;\n align-items: center;\n flex-shrink: 0;\n}\n\n.modal-action-btn {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--mj-radius-full);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\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.modal-action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-brand-on-primary);\n}\n\n.modal-action-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.modal-body {\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n@media (max-width: 639px) {\n .modal-body {\n padding: 1rem 1.25rem;\n }\n}\n\n.modal-footer {\n justify-content: flex-end;\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-footer {\n padding: 1rem 1.25rem;\n }\n\n /* Stretch the action buttons to full width on small viewports. */\n .modal-footer button {\n width: 100%;\n justify-content: center;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Form Elements\n ----------------------------------------------------------------------------- */\n.form-group {\n margin-bottom: 1.5rem;\n}\n\n.form-label {\n display: block;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 0.5rem;\n}\n\n.form-input,\n.form-select,\n.form-textarea {\n width: 100%;\n min-height: 44px;\n padding: 0.875rem 1rem;\n border: 2px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font-size: 1rem;\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-input:hover,\n.form-select:hover,\n.form-textarea:hover {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n.form-input:focus,\n.form-select:focus,\n.form-textarea:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n background: var(--mj-bg-surface);\n}\n\n.form-input::placeholder,\n.form-textarea::placeholder {\n color: var(--mj-text-secondary);\n opacity: 0.7;\n}\n\n.form-select {\n cursor: pointer;\n}\n\n.form-hint {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n margin-top: 0.375rem;\n}\n\n.form-checkboxes {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.checkbox-label {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n font-size: 1rem;\n color: var(--mj-text-primary);\n cursor: pointer;\n min-height: 44px;\n padding: 0.25rem 0;\n}\n\n.checkbox-label input[type=\"checkbox\"] {\n width: 20px;\n height: 20px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n flex-shrink: 0;\n}\n\n/* Form Section */\n.form-section {\n margin-top: 1.5rem;\n padding: 1.25rem;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface-sunken);\n}\n\n.form-section-title {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.form-section-title i {\n color: var(--mj-brand-primary);\n font-size: 1.125rem;\n}\n\n.form-textarea {\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n resize: vertical;\n min-height: 100px;\n}\n\n/* -----------------------------------------------------------------------------\n Confirmation Dialog\n ----------------------------------------------------------------------------- */\n.confirm-dialog {\n background: var(--mj-bg-page);\n border-radius: var(--mj-radius-2xl);\n box-shadow: var(--mj-shadow-2xl);\n max-width: 420px;\n width: 90%;\n padding: 2rem;\n text-align: center;\n animation: dialogBounce 0.3s cubic-bezier(0, 0, 0.2, 1);\n}\n\n@media (max-width: 639px) {\n .confirm-dialog {\n padding: 1.5rem;\n border-radius: var(--mj-radius-2xl);\n }\n}\n\n.confirm-dialog-icon {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: var(--mj-status-warning-bg);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n}\n\n.confirm-dialog-icon i {\n font-size: 1.75rem;\n color: var(--mj-status-warning-text);\n}\n\n.confirm-dialog-content {\n margin-bottom: 1.5rem;\n}\n\n.confirm-dialog-title {\n margin: 0 0 0.75rem 0;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.confirm-dialog-message {\n margin: 0;\n font-size: 1rem;\n color: var(--mj-text-secondary);\n line-height: 1.6;\n}\n\n.confirm-dialog-message strong {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n\n.confirm-dialog-details {\n display: block;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-md);\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n.confirm-dialog-actions {\n display: flex;\n gap: 0.75rem;\n justify-content: center;\n}\n\n@media (max-width: 639px) {\n .confirm-dialog-actions {\n flex-direction: column-reverse;\n }\n\n /* Stretch the action buttons to full width on small viewports. */\n .confirm-dialog-actions button {\n width: 100%;\n justify-content: center;\n }\n}\n\n/* -----------------------------------------------------------------------------\n SQL-Logging-specific Animations\n ----------------------------------------------------------------------------- */\n@keyframes expandIn {\n from {\n transform: scale(0.95);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n@keyframes dialogBounce {\n 0% {\n transform: scale(0.9) translateY(10px);\n opacity: 0;\n }\n 70% {\n transform: scale(1.02) translateY(-5px);\n }\n 100% {\n transform: scale(1) translateY(0);\n opacity: 1;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Screen Reader Only\n ----------------------------------------------------------------------------- */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n"] }]
|
|
1288
1285
|
}], () => [{ type: i1.SharedService }, { type: i0.ChangeDetectorRef }], { onEscapeKey: [{
|
|
1289
1286
|
type: HostListener,
|
|
1290
1287
|
args: ['document:keydown.escape']
|