@memberjunction/ng-explorer-settings 3.1.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +15 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-dialog/application-dialog.component.js +329 -190
- package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
- package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
- package/dist/lib/application-management/application-management.component.js +265 -184
- package/dist/lib/application-management/application-management.component.js.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts +1 -0
- package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/entity-permissions.component.js +369 -192
- package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +160 -143
- package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
- package/dist/lib/module.d.ts +17 -21
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/module.js +20 -39
- package/dist/lib/module.js.map +1 -1
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts +113 -0
- package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -0
- package/dist/lib/notification-preferences/notification-preferences.component.js +382 -0
- package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -0
- package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-dialog/role-dialog.component.js +93 -89
- package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
- package/dist/lib/role-management/role-management.component.d.ts +1 -0
- package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
- package/dist/lib/role-management/role-management.component.js +275 -158
- package/dist/lib/role-management/role-management.component.js.map +1 -1
- package/dist/lib/settings/settings.component.d.ts +54 -1
- package/dist/lib/settings/settings.component.d.ts.map +1 -1
- package/dist/lib/settings/settings.component.js +528 -172
- package/dist/lib/settings/settings.component.js.map +1 -1
- package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
- package/dist/lib/shared/settings-card.component.js +21 -18
- package/dist/lib/shared/settings-card.component.js.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.d.ts +70 -10
- package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
- package/dist/lib/sql-logging/sql-logging.component.js +547 -205
- package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
- package/dist/lib/user-app-config/user-app-config.component.d.ts +21 -3
- package/dist/lib/user-app-config/user-app-config.component.d.ts.map +1 -1
- package/dist/lib/user-app-config/user-app-config.component.js +202 -147
- package/dist/lib/user-app-config/user-app-config.component.js.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-dialog/user-dialog.component.js +120 -116
- package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
- package/dist/lib/user-management/user-management.component.d.ts +32 -2
- package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
- package/dist/lib/user-management/user-management.component.js +822 -297
- package/dist/lib/user-management/user-management.component.js.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +31 -2
- package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
- package/dist/lib/user-profile-settings/user-profile-settings.component.js +213 -80
- package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +21 -20
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { Component } from '@angular/core';
|
|
7
|
+
import { Component, HostListener } from '@angular/core';
|
|
8
8
|
import { Subject, interval } from 'rxjs';
|
|
9
9
|
import { takeUntil } from 'rxjs/operators';
|
|
10
10
|
import { Metadata } from '@memberjunction/core';
|
|
@@ -15,101 +15,127 @@ import * as i0 from "@angular/core";
|
|
|
15
15
|
import * as i1 from "@memberjunction/ng-shared";
|
|
16
16
|
import * as i2 from "@angular/forms";
|
|
17
17
|
import * as i3 from "@memberjunction/ng-code-editor";
|
|
18
|
+
import * as i4 from "@memberjunction/ng-shared-generic";
|
|
18
19
|
const _forTrack0 = ($index, $item) => $item.id;
|
|
19
20
|
const _forTrack1 = ($index, $item) => $item.value;
|
|
20
21
|
function SqlLoggingComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
21
22
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
22
|
-
i0.ɵɵelementStart(0, "button",
|
|
23
|
+
i0.ɵɵelementStart(0, "button", 10);
|
|
23
24
|
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.openStartSessionDialog()); });
|
|
24
|
-
i0.ɵɵelement(1, "i",
|
|
25
|
+
i0.ɵɵelement(1, "i", 11);
|
|
25
26
|
i0.ɵɵtext(2, " Start New Session ");
|
|
26
27
|
i0.ɵɵelementEnd();
|
|
27
28
|
} if (rf & 2) {
|
|
28
29
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
29
30
|
i0.ɵɵproperty("disabled", ctx_r1.loading || ctx_r1.activeSessions.length >= ((ctx_r1.sqlLoggingConfig == null ? null : ctx_r1.sqlLoggingConfig.maxActiveSessions) || 5));
|
|
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)" : ""));
|
|
30
32
|
} }
|
|
31
33
|
function SqlLoggingComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
32
|
-
|
|
33
|
-
i0.ɵɵ
|
|
34
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
35
|
+
i0.ɵɵelementStart(0, "div", 5)(1, "button", 12);
|
|
36
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_6_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", 13)(3, "div", 14);
|
|
38
|
+
i0.ɵɵelement(4, "i", 15);
|
|
34
39
|
i0.ɵɵelementEnd();
|
|
35
|
-
i0.ɵɵelementStart(
|
|
36
|
-
i0.ɵɵtext(
|
|
40
|
+
i0.ɵɵelementStart(5, "div", 16)(6, "h3", 17);
|
|
41
|
+
i0.ɵɵtext(7, "Statistics");
|
|
37
42
|
i0.ɵɵelementEnd();
|
|
38
|
-
i0.ɵɵelementStart(
|
|
39
|
-
i0.ɵɵtext(
|
|
43
|
+
i0.ɵɵelementStart(8, "p", 18);
|
|
44
|
+
i0.ɵɵtext(9, "View session statistics and metrics");
|
|
40
45
|
i0.ɵɵelementEnd()()();
|
|
41
|
-
i0.ɵɵ
|
|
42
|
-
i0.ɵɵ
|
|
46
|
+
i0.ɵɵelement(10, "i", 19);
|
|
47
|
+
i0.ɵɵelementEnd();
|
|
48
|
+
i0.ɵɵelementStart(11, "div", 20)(12, "div", 21)(13, "div", 22);
|
|
49
|
+
i0.ɵɵelement(14, "i", 23);
|
|
43
50
|
i0.ɵɵelementEnd();
|
|
44
|
-
i0.ɵɵelementStart(
|
|
45
|
-
i0.ɵɵtext(
|
|
51
|
+
i0.ɵɵelementStart(15, "div", 24)(16, "div", 25);
|
|
52
|
+
i0.ɵɵtext(17);
|
|
46
53
|
i0.ɵɵelementEnd();
|
|
47
|
-
i0.ɵɵelementStart(
|
|
48
|
-
i0.ɵɵtext(
|
|
54
|
+
i0.ɵɵelementStart(18, "div", 26);
|
|
55
|
+
i0.ɵɵtext(19, "Status");
|
|
49
56
|
i0.ɵɵelementEnd()()();
|
|
50
|
-
i0.ɵɵelementStart(
|
|
51
|
-
i0.ɵɵelement(
|
|
57
|
+
i0.ɵɵelementStart(20, "div", 21)(21, "div", 27);
|
|
58
|
+
i0.ɵɵelement(22, "i", 28);
|
|
52
59
|
i0.ɵɵelementEnd();
|
|
53
|
-
i0.ɵɵelementStart(
|
|
54
|
-
i0.ɵɵtext(
|
|
60
|
+
i0.ɵɵelementStart(23, "div", 24)(24, "div", 25);
|
|
61
|
+
i0.ɵɵtext(25);
|
|
55
62
|
i0.ɵɵelementEnd();
|
|
56
|
-
i0.ɵɵelementStart(
|
|
57
|
-
i0.ɵɵtext(
|
|
63
|
+
i0.ɵɵelementStart(26, "div", 26);
|
|
64
|
+
i0.ɵɵtext(27, "Active Sessions");
|
|
58
65
|
i0.ɵɵelementEnd()()();
|
|
59
|
-
i0.ɵɵelementStart(
|
|
60
|
-
i0.ɵɵelement(
|
|
66
|
+
i0.ɵɵelementStart(28, "div", 21)(29, "div", 29);
|
|
67
|
+
i0.ɵɵelement(30, "i", 30);
|
|
61
68
|
i0.ɵɵelementEnd();
|
|
62
|
-
i0.ɵɵelementStart(
|
|
63
|
-
i0.ɵɵtext(
|
|
69
|
+
i0.ɵɵelementStart(31, "div", 24)(32, "div", 25);
|
|
70
|
+
i0.ɵɵtext(33);
|
|
64
71
|
i0.ɵɵelementEnd();
|
|
65
|
-
i0.ɵɵelementStart(
|
|
66
|
-
i0.ɵɵtext(
|
|
67
|
-
i0.ɵɵelementEnd()()()
|
|
72
|
+
i0.ɵɵelementStart(34, "div", 26);
|
|
73
|
+
i0.ɵɵtext(35, "Max Sessions");
|
|
74
|
+
i0.ɵɵelementEnd()()();
|
|
75
|
+
i0.ɵɵelementStart(36, "div", 21)(37, "div", 31);
|
|
76
|
+
i0.ɵɵelement(38, "i", 32);
|
|
77
|
+
i0.ɵɵelementEnd();
|
|
78
|
+
i0.ɵɵelementStart(39, "div", 24)(40, "div", 25);
|
|
79
|
+
i0.ɵɵtext(41);
|
|
80
|
+
i0.ɵɵelementEnd();
|
|
81
|
+
i0.ɵɵelementStart(42, "div", 26);
|
|
82
|
+
i0.ɵɵtext(43, "Total Statements");
|
|
83
|
+
i0.ɵɵelementEnd()()()()();
|
|
68
84
|
} if (rf & 2) {
|
|
69
85
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
70
|
-
i0.ɵɵadvance(
|
|
71
|
-
i0.ɵɵ
|
|
72
|
-
i0.ɵɵ
|
|
73
|
-
i0.ɵɵ
|
|
74
|
-
i0.ɵɵ
|
|
75
|
-
i0.ɵɵ
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵ
|
|
86
|
+
i0.ɵɵadvance();
|
|
87
|
+
i0.ɵɵclassProp("expanded", ctx_r1.showStats);
|
|
88
|
+
i0.ɵɵattribute("aria-expanded", ctx_r1.showStats);
|
|
89
|
+
i0.ɵɵadvance(10);
|
|
90
|
+
i0.ɵɵclassProp("visible", ctx_r1.showStats);
|
|
91
|
+
i0.ɵɵadvance(5);
|
|
92
|
+
i0.ɵɵattribute("aria-label", "Status: " + (ctx_r1.configEnabled ? "Enabled" : "Disabled"));
|
|
93
|
+
i0.ɵɵadvance();
|
|
94
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.configEnabled ? "Enabled" : "Disabled", " ");
|
|
95
|
+
i0.ɵɵadvance(7);
|
|
96
|
+
i0.ɵɵattribute("aria-label", ctx_r1.activeSessions.length + " active sessions");
|
|
97
|
+
i0.ɵɵadvance();
|
|
98
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.activeSessions.length, " ");
|
|
99
|
+
i0.ɵɵadvance(7);
|
|
100
|
+
i0.ɵɵattribute("aria-label", ((ctx_r1.sqlLoggingConfig == null ? null : ctx_r1.sqlLoggingConfig.maxActiveSessions) || 5) + " maximum sessions allowed");
|
|
101
|
+
i0.ɵɵadvance();
|
|
102
|
+
i0.ɵɵtextInterpolate1(" ", (ctx_r1.sqlLoggingConfig == null ? null : ctx_r1.sqlLoggingConfig.maxActiveSessions) || 5, " ");
|
|
103
|
+
i0.ɵɵadvance(7);
|
|
104
|
+
i0.ɵɵattribute("aria-label", ctx_r1.getTotalStatementCount() + " total SQL statements captured");
|
|
105
|
+
i0.ɵɵadvance();
|
|
106
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getTotalStatementCount(), " ");
|
|
78
107
|
} }
|
|
79
108
|
function SqlLoggingComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
-
i0.ɵɵelementStart(0, "div", 6)
|
|
81
|
-
i0.ɵɵelement(
|
|
109
|
+
i0.ɵɵelementStart(0, "div", 6);
|
|
110
|
+
i0.ɵɵelement(1, "mj-loading", 33);
|
|
82
111
|
i0.ɵɵelementEnd();
|
|
83
|
-
i0.ɵɵelementStart(5, "div", 25);
|
|
84
|
-
i0.ɵɵtext(6, "Loading SQL logging configuration...");
|
|
85
|
-
i0.ɵɵelementEnd()();
|
|
86
112
|
} }
|
|
87
113
|
function SqlLoggingComponent_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
88
|
-
const
|
|
89
|
-
i0.ɵɵelementStart(0, "div",
|
|
90
|
-
i0.ɵɵelement(1, "i",
|
|
91
|
-
i0.ɵɵelementStart(2, "p",
|
|
114
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
115
|
+
i0.ɵɵelementStart(0, "div", 34);
|
|
116
|
+
i0.ɵɵelement(1, "i", 37);
|
|
117
|
+
i0.ɵɵelementStart(2, "p", 38);
|
|
92
118
|
i0.ɵɵtext(3, "Access Denied");
|
|
93
119
|
i0.ɵɵelementEnd();
|
|
94
|
-
i0.ɵɵelementStart(4, "p",
|
|
120
|
+
i0.ɵɵelementStart(4, "p", 39);
|
|
95
121
|
i0.ɵɵtext(5, "SQL logging requires Owner privileges. Please contact your system administrator for access.");
|
|
96
122
|
i0.ɵɵelementEnd();
|
|
97
|
-
i0.ɵɵelementStart(6, "button",
|
|
98
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_1_Template_button_click_6_listener() { i0.ɵɵrestoreView(
|
|
99
|
-
i0.ɵɵelement(7, "i",
|
|
123
|
+
i0.ɵɵelementStart(6, "button", 40);
|
|
124
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_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", 41);
|
|
100
126
|
i0.ɵɵtext(8, " Refresh Permissions ");
|
|
101
127
|
i0.ɵɵelementEnd()();
|
|
102
128
|
} }
|
|
103
129
|
function SqlLoggingComponent_Conditional_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
104
|
-
i0.ɵɵelementStart(0, "div",
|
|
105
|
-
i0.ɵɵelement(1, "i",
|
|
106
|
-
i0.ɵɵelementStart(2, "p",
|
|
130
|
+
i0.ɵɵelementStart(0, "div", 34);
|
|
131
|
+
i0.ɵɵelement(1, "i", 42);
|
|
132
|
+
i0.ɵɵelementStart(2, "p", 38);
|
|
107
133
|
i0.ɵɵtext(3, "SQL Logging Disabled");
|
|
108
134
|
i0.ɵɵelementEnd();
|
|
109
|
-
i0.ɵɵelementStart(4, "p",
|
|
135
|
+
i0.ɵɵelementStart(4, "p", 39);
|
|
110
136
|
i0.ɵɵtext(5, "SQL logging is not enabled in the server configuration.");
|
|
111
137
|
i0.ɵɵelementEnd();
|
|
112
|
-
i0.ɵɵelementStart(6, "div",
|
|
138
|
+
i0.ɵɵelementStart(6, "div", 43)(7, "h4");
|
|
113
139
|
i0.ɵɵtext(8, "To enable SQL logging:");
|
|
114
140
|
i0.ɵɵelementEnd();
|
|
115
141
|
i0.ɵɵelementStart(9, "ol")(10, "li");
|
|
@@ -127,26 +153,26 @@ function SqlLoggingComponent_Conditional_8_Conditional_2_Template(rf, ctx) { if
|
|
|
127
153
|
i0.ɵɵelementEnd()()()();
|
|
128
154
|
} }
|
|
129
155
|
function SqlLoggingComponent_Conditional_8_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
130
|
-
const
|
|
131
|
-
i0.ɵɵelementStart(0, "div",
|
|
132
|
-
i0.ɵɵelement(1, "i",
|
|
133
|
-
i0.ɵɵelementStart(2, "p",
|
|
156
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
157
|
+
i0.ɵɵelementStart(0, "div", 35);
|
|
158
|
+
i0.ɵɵelement(1, "i", 44);
|
|
159
|
+
i0.ɵɵelementStart(2, "p", 38);
|
|
134
160
|
i0.ɵɵtext(3, "No Active Sessions");
|
|
135
161
|
i0.ɵɵelementEnd();
|
|
136
|
-
i0.ɵɵelementStart(4, "p",
|
|
162
|
+
i0.ɵɵelementStart(4, "p", 39);
|
|
137
163
|
i0.ɵɵtext(5, "Start a new SQL logging session to begin capturing SQL statements.");
|
|
138
164
|
i0.ɵɵelementEnd();
|
|
139
|
-
i0.ɵɵelementStart(6, "button",
|
|
140
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_3_Template_button_click_6_listener() { i0.ɵɵrestoreView(
|
|
141
|
-
i0.ɵɵelement(7, "i",
|
|
165
|
+
i0.ɵɵelementStart(6, "button", 45);
|
|
166
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_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", 11);
|
|
142
168
|
i0.ɵɵtext(8, " Start New Session ");
|
|
143
169
|
i0.ɵɵelementEnd()();
|
|
144
170
|
} }
|
|
145
171
|
function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
146
|
-
const
|
|
147
|
-
i0.ɵɵelementStart(0, "button",
|
|
148
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(
|
|
149
|
-
i0.ɵɵelement(1, "i",
|
|
172
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
173
|
+
i0.ɵɵelementStart(0, "button", 53);
|
|
174
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_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", 54);
|
|
150
176
|
i0.ɵɵtext(2, " Stop All ");
|
|
151
177
|
i0.ɵɵelementEnd();
|
|
152
178
|
} if (rf & 2) {
|
|
@@ -154,74 +180,81 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template(
|
|
|
154
180
|
i0.ɵɵproperty("disabled", ctx_r1.loading);
|
|
155
181
|
} }
|
|
156
182
|
function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
157
|
-
i0.ɵɵelementStart(0, "span",
|
|
158
|
-
i0.ɵɵelement(1, "i",
|
|
183
|
+
i0.ɵɵelementStart(0, "span", 64);
|
|
184
|
+
i0.ɵɵelement(1, "i", 67);
|
|
159
185
|
i0.ɵɵtext(2, " User Filtered ");
|
|
160
186
|
i0.ɵɵelementEnd();
|
|
161
187
|
} }
|
|
162
188
|
function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
163
|
-
i0.ɵɵelementStart(0, "span",
|
|
164
|
-
i0.ɵɵelement(1, "i",
|
|
189
|
+
i0.ɵɵelementStart(0, "span", 65);
|
|
190
|
+
i0.ɵɵelement(1, "i", 68);
|
|
165
191
|
i0.ɵɵtext(2, " Migration ");
|
|
166
192
|
i0.ɵɵelementEnd();
|
|
167
193
|
} }
|
|
168
194
|
function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
169
|
-
const
|
|
170
|
-
i0.ɵɵelementStart(0, "div",
|
|
171
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template_div_click_0_listener() { const
|
|
172
|
-
i0.ɵɵelementStart(1, "div",
|
|
195
|
+
const _r7 = i0.ɵɵgetCurrentView();
|
|
196
|
+
i0.ɵɵelementStart(0, "div", 55);
|
|
197
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_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_8_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_8_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", 56)(2, "div", 57)(3, "h4", 58);
|
|
173
199
|
i0.ɵɵtext(4);
|
|
174
200
|
i0.ɵɵelementEnd();
|
|
175
|
-
i0.ɵɵelementStart(5, "div",
|
|
176
|
-
i0.ɵɵelement(7, "i",
|
|
201
|
+
i0.ɵɵelementStart(5, "div", 59)(6, "span", 60);
|
|
202
|
+
i0.ɵɵelement(7, "i", 61);
|
|
177
203
|
i0.ɵɵtext(8);
|
|
178
204
|
i0.ɵɵelementEnd();
|
|
179
|
-
i0.ɵɵelementStart(9, "span",
|
|
180
|
-
i0.ɵɵelement(10, "i",
|
|
205
|
+
i0.ɵɵelementStart(9, "span", 60);
|
|
206
|
+
i0.ɵɵelement(10, "i", 32);
|
|
181
207
|
i0.ɵɵtext(11);
|
|
182
208
|
i0.ɵɵelementEnd()()();
|
|
183
|
-
i0.ɵɵelementStart(12, "button",
|
|
184
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template_button_click_12_listener($event) { const
|
|
185
|
-
i0.ɵɵelement(13, "i",
|
|
209
|
+
i0.ɵɵelementStart(12, "button", 62);
|
|
210
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_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", 54);
|
|
186
212
|
i0.ɵɵelementEnd()();
|
|
187
|
-
i0.ɵɵelementStart(14, "div",
|
|
188
|
-
i0.ɵɵtemplate(15, SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Conditional_15_Template, 3, 0, "span",
|
|
189
|
-
i0.ɵɵelementStart(17, "span",
|
|
213
|
+
i0.ɵɵelementStart(14, "div", 63);
|
|
214
|
+
i0.ɵɵtemplate(15, SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Conditional_15_Template, 3, 0, "span", 64)(16, SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Conditional_16_Template, 3, 0, "span", 65);
|
|
215
|
+
i0.ɵɵelementStart(17, "span", 66);
|
|
190
216
|
i0.ɵɵtext(18);
|
|
191
217
|
i0.ɵɵelementEnd()()();
|
|
192
218
|
} if (rf & 2) {
|
|
193
|
-
const
|
|
219
|
+
const session_r8 = ctx.$implicit;
|
|
194
220
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
195
|
-
i0.ɵɵclassProp("selected", (ctx_r1.selectedSession == null ? null : ctx_r1.selectedSession.id) ===
|
|
221
|
+
i0.ɵɵclassProp("selected", (ctx_r1.selectedSession == null ? null : ctx_r1.selectedSession.id) === session_r8.id);
|
|
222
|
+
i0.ɵɵattribute("aria-label", "Session: " + session_r8.sessionName + ", " + session_r8.statementCount + " statements, duration " + ctx_r1.getSessionDuration(session_r8.startTime))("aria-selected", (ctx_r1.selectedSession == null ? null : ctx_r1.selectedSession.id) === session_r8.id);
|
|
196
223
|
i0.ɵɵadvance(4);
|
|
197
|
-
i0.ɵɵtextInterpolate(
|
|
224
|
+
i0.ɵɵtextInterpolate(session_r8.sessionName);
|
|
198
225
|
i0.ɵɵadvance(4);
|
|
199
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r1.getSessionDuration(
|
|
226
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.getSessionDuration(session_r8.startTime), " ");
|
|
200
227
|
i0.ɵɵadvance(3);
|
|
201
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
202
|
-
i0.ɵɵadvance(4);
|
|
203
|
-
i0.ɵɵconditional(session_r7.filterByUserId ? 15 : -1);
|
|
228
|
+
i0.ɵɵtextInterpolate1(" ", session_r8.statementCount, " statements ");
|
|
204
229
|
i0.ɵɵadvance();
|
|
205
|
-
i0.ɵɵ
|
|
230
|
+
i0.ɵɵattribute("aria-label", "Stop session " + session_r8.sessionName);
|
|
231
|
+
i0.ɵɵadvance(3);
|
|
232
|
+
i0.ɵɵconditional(session_r8.filterByUserId ? 15 : -1);
|
|
233
|
+
i0.ɵɵadvance();
|
|
234
|
+
i0.ɵɵconditional((session_r8.options == null ? null : session_r8.options.formatAsMigration) ? 16 : -1);
|
|
206
235
|
i0.ɵɵadvance(2);
|
|
207
|
-
i0.ɵɵtextInterpolate1(" ", (
|
|
236
|
+
i0.ɵɵtextInterpolate1(" ", (session_r8.options == null ? null : session_r8.options.statementTypes) || "both", " ");
|
|
208
237
|
} }
|
|
209
238
|
function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
210
|
-
const
|
|
211
|
-
i0.ɵɵelementStart(0, "div",
|
|
239
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
240
|
+
i0.ɵɵelementStart(0, "div", 47)(1, "h3", 48);
|
|
212
241
|
i0.ɵɵtext(2);
|
|
213
242
|
i0.ɵɵelementEnd();
|
|
214
|
-
i0.ɵɵelementStart(3, "div",
|
|
215
|
-
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template_input_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(
|
|
243
|
+
i0.ɵɵelementStart(3, "div", 69)(4, "label", 70)(5, "input", 71);
|
|
244
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_8_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); });
|
|
216
245
|
i0.ɵɵelementEnd();
|
|
217
246
|
i0.ɵɵtext(6, " Auto-refresh ");
|
|
218
247
|
i0.ɵɵelementEnd();
|
|
219
|
-
i0.ɵɵelementStart(7, "button",
|
|
220
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template_button_click_7_listener() { i0.ɵɵrestoreView(
|
|
221
|
-
i0.ɵɵelement(8, "i",
|
|
248
|
+
i0.ɵɵelementStart(7, "button", 72);
|
|
249
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_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)); });
|
|
250
|
+
i0.ɵɵelement(8, "i", 41);
|
|
251
|
+
i0.ɵɵelementEnd();
|
|
252
|
+
i0.ɵɵelementStart(9, "button", 73);
|
|
253
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleLogViewerExpand()); });
|
|
254
|
+
i0.ɵɵelement(10, "i", 74);
|
|
222
255
|
i0.ɵɵelementEnd()()();
|
|
223
|
-
i0.ɵɵelementStart(
|
|
224
|
-
i0.ɵɵelement(
|
|
256
|
+
i0.ɵɵelementStart(11, "div", 75);
|
|
257
|
+
i0.ɵɵelement(12, "mj-code-editor", 76);
|
|
225
258
|
i0.ɵɵelementEnd();
|
|
226
259
|
} if (rf & 2) {
|
|
227
260
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
@@ -231,30 +264,34 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template
|
|
|
231
264
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.autoRefresh);
|
|
232
265
|
i0.ɵɵadvance(3);
|
|
233
266
|
i0.ɵɵclassProp("fa-spin", ctx_r1.loading);
|
|
267
|
+
i0.ɵɵadvance();
|
|
268
|
+
i0.ɵɵattribute("aria-label", ctx_r1.isLogViewerExpanded ? "Collapse log viewer" : "Expand log viewer to fullscreen")("aria-expanded", ctx_r1.isLogViewerExpanded);
|
|
269
|
+
i0.ɵɵadvance();
|
|
270
|
+
i0.ɵɵclassProp("fa-expand", !ctx_r1.isLogViewerExpanded)("fa-compress", ctx_r1.isLogViewerExpanded);
|
|
234
271
|
i0.ɵɵadvance(2);
|
|
235
272
|
i0.ɵɵproperty("value", ctx_r1.logContent)("readonly", true)("disabled", true)("language", "sql")("setup", "basic")("lineWrapping", true)("highlightWhitespace", false);
|
|
236
273
|
} }
|
|
237
274
|
function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
238
|
-
i0.ɵɵelementStart(0, "div",
|
|
239
|
-
i0.ɵɵelement(1, "i",
|
|
240
|
-
i0.ɵɵelementStart(2, "p",
|
|
275
|
+
i0.ɵɵelementStart(0, "div", 35);
|
|
276
|
+
i0.ɵɵelement(1, "i", 77);
|
|
277
|
+
i0.ɵɵelementStart(2, "p", 38);
|
|
241
278
|
i0.ɵɵtext(3, "Select a Session");
|
|
242
279
|
i0.ɵɵelementEnd();
|
|
243
|
-
i0.ɵɵelementStart(4, "p",
|
|
280
|
+
i0.ɵɵelementStart(4, "p", 39);
|
|
244
281
|
i0.ɵɵtext(5, "Choose a session from the list to view its SQL log.");
|
|
245
282
|
i0.ɵɵelementEnd()();
|
|
246
283
|
} }
|
|
247
284
|
function SqlLoggingComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
248
|
-
i0.ɵɵelementStart(0, "div",
|
|
285
|
+
i0.ɵɵelementStart(0, "div", 36)(1, "div", 46)(2, "div", 47)(3, "h3", 48);
|
|
249
286
|
i0.ɵɵtext(4, "Active Sessions");
|
|
250
287
|
i0.ɵɵelementEnd();
|
|
251
|
-
i0.ɵɵtemplate(5, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template, 3, 1, "button",
|
|
288
|
+
i0.ɵɵtemplate(5, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template, 3, 1, "button", 49);
|
|
252
289
|
i0.ɵɵelementEnd();
|
|
253
|
-
i0.ɵɵelementStart(6, "div",
|
|
254
|
-
i0.ɵɵrepeaterCreate(7, SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template, 19,
|
|
290
|
+
i0.ɵɵelementStart(6, "div", 50);
|
|
291
|
+
i0.ɵɵrepeaterCreate(7, SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template, 19, 11, "div", 51, _forTrack0);
|
|
255
292
|
i0.ɵɵelementEnd()();
|
|
256
|
-
i0.ɵɵelementStart(9, "div",
|
|
257
|
-
i0.ɵɵtemplate(10, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template,
|
|
293
|
+
i0.ɵɵelementStart(9, "div", 52);
|
|
294
|
+
i0.ɵɵtemplate(10, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template, 13, 17)(11, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_11_Template, 6, 0, "div", 35);
|
|
258
295
|
i0.ɵɵelementEnd()();
|
|
259
296
|
} if (rf & 2) {
|
|
260
297
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -262,106 +299,293 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if
|
|
|
262
299
|
i0.ɵɵconditional(ctx_r1.activeSessions.length > 0 ? 5 : -1);
|
|
263
300
|
i0.ɵɵadvance(2);
|
|
264
301
|
i0.ɵɵrepeater(ctx_r1.activeSessions);
|
|
265
|
-
i0.ɵɵadvance(
|
|
302
|
+
i0.ɵɵadvance(2);
|
|
303
|
+
i0.ɵɵclassProp("expanded", ctx_r1.isLogViewerExpanded);
|
|
304
|
+
i0.ɵɵadvance();
|
|
266
305
|
i0.ɵɵconditional(ctx_r1.selectedSession ? 10 : 11);
|
|
267
306
|
} }
|
|
268
307
|
function SqlLoggingComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
269
308
|
i0.ɵɵelementStart(0, "div", 7);
|
|
270
|
-
i0.ɵɵtemplate(1, SqlLoggingComponent_Conditional_8_Conditional_1_Template, 9, 0, "div",
|
|
309
|
+
i0.ɵɵtemplate(1, SqlLoggingComponent_Conditional_8_Conditional_1_Template, 9, 0, "div", 34)(2, SqlLoggingComponent_Conditional_8_Conditional_2_Template, 19, 0, "div", 34)(3, SqlLoggingComponent_Conditional_8_Conditional_3_Template, 9, 0, "div", 35)(4, SqlLoggingComponent_Conditional_8_Conditional_4_Template, 12, 4, "div", 36);
|
|
271
310
|
i0.ɵɵelementEnd();
|
|
272
311
|
} if (rf & 2) {
|
|
273
312
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
274
313
|
i0.ɵɵadvance();
|
|
275
314
|
i0.ɵɵconditional(!ctx_r1.isOwner ? 1 : !ctx_r1.configEnabled ? 2 : ctx_r1.activeSessions.length === 0 ? 3 : 4);
|
|
276
315
|
} }
|
|
277
|
-
function
|
|
278
|
-
i0.ɵɵelementStart(0, "option",
|
|
316
|
+
function SqlLoggingComponent_Conditional_9_For_29_Template(rf, ctx) { if (rf & 1) {
|
|
317
|
+
i0.ɵɵelementStart(0, "option", 96);
|
|
318
|
+
i0.ɵɵtext(1);
|
|
319
|
+
i0.ɵɵelementEnd();
|
|
320
|
+
} if (rf & 2) {
|
|
321
|
+
const option_r11 = ctx.$implicit;
|
|
322
|
+
i0.ɵɵproperty("value", option_r11.value);
|
|
323
|
+
i0.ɵɵadvance();
|
|
324
|
+
i0.ɵɵtextInterpolate(option_r11.text);
|
|
325
|
+
} }
|
|
326
|
+
function SqlLoggingComponent_Conditional_9_For_51_Template(rf, ctx) { if (rf & 1) {
|
|
327
|
+
i0.ɵɵelementStart(0, "option", 96);
|
|
279
328
|
i0.ɵɵtext(1);
|
|
280
329
|
i0.ɵɵelementEnd();
|
|
281
330
|
} if (rf & 2) {
|
|
282
|
-
const
|
|
283
|
-
i0.ɵɵproperty("value",
|
|
331
|
+
const option_r12 = ctx.$implicit;
|
|
332
|
+
i0.ɵɵproperty("value", option_r12.value);
|
|
284
333
|
i0.ɵɵadvance();
|
|
285
|
-
i0.ɵɵtextInterpolate(
|
|
334
|
+
i0.ɵɵtextInterpolate(option_r12.text);
|
|
335
|
+
} }
|
|
336
|
+
function SqlLoggingComponent_Conditional_9_Conditional_64_Template(rf, ctx) { if (rf & 1) {
|
|
337
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
338
|
+
i0.ɵɵelementStart(0, "div", 87)(1, "label", 115);
|
|
339
|
+
i0.ɵɵtext(2, "Default Schema Name");
|
|
340
|
+
i0.ɵɵelementEnd();
|
|
341
|
+
i0.ɵɵelementStart(3, "input", 116);
|
|
342
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
343
|
+
i0.ɵɵelementEnd();
|
|
344
|
+
i0.ɵɵelementStart(4, "div", 117);
|
|
345
|
+
i0.ɵɵtext(5, "Schema name to replace with ${flyway:defaultSchema} placeholder.");
|
|
346
|
+
i0.ɵɵelementEnd()();
|
|
347
|
+
} if (rf & 2) {
|
|
348
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
349
|
+
i0.ɵɵadvance(3);
|
|
350
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.defaultSchemaName);
|
|
351
|
+
} }
|
|
352
|
+
function SqlLoggingComponent_Conditional_9_Conditional_73_Template(rf, ctx) { if (rf & 1) {
|
|
353
|
+
i0.ɵɵelement(0, "i", 118);
|
|
354
|
+
i0.ɵɵtext(1, " Starting... ");
|
|
355
|
+
} }
|
|
356
|
+
function SqlLoggingComponent_Conditional_9_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
357
|
+
i0.ɵɵelement(0, "i", 11);
|
|
358
|
+
i0.ɵɵtext(1, " Start Session ");
|
|
286
359
|
} }
|
|
287
360
|
function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
288
|
-
const
|
|
289
|
-
i0.ɵɵelementStart(0, "div",
|
|
290
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_0_listener() { i0.ɵɵrestoreView(
|
|
291
|
-
i0.ɵɵelementStart(1, "div",
|
|
292
|
-
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(
|
|
293
|
-
i0.ɵɵelementStart(2, "div",
|
|
294
|
-
i0.ɵɵelement(4, "i",
|
|
361
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
362
|
+
i0.ɵɵelementStart(0, "div", 78);
|
|
363
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
|
|
364
|
+
i0.ɵɵelementStart(1, "div", 79);
|
|
365
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r10); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
366
|
+
i0.ɵɵelementStart(2, "div", 80)(3, "h3", 81);
|
|
367
|
+
i0.ɵɵelement(4, "i", 11);
|
|
295
368
|
i0.ɵɵtext(5, " Start SQL Logging Session ");
|
|
296
369
|
i0.ɵɵelementEnd();
|
|
297
|
-
i0.ɵɵelementStart(6, "button",
|
|
298
|
-
i0.ɵɵlistener("click", function
|
|
299
|
-
i0.ɵɵelement(
|
|
370
|
+
i0.ɵɵelementStart(6, "div", 82)(7, "button", 83);
|
|
371
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleStartDialogFullscreen()); });
|
|
372
|
+
i0.ɵɵelement(8, "i", 74);
|
|
373
|
+
i0.ɵɵelementEnd();
|
|
374
|
+
i0.ɵɵelementStart(9, "button", 84);
|
|
375
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
|
|
376
|
+
i0.ɵɵelement(10, "i", 85);
|
|
377
|
+
i0.ɵɵelementEnd()()();
|
|
378
|
+
i0.ɵɵelementStart(11, "div", 86)(12, "div", 87)(13, "label", 88);
|
|
379
|
+
i0.ɵɵtext(14, "Session Name");
|
|
380
|
+
i0.ɵɵelementEnd();
|
|
381
|
+
i0.ɵɵelementStart(15, "input", 89);
|
|
382
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
383
|
+
i0.ɵɵelementEnd();
|
|
384
|
+
i0.ɵɵelementStart(16, "div", 90);
|
|
385
|
+
i0.ɵɵtext(17, "A descriptive name to identify this logging session");
|
|
300
386
|
i0.ɵɵelementEnd()();
|
|
301
|
-
i0.ɵɵelementStart(
|
|
302
|
-
i0.ɵɵtext(
|
|
387
|
+
i0.ɵɵelementStart(18, "div", 87)(19, "label", 91);
|
|
388
|
+
i0.ɵɵtext(20, "File Name");
|
|
303
389
|
i0.ɵɵelementEnd();
|
|
304
|
-
i0.ɵɵelementStart(
|
|
305
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
390
|
+
i0.ɵɵelementStart(21, "input", 92);
|
|
391
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
392
|
+
i0.ɵɵelementEnd();
|
|
393
|
+
i0.ɵɵelementStart(22, "div", 93);
|
|
394
|
+
i0.ɵɵtext(23, "The SQL log will be saved to this file");
|
|
306
395
|
i0.ɵɵelementEnd()();
|
|
307
|
-
i0.ɵɵelementStart(
|
|
308
|
-
i0.ɵɵtext(
|
|
396
|
+
i0.ɵɵelementStart(24, "div", 87)(25, "label", 94);
|
|
397
|
+
i0.ɵɵtext(26, "Statement Types");
|
|
309
398
|
i0.ɵɵelementEnd();
|
|
310
|
-
i0.ɵɵelementStart(
|
|
311
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
399
|
+
i0.ɵɵelementStart(27, "select", 95);
|
|
400
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
401
|
+
i0.ɵɵrepeaterCreate(28, SqlLoggingComponent_Conditional_9_For_29_Template, 2, 2, "option", 96, _forTrack1);
|
|
312
402
|
i0.ɵɵelementEnd();
|
|
313
|
-
i0.ɵɵelementStart(
|
|
314
|
-
i0.ɵɵtext(
|
|
403
|
+
i0.ɵɵelementStart(30, "div", 97);
|
|
404
|
+
i0.ɵɵtext(31, "Filter which types of SQL statements to capture");
|
|
315
405
|
i0.ɵɵelementEnd()();
|
|
316
|
-
i0.ɵɵelementStart(
|
|
317
|
-
i0.ɵɵ
|
|
406
|
+
i0.ɵɵelementStart(32, "div", 98)(33, "label", 70)(34, "input", 99);
|
|
407
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
408
|
+
i0.ɵɵelementEnd();
|
|
409
|
+
i0.ɵɵtext(35, " Filter to my SQL statements only ");
|
|
410
|
+
i0.ɵɵelementEnd();
|
|
411
|
+
i0.ɵɵelementStart(36, "label", 70)(37, "input", 99);
|
|
412
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
413
|
+
i0.ɵɵelementEnd();
|
|
414
|
+
i0.ɵɵtext(38, " Format as migration file ");
|
|
415
|
+
i0.ɵɵelementEnd();
|
|
416
|
+
i0.ɵɵelementStart(39, "label", 70)(40, "input", 99);
|
|
417
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
318
418
|
i0.ɵɵelementEnd();
|
|
319
|
-
i0.ɵɵ
|
|
320
|
-
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_select_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.statementTypes, $event) || (ctx_r1.newSessionOptions.statementTypes = $event); return i0.ɵɵresetView($event); });
|
|
321
|
-
i0.ɵɵrepeaterCreate(23, SqlLoggingComponent_Conditional_9_For_24_Template, 2, 2, "option", 80, _forTrack1);
|
|
419
|
+
i0.ɵɵtext(41, " Pretty print SQL statements ");
|
|
322
420
|
i0.ɵɵelementEnd()();
|
|
323
|
-
i0.ɵɵelementStart(
|
|
324
|
-
i0.ɵɵ
|
|
421
|
+
i0.ɵɵelementStart(42, "div", 100)(43, "h4", 101);
|
|
422
|
+
i0.ɵɵelement(44, "i", 102);
|
|
423
|
+
i0.ɵɵtext(45, " SQL Pattern Filtering ");
|
|
325
424
|
i0.ɵɵelementEnd();
|
|
326
|
-
i0.ɵɵ
|
|
425
|
+
i0.ɵɵelementStart(46, "div", 87)(47, "label", 103);
|
|
426
|
+
i0.ɵɵtext(48, "Filter Mode");
|
|
327
427
|
i0.ɵɵelementEnd();
|
|
328
|
-
i0.ɵɵelementStart(
|
|
329
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
428
|
+
i0.ɵɵelementStart(49, "select", 104);
|
|
429
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
430
|
+
i0.ɵɵrepeaterCreate(50, SqlLoggingComponent_Conditional_9_For_51_Template, 2, 2, "option", 96, _forTrack1);
|
|
330
431
|
i0.ɵɵelementEnd();
|
|
331
|
-
i0.ɵɵ
|
|
432
|
+
i0.ɵɵelementStart(52, "div", 105);
|
|
433
|
+
i0.ɵɵtext(53, "Exclude: Skip SQL matching any pattern. Include: Only log SQL matching a pattern.");
|
|
434
|
+
i0.ɵɵelementEnd()();
|
|
435
|
+
i0.ɵɵelementStart(54, "div", 87)(55, "label", 106);
|
|
436
|
+
i0.ɵɵtext(56, "Filter Patterns (one per line or comma-separated)");
|
|
332
437
|
i0.ɵɵelementEnd();
|
|
333
|
-
i0.ɵɵelementStart(
|
|
334
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
438
|
+
i0.ɵɵelementStart(57, "textarea", 107);
|
|
439
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
335
440
|
i0.ɵɵelementEnd();
|
|
336
|
-
i0.ɵɵ
|
|
441
|
+
i0.ɵɵelementStart(58, "div", 108);
|
|
442
|
+
i0.ɵɵtext(59, "Supports wildcards (*) and regex (/pattern/flags). Example: *spCreate* matches any SP starting with spCreate.");
|
|
337
443
|
i0.ɵɵelementEnd()()();
|
|
338
|
-
i0.ɵɵelementStart(
|
|
339
|
-
i0.ɵɵ
|
|
340
|
-
i0.ɵɵtext(
|
|
341
|
-
i0.ɵɵelementEnd();
|
|
342
|
-
i0.ɵɵ
|
|
343
|
-
i0.ɵɵ
|
|
344
|
-
i0.ɵɵ
|
|
345
|
-
i0.ɵɵ
|
|
444
|
+
i0.ɵɵelementStart(60, "div", 100)(61, "h4", 101);
|
|
445
|
+
i0.ɵɵelement(62, "i", 109);
|
|
446
|
+
i0.ɵɵtext(63, " Advanced Options ");
|
|
447
|
+
i0.ɵɵelementEnd();
|
|
448
|
+
i0.ɵɵtemplate(64, SqlLoggingComponent_Conditional_9_Conditional_64_Template, 6, 1, "div", 87);
|
|
449
|
+
i0.ɵɵelementStart(65, "div", 110)(66, "label", 70)(67, "input", 99);
|
|
450
|
+
i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_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); });
|
|
451
|
+
i0.ɵɵelementEnd();
|
|
452
|
+
i0.ɵɵtext(68, " Verbose Debug Output ");
|
|
453
|
+
i0.ɵɵelementEnd();
|
|
454
|
+
i0.ɵɵelementStart(69, "div", 111);
|
|
455
|
+
i0.ɵɵtext(70, "Log detailed filter decisions to server console (for debugging).");
|
|
456
|
+
i0.ɵɵelementEnd()()()();
|
|
457
|
+
i0.ɵɵelementStart(71, "div", 112)(72, "button", 113);
|
|
458
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_72_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startNewSession()); });
|
|
459
|
+
i0.ɵɵtemplate(73, SqlLoggingComponent_Conditional_9_Conditional_73_Template, 2, 0)(74, SqlLoggingComponent_Conditional_9_Conditional_74_Template, 2, 0);
|
|
460
|
+
i0.ɵɵelementEnd();
|
|
461
|
+
i0.ɵɵelementStart(75, "button", 114);
|
|
462
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_75_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
|
|
463
|
+
i0.ɵɵtext(76, "Cancel");
|
|
346
464
|
i0.ɵɵelementEnd()()()();
|
|
347
465
|
} if (rf & 2) {
|
|
348
466
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
349
|
-
i0.ɵɵadvance(
|
|
467
|
+
i0.ɵɵadvance();
|
|
468
|
+
i0.ɵɵclassProp("fullscreen", ctx_r1.isStartDialogFullscreen);
|
|
469
|
+
i0.ɵɵadvance(6);
|
|
470
|
+
i0.ɵɵattribute("aria-label", ctx_r1.isStartDialogFullscreen ? "Exit fullscreen" : "Enter fullscreen");
|
|
471
|
+
i0.ɵɵadvance();
|
|
472
|
+
i0.ɵɵclassProp("fa-compress", ctx_r1.isStartDialogFullscreen)("fa-expand", !ctx_r1.isStartDialogFullscreen);
|
|
473
|
+
i0.ɵɵadvance(7);
|
|
350
474
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.sessionName);
|
|
351
|
-
i0.ɵɵadvance(
|
|
475
|
+
i0.ɵɵadvance(6);
|
|
352
476
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.fileName);
|
|
353
477
|
i0.ɵɵadvance(6);
|
|
354
478
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.statementTypes);
|
|
355
479
|
i0.ɵɵadvance();
|
|
356
480
|
i0.ɵɵrepeater(ctx_r1.statementTypeOptions);
|
|
357
|
-
i0.ɵɵadvance(
|
|
481
|
+
i0.ɵɵadvance(6);
|
|
358
482
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.filterToCurrentUser);
|
|
359
483
|
i0.ɵɵadvance(3);
|
|
360
484
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.formatAsMigration);
|
|
361
485
|
i0.ɵɵadvance(3);
|
|
362
486
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.prettyPrint);
|
|
487
|
+
i0.ɵɵadvance(9);
|
|
488
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.filterType);
|
|
489
|
+
i0.ɵɵadvance();
|
|
490
|
+
i0.ɵɵrepeater(ctx_r1.filterTypeOptions);
|
|
491
|
+
i0.ɵɵadvance(7);
|
|
492
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.filterPatterns);
|
|
493
|
+
i0.ɵɵadvance(7);
|
|
494
|
+
i0.ɵɵconditional(ctx_r1.newSessionOptions.formatAsMigration ? 64 : -1);
|
|
495
|
+
i0.ɵɵadvance(3);
|
|
496
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.verboseOutput);
|
|
363
497
|
i0.ɵɵadvance(5);
|
|
364
498
|
i0.ɵɵproperty("disabled", ctx_r1.loading);
|
|
499
|
+
i0.ɵɵadvance();
|
|
500
|
+
i0.ɵɵconditional(ctx_r1.loading ? 73 : 74);
|
|
501
|
+
} }
|
|
502
|
+
function SqlLoggingComponent_Conditional_10_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
503
|
+
i0.ɵɵtext(0, " Stop All Sessions? ");
|
|
504
|
+
} }
|
|
505
|
+
function SqlLoggingComponent_Conditional_10_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
506
|
+
i0.ɵɵtext(0, " Stop Session? ");
|
|
507
|
+
} }
|
|
508
|
+
function SqlLoggingComponent_Conditional_10_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
509
|
+
i0.ɵɵtext(0, " Are you sure you want to stop ");
|
|
510
|
+
i0.ɵɵelementStart(1, "strong");
|
|
511
|
+
i0.ɵɵtext(2);
|
|
512
|
+
i0.ɵɵelementEnd();
|
|
513
|
+
i0.ɵɵtext(3, " SQL logging sessions? This action cannot be undone. ");
|
|
514
|
+
} if (rf & 2) {
|
|
515
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
516
|
+
i0.ɵɵadvance(2);
|
|
517
|
+
i0.ɵɵtextInterpolate1("all ", ctx_r1.activeSessions.length, " active");
|
|
518
|
+
} }
|
|
519
|
+
function SqlLoggingComponent_Conditional_10_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
520
|
+
i0.ɵɵtext(0, " Are you sure you want to stop the session ");
|
|
521
|
+
i0.ɵɵelementStart(1, "strong");
|
|
522
|
+
i0.ɵɵtext(2);
|
|
523
|
+
i0.ɵɵelementEnd();
|
|
524
|
+
i0.ɵɵtext(3, "? ");
|
|
525
|
+
i0.ɵɵelementStart(4, "span", 129);
|
|
526
|
+
i0.ɵɵtext(5);
|
|
527
|
+
i0.ɵɵelementEnd();
|
|
528
|
+
} if (rf & 2) {
|
|
529
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
530
|
+
i0.ɵɵadvance(2);
|
|
531
|
+
i0.ɵɵtextInterpolate1("\"", ctx_r1.sessionToStop.sessionName, "\"");
|
|
532
|
+
i0.ɵɵadvance(3);
|
|
533
|
+
i0.ɵɵtextInterpolate1(" This session has captured ", ctx_r1.sessionToStop.statementCount, " SQL statements. ");
|
|
534
|
+
} }
|
|
535
|
+
function SqlLoggingComponent_Conditional_10_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
536
|
+
i0.ɵɵelement(0, "i", 118);
|
|
537
|
+
i0.ɵɵtext(1, " Stopping... ");
|
|
538
|
+
} }
|
|
539
|
+
function SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
540
|
+
i0.ɵɵtext(0, " Stop All Sessions ");
|
|
541
|
+
} }
|
|
542
|
+
function SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
543
|
+
i0.ɵɵtext(0, " Stop Session ");
|
|
544
|
+
} }
|
|
545
|
+
function SqlLoggingComponent_Conditional_10_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
546
|
+
i0.ɵɵelement(0, "i", 54);
|
|
547
|
+
i0.ɵɵtemplate(1, SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_1_Template, 1, 0)(2, SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_2_Template, 1, 0);
|
|
548
|
+
} if (rf & 2) {
|
|
549
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
550
|
+
i0.ɵɵadvance();
|
|
551
|
+
i0.ɵɵconditional(ctx_r1.isStoppingAll ? 1 : 2);
|
|
552
|
+
} }
|
|
553
|
+
function SqlLoggingComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
554
|
+
const _r14 = i0.ɵɵgetCurrentView();
|
|
555
|
+
i0.ɵɵelementStart(0, "div", 119);
|
|
556
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelStopConfirm()); });
|
|
557
|
+
i0.ɵɵelementStart(1, "div", 120);
|
|
558
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r14); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
559
|
+
i0.ɵɵelementStart(2, "div", 121);
|
|
560
|
+
i0.ɵɵelement(3, "i", 122);
|
|
561
|
+
i0.ɵɵelementEnd();
|
|
562
|
+
i0.ɵɵelementStart(4, "div", 123)(5, "h3", 124);
|
|
563
|
+
i0.ɵɵtemplate(6, SqlLoggingComponent_Conditional_10_Conditional_6_Template, 1, 0)(7, SqlLoggingComponent_Conditional_10_Conditional_7_Template, 1, 0);
|
|
564
|
+
i0.ɵɵelementEnd();
|
|
565
|
+
i0.ɵɵelementStart(8, "p", 125);
|
|
566
|
+
i0.ɵɵtemplate(9, SqlLoggingComponent_Conditional_10_Conditional_9_Template, 4, 1)(10, SqlLoggingComponent_Conditional_10_Conditional_10_Template, 6, 2);
|
|
567
|
+
i0.ɵɵelementEnd()();
|
|
568
|
+
i0.ɵɵelementStart(11, "div", 126)(12, "button", 127);
|
|
569
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmStopSession()); });
|
|
570
|
+
i0.ɵɵtemplate(13, SqlLoggingComponent_Conditional_10_Conditional_13_Template, 2, 0)(14, SqlLoggingComponent_Conditional_10_Conditional_14_Template, 3, 1);
|
|
571
|
+
i0.ɵɵelementEnd();
|
|
572
|
+
i0.ɵɵelementStart(15, "button", 128);
|
|
573
|
+
i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelStopConfirm()); });
|
|
574
|
+
i0.ɵɵtext(16, "Cancel");
|
|
575
|
+
i0.ɵɵelementEnd()()()();
|
|
576
|
+
} if (rf & 2) {
|
|
577
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
578
|
+
i0.ɵɵadvance(6);
|
|
579
|
+
i0.ɵɵconditional(ctx_r1.isStoppingAll ? 6 : 7);
|
|
580
|
+
i0.ɵɵadvance(3);
|
|
581
|
+
i0.ɵɵconditional(ctx_r1.isStoppingAll ? 9 : ctx_r1.sessionToStop ? 10 : -1);
|
|
582
|
+
i0.ɵɵadvance(3);
|
|
583
|
+
i0.ɵɵproperty("disabled", ctx_r1.loading);
|
|
584
|
+
i0.ɵɵattribute("aria-label", ctx_r1.isStoppingAll ? "Confirm stop all sessions" : "Confirm stop session");
|
|
585
|
+
i0.ɵɵadvance();
|
|
586
|
+
i0.ɵɵconditional(ctx_r1.loading ? 13 : 14);
|
|
587
|
+
i0.ɵɵadvance(2);
|
|
588
|
+
i0.ɵɵproperty("disabled", ctx_r1.loading);
|
|
365
589
|
} }
|
|
366
590
|
/**
|
|
367
591
|
* Angular component for managing SQL logging sessions in MemberJunction.
|
|
@@ -384,6 +608,7 @@ function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
|
384
608
|
*/
|
|
385
609
|
let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
386
610
|
sharedService;
|
|
611
|
+
cdr;
|
|
387
612
|
destroy$ = new Subject();
|
|
388
613
|
/** Whether the component is currently performing an async operation */
|
|
389
614
|
loading = false;
|
|
@@ -407,6 +632,18 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
407
632
|
refreshInterval = 5000; // 5 seconds
|
|
408
633
|
/** Whether the start session dialog is currently visible */
|
|
409
634
|
showStartSessionDialog = false;
|
|
635
|
+
/** Whether to show the statistics cards section */
|
|
636
|
+
showStats = false;
|
|
637
|
+
/** Whether the log viewer is in expanded (fullscreen) mode */
|
|
638
|
+
isLogViewerExpanded = false;
|
|
639
|
+
/** Whether the start session dialog is in fullscreen mode */
|
|
640
|
+
isStartDialogFullscreen = false;
|
|
641
|
+
/** Whether the stop session confirmation dialog is visible */
|
|
642
|
+
showStopConfirmDialog = false;
|
|
643
|
+
/** Session pending stop confirmation (single session or null for all) */
|
|
644
|
+
sessionToStop = null;
|
|
645
|
+
/** Whether stopping all sessions (vs single session) */
|
|
646
|
+
isStoppingAll = false;
|
|
410
647
|
/** Options for creating a new SQL logging session */
|
|
411
648
|
newSessionOptions = {
|
|
412
649
|
/** Custom filename for the log file */
|
|
@@ -420,20 +657,31 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
420
657
|
/** Whether to format SQL with proper indentation */
|
|
421
658
|
prettyPrint: true,
|
|
422
659
|
/** Human-readable name for the session */
|
|
423
|
-
sessionName: ''
|
|
660
|
+
sessionName: '',
|
|
661
|
+
/** Regex filter options */
|
|
662
|
+
filterPatterns: '', // Comma or newline separated patterns
|
|
663
|
+
filterType: 'exclude',
|
|
664
|
+
verboseOutput: false,
|
|
665
|
+
defaultSchemaName: '__mj', // Default MJ schema
|
|
424
666
|
};
|
|
425
667
|
/** Available options for SQL statement type filtering */
|
|
426
668
|
statementTypeOptions = [
|
|
427
669
|
{ text: 'Both Queries and Mutations', value: 'both' },
|
|
428
670
|
{ text: 'Queries Only', value: 'queries' },
|
|
429
|
-
{ text: 'Mutations Only', value: 'mutations' }
|
|
671
|
+
{ text: 'Mutations Only', value: 'mutations' },
|
|
430
672
|
];
|
|
431
|
-
|
|
673
|
+
/** Options for Regex filter */
|
|
674
|
+
filterTypeOptions = [
|
|
675
|
+
{ text: 'Exclude Matching (default)', value: 'exclude' },
|
|
676
|
+
{ text: 'Include Matching Only', value: 'include' },
|
|
677
|
+
];
|
|
678
|
+
constructor(sharedService, cdr) {
|
|
432
679
|
super();
|
|
433
680
|
this.sharedService = sharedService;
|
|
681
|
+
this.cdr = cdr;
|
|
434
682
|
}
|
|
435
683
|
async GetResourceDisplayName(data) {
|
|
436
|
-
return
|
|
684
|
+
return 'SQL Logging';
|
|
437
685
|
}
|
|
438
686
|
initDashboard() {
|
|
439
687
|
this.startAutoRefresh();
|
|
@@ -483,7 +731,7 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
483
731
|
email: currentUser?.Email,
|
|
484
732
|
type: currentUser?.Type,
|
|
485
733
|
name: currentUser?.Name,
|
|
486
|
-
id: currentUser?.ID
|
|
734
|
+
id: currentUser?.ID,
|
|
487
735
|
});
|
|
488
736
|
// Use the current user from Metadata
|
|
489
737
|
const userToCheck = currentUser;
|
|
@@ -553,9 +801,14 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
553
801
|
formatAsMigration: this.newSessionOptions.formatAsMigration,
|
|
554
802
|
statementTypes: this.newSessionOptions.statementTypes,
|
|
555
803
|
prettyPrint: this.newSessionOptions.prettyPrint,
|
|
556
|
-
sessionName: this.newSessionOptions.sessionName
|
|
557
|
-
|
|
558
|
-
|
|
804
|
+
sessionName: this.newSessionOptions.sessionName,
|
|
805
|
+
// Regex Filter Option
|
|
806
|
+
filterPatterns: this.parseFilterPatterns(this.newSessionOptions.filterPatterns),
|
|
807
|
+
filterType: this.newSessionOptions.filterType,
|
|
808
|
+
verboseOutput: this.newSessionOptions.verboseOutput,
|
|
809
|
+
defaultSchemaName: this.newSessionOptions.defaultSchemaName,
|
|
810
|
+
},
|
|
811
|
+
},
|
|
559
812
|
};
|
|
560
813
|
const result = await dataProvider.ExecuteGQL(mutation, variables);
|
|
561
814
|
if (result.errors) {
|
|
@@ -579,18 +832,12 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
579
832
|
}
|
|
580
833
|
}
|
|
581
834
|
/**
|
|
582
|
-
*
|
|
835
|
+
* Executes the stop operation for a specific SQL logging session.
|
|
836
|
+
* Called after user confirms via the confirmation dialog.
|
|
583
837
|
*
|
|
584
838
|
* @param session - The session object to stop
|
|
585
|
-
* @param event - Optional event to stop propagation
|
|
586
839
|
*/
|
|
587
|
-
async
|
|
588
|
-
if (event) {
|
|
589
|
-
event.stopPropagation();
|
|
590
|
-
}
|
|
591
|
-
if (!confirm(`Stop SQL logging session "${session.sessionName}"?`)) {
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
840
|
+
async executeStopSession(session) {
|
|
594
841
|
try {
|
|
595
842
|
this.loading = true;
|
|
596
843
|
const dataProvider = Metadata.Provider;
|
|
@@ -611,21 +858,19 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
611
858
|
await this.loadActiveSessions();
|
|
612
859
|
}
|
|
613
860
|
catch (error) {
|
|
861
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to stop SQL logging session';
|
|
614
862
|
console.error('Error stopping SQL logging session:', error);
|
|
615
|
-
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${
|
|
863
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${errorMessage}`, 'error', 5000);
|
|
616
864
|
}
|
|
617
865
|
finally {
|
|
618
866
|
this.loading = false;
|
|
619
867
|
}
|
|
620
868
|
}
|
|
621
869
|
/**
|
|
622
|
-
*
|
|
623
|
-
*
|
|
870
|
+
* Executes the stop operation for all active SQL logging sessions.
|
|
871
|
+
* Called after user confirms via the confirmation dialog.
|
|
624
872
|
*/
|
|
625
|
-
async
|
|
626
|
-
if (!confirm('Stop ALL active SQL logging sessions?')) {
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
873
|
+
async executeStopAllSessions() {
|
|
629
874
|
try {
|
|
630
875
|
this.loading = true;
|
|
631
876
|
const dataProvider = Metadata.Provider;
|
|
@@ -644,8 +889,9 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
644
889
|
await this.loadActiveSessions();
|
|
645
890
|
}
|
|
646
891
|
catch (error) {
|
|
892
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to stop all SQL logging sessions';
|
|
647
893
|
console.error('Error stopping all SQL logging sessions:', error);
|
|
648
|
-
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${
|
|
894
|
+
MJNotificationService.Instance.CreateSimpleNotification(`Error: ${errorMessage}`, 'error', 5000);
|
|
649
895
|
}
|
|
650
896
|
finally {
|
|
651
897
|
this.loading = false;
|
|
@@ -676,7 +922,7 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
676
922
|
`;
|
|
677
923
|
const variables = {
|
|
678
924
|
sessionId: session.id,
|
|
679
|
-
maxLines: 1000 // Limit to last 1000 lines for performance
|
|
925
|
+
maxLines: 1000, // Limit to last 1000 lines for performance
|
|
680
926
|
};
|
|
681
927
|
const result = await dataProvider.ExecuteGQL(query, variables);
|
|
682
928
|
if (result.errors) {
|
|
@@ -699,11 +945,12 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
699
945
|
}
|
|
700
946
|
catch (error) {
|
|
701
947
|
console.error('Error loading session log:', error);
|
|
702
|
-
this.logContent =
|
|
703
|
-
`--
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
948
|
+
this.logContent =
|
|
949
|
+
`-- Error loading log file --\n-- ${error.message || 'Unknown error occurred'} --\n\n` +
|
|
950
|
+
`-- Session Info --\n` +
|
|
951
|
+
`-- File: ${session.filePath}\n` +
|
|
952
|
+
`-- Session: ${session.sessionName}\n` +
|
|
953
|
+
`-- Started: ${new Date(session.startTime).toLocaleString()}\n`;
|
|
707
954
|
}
|
|
708
955
|
}
|
|
709
956
|
/**
|
|
@@ -748,6 +995,7 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
748
995
|
console.log('Extracted config data:', configData);
|
|
749
996
|
this.sqlLoggingConfig = configData || null;
|
|
750
997
|
this.configEnabled = this.sqlLoggingConfig?.enabled || false;
|
|
998
|
+
this.cdr.detectChanges();
|
|
751
999
|
console.log('Component state after update:');
|
|
752
1000
|
console.log(' this.sqlLoggingConfig:', this.sqlLoggingConfig);
|
|
753
1001
|
console.log(' this.configEnabled:', this.configEnabled);
|
|
@@ -795,10 +1043,11 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
795
1043
|
const sessionsData = result?.activeSqlLoggingSessions;
|
|
796
1044
|
console.log('Extracted sessions data:', sessionsData);
|
|
797
1045
|
this.activeSessions = sessionsData || [];
|
|
1046
|
+
this.cdr.detectChanges();
|
|
798
1047
|
// Update selected session if it still exists
|
|
799
1048
|
if (this.selectedSession) {
|
|
800
1049
|
const selectedId = this.selectedSession.id;
|
|
801
|
-
const stillExists = this.activeSessions.find(s => s.id === selectedId);
|
|
1050
|
+
const stillExists = this.activeSessions.find((s) => s.id === selectedId);
|
|
802
1051
|
if (stillExists) {
|
|
803
1052
|
this.selectedSession = stillExists;
|
|
804
1053
|
}
|
|
@@ -846,7 +1095,7 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
846
1095
|
// Try to refresh SharedService data
|
|
847
1096
|
await SharedService.RefreshData(false);
|
|
848
1097
|
// Wait a moment for data to propagate
|
|
849
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
1098
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
850
1099
|
// Re-check permissions
|
|
851
1100
|
await this.checkUserPermissions();
|
|
852
1101
|
console.log('Permissions refreshed');
|
|
@@ -872,12 +1121,98 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
872
1121
|
}
|
|
873
1122
|
/**
|
|
874
1123
|
* Calculates the total number of SQL statements across all active sessions.
|
|
875
|
-
*
|
|
876
1124
|
* @returns Total statement count
|
|
877
1125
|
*/
|
|
878
1126
|
getTotalStatementCount() {
|
|
879
1127
|
return this.activeSessions.reduce((sum, session) => sum + (session.statementCount || 0), 0);
|
|
880
1128
|
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Parses a string of filter patterns (comma or newline separated) into an array
|
|
1131
|
+
* @param patternsString - Comma or newline separated patterns
|
|
1132
|
+
* @returns Array of pattern strings, or undefined if empty
|
|
1133
|
+
*/
|
|
1134
|
+
parseFilterPatterns(patternsString) {
|
|
1135
|
+
if (!patternsString || !patternsString.trim()) {
|
|
1136
|
+
return undefined;
|
|
1137
|
+
}
|
|
1138
|
+
/** Split by comma or newline, trim whitespace, filter empty */
|
|
1139
|
+
return patternsString
|
|
1140
|
+
.split(/[,\n]/)
|
|
1141
|
+
.map((p) => p.trim())
|
|
1142
|
+
.filter((p) => p.length > 0);
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Toggles the log viewer between normal and expanded (fullscreen) mode.
|
|
1146
|
+
*/
|
|
1147
|
+
toggleLogViewerExpand() {
|
|
1148
|
+
this.isLogViewerExpanded = !this.isLogViewerExpanded;
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Toggles the start session dialog between normal and fullscreen mode.
|
|
1152
|
+
*/
|
|
1153
|
+
toggleStartDialogFullscreen() {
|
|
1154
|
+
this.isStartDialogFullscreen = !this.isStartDialogFullscreen;
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Handles keyboard events for the component.
|
|
1158
|
+
* Closes expanded log viewer or confirmation dialog when Escape is pressed.
|
|
1159
|
+
*/
|
|
1160
|
+
onEscapeKey() {
|
|
1161
|
+
if (this.showStopConfirmDialog) {
|
|
1162
|
+
this.cancelStopConfirm();
|
|
1163
|
+
}
|
|
1164
|
+
else if (this.isLogViewerExpanded) {
|
|
1165
|
+
this.isLogViewerExpanded = false;
|
|
1166
|
+
}
|
|
1167
|
+
else if (this.isStartDialogFullscreen) {
|
|
1168
|
+
this.isStartDialogFullscreen = false;
|
|
1169
|
+
}
|
|
1170
|
+
else if (this.showStartSessionDialog) {
|
|
1171
|
+
this.showStartSessionDialog = false;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Opens the confirmation dialog for stopping a single session.
|
|
1176
|
+
*
|
|
1177
|
+
* @param session - The session to stop
|
|
1178
|
+
* @param event - Optional event to stop propagation
|
|
1179
|
+
*/
|
|
1180
|
+
openStopSessionConfirm(session, event) {
|
|
1181
|
+
if (event) {
|
|
1182
|
+
event.stopPropagation();
|
|
1183
|
+
}
|
|
1184
|
+
this.sessionToStop = session;
|
|
1185
|
+
this.isStoppingAll = false;
|
|
1186
|
+
this.showStopConfirmDialog = true;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Opens the confirmation dialog for stopping all sessions.
|
|
1190
|
+
*/
|
|
1191
|
+
openStopAllSessionsConfirm() {
|
|
1192
|
+
this.sessionToStop = null;
|
|
1193
|
+
this.isStoppingAll = true;
|
|
1194
|
+
this.showStopConfirmDialog = true;
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Closes the stop confirmation dialog without taking action.
|
|
1198
|
+
*/
|
|
1199
|
+
cancelStopConfirm() {
|
|
1200
|
+
this.showStopConfirmDialog = false;
|
|
1201
|
+
this.sessionToStop = null;
|
|
1202
|
+
this.isStoppingAll = false;
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Confirms and executes the stop action (single session or all sessions).
|
|
1206
|
+
*/
|
|
1207
|
+
async confirmStopSession() {
|
|
1208
|
+
if (this.isStoppingAll) {
|
|
1209
|
+
await this.executeStopAllSessions();
|
|
1210
|
+
}
|
|
1211
|
+
else if (this.sessionToStop) {
|
|
1212
|
+
await this.executeStopSession(this.sessionToStop);
|
|
1213
|
+
}
|
|
1214
|
+
this.cancelStopConfirm();
|
|
1215
|
+
}
|
|
881
1216
|
/**
|
|
882
1217
|
* Debug method to test contextUser flow for SQL filtering.
|
|
883
1218
|
* This shows how the new architecture handles user context without storing email in provider.
|
|
@@ -906,16 +1241,18 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
906
1241
|
this.loading = false;
|
|
907
1242
|
}
|
|
908
1243
|
}
|
|
909
|
-
static ɵfac = function SqlLoggingComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SqlLoggingComponent)(i0.ɵɵdirectiveInject(i1.SharedService)); };
|
|
910
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SqlLoggingComponent, selectors: [["mj-sql-logging"]],
|
|
1244
|
+
static ɵfac = function SqlLoggingComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SqlLoggingComponent)(i0.ɵɵdirectiveInject(i1.SharedService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
1245
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SqlLoggingComponent, selectors: [["mj-sql-logging"]], hostBindings: function SqlLoggingComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1246
|
+
i0.ɵɵlistener("keydown.escape", function SqlLoggingComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, false, i0.ɵɵresolveDocument);
|
|
1247
|
+
} }, features: [i0.ɵɵInheritDefinitionFeature], decls: 11, vars: 9, consts: [[1, "sql-logging-container"], ["role", "toolbar", "aria-label", "SQL logging actions", 1, "action-buttons"], ["aria-label", "Refresh sessions", 1, "btn-secondary", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "btn-primary", 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"], [1, "btn-primary", 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"], ["aria-label", "Refresh user permissions", 1, "btn-secondary", 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"], ["aria-label", "Start a new SQL logging session", 1, "btn-primary", 2, "margin-top", "1rem", 3, "click"], ["role", "region", "aria-label", "Active sessions list", 1, "sessions-panel"], [1, "panel-header"], [1, "panel-title"], ["aria-label", "Stop all active sessions", 1, "btn-danger", "btn-small", 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"], ["aria-label", "Stop all active sessions", 1, "btn-danger", "btn-small", 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"], [1, "action-btn", "action-btn-danger", 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"], ["aria-label", "Refresh log content", 1, "action-btn", 3, "click"], [1, "action-btn", 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"], ["aria-label", "Start the SQL logging session", 1, "btn-primary", 3, "click", "disabled"], ["aria-label", "Cancel and close dialog", 1, "btn-secondary", 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"], [1, "btn-danger", 3, "click", "disabled"], ["aria-label", "Cancel and keep sessions running", 1, "btn-secondary", 3, "click", "disabled"], [1, "confirm-dialog-details"]], template: function SqlLoggingComponent_Template(rf, ctx) { if (rf & 1) {
|
|
911
1248
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "button", 2);
|
|
912
1249
|
i0.ɵɵlistener("click", function SqlLoggingComponent_Template_button_click_2_listener() { return ctx.loadActiveSessions(); });
|
|
913
1250
|
i0.ɵɵelement(3, "i", 3);
|
|
914
1251
|
i0.ɵɵtext(4, " Refresh ");
|
|
915
1252
|
i0.ɵɵelementEnd();
|
|
916
|
-
i0.ɵɵtemplate(5, SqlLoggingComponent_Conditional_5_Template, 3,
|
|
1253
|
+
i0.ɵɵtemplate(5, SqlLoggingComponent_Conditional_5_Template, 3, 2, "button", 4);
|
|
917
1254
|
i0.ɵɵelementEnd();
|
|
918
|
-
i0.ɵɵtemplate(6, SqlLoggingComponent_Conditional_6_Template,
|
|
1255
|
+
i0.ɵɵtemplate(6, SqlLoggingComponent_Conditional_6_Template, 44, 13, "div", 5)(7, SqlLoggingComponent_Conditional_7_Template, 2, 0, "div", 6)(8, SqlLoggingComponent_Conditional_8_Template, 5, 1, "div", 7)(9, SqlLoggingComponent_Conditional_9_Template, 77, 19, "div", 8)(10, SqlLoggingComponent_Conditional_10_Template, 17, 6, "div", 9);
|
|
919
1256
|
i0.ɵɵelementEnd();
|
|
920
1257
|
} if (rf & 2) {
|
|
921
1258
|
i0.ɵɵadvance(2);
|
|
@@ -932,7 +1269,9 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
|
|
|
932
1269
|
i0.ɵɵconditional(!ctx.loading || ctx.activeSessions.length > 0 ? 8 : -1);
|
|
933
1270
|
i0.ɵɵadvance();
|
|
934
1271
|
i0.ɵɵconditional(ctx.showStartSessionDialog ? 9 : -1);
|
|
935
|
-
} }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent], styles: ["@keyframes _ngcontent-%COMP%_shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.sql-logging-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n overflow: hidden;\n position: relative;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-bottom: 1.5rem;\n}\n@media (max-width: 768px) {\n .action-buttons[_ngcontent-%COMP%] {\n justify-content: center;\n flex-wrap: wrap;\n }\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #2196f3;\n color: white;\n}\n.btn-primary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-primary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n.btn-primary[_ngcontent-%COMP%]:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n}\n.btn-secondary[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-secondary[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n.btn-secondary[_ngcontent-%COMP%]:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n}\n\n.btn-danger[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #f44336;\n color: white;\n}\n.btn-danger[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n.btn-danger[_ngcontent-%COMP%]:hover {\n background-color: #d32f2f;\n}\n.btn-danger.btn-small[_ngcontent-%COMP%] {\n padding: 0.375rem 0.75rem;\n font-size: 0.875rem;\n}\n\n.stats-grid[_ngcontent-%COMP%] {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 2rem;\n width: 100%;\n}\n@media (max-width: 768px) {\n .stats-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n margin-right: 10px;\n align-items: center;\n gap: 1rem;\n transition: all 0.3s ease;\n min-width: 0;\n}\n.stat-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n}\n.stat-icon-status[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n}\n.stat-icon-active[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n}\n.stat-icon-limit[_ngcontent-%COMP%] {\n background: rgba(255, 152, 0, 0.1);\n color: #ff9800;\n}\n.stat-icon-total[_ngcontent-%COMP%] {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n}\n.stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n}\n.stat-content[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n}\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n padding: 1.5rem;\n min-height: 400px;\n}\n\n.sessions-layout[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n height: calc(100vh - 450px);\n min-height: 400px;\n max-height: 600px;\n}\n@media (max-width: 1024px) {\n .sessions-layout[_ngcontent-%COMP%] {\n flex-direction: column;\n height: auto;\n max-height: none;\n }\n}\n\n.sessions-panel[_ngcontent-%COMP%] {\n flex: 0 0 400px;\n display: flex;\n flex-direction: column;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n overflow: hidden;\n}\n@media (max-width: 1024px) {\n .sessions-panel[_ngcontent-%COMP%] {\n flex: 1;\n max-height: 400px;\n }\n}\n\n.panel-header[_ngcontent-%COMP%] {\n padding: 1rem;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.panel-header[_ngcontent-%COMP%] .panel-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n}\n\n.panel-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.sessions-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n padding: 0.75rem;\n}\n\n.session-card[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n padding: 1rem;\n margin-bottom: 0.75rem;\n cursor: pointer;\n transition: all 0.2s;\n}\n.session-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.session-card.selected[_ngcontent-%COMP%] {\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\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}\n.session-info[_ngcontent-%COMP%] .session-title[_ngcontent-%COMP%] {\n margin: 0 0 0.5rem 0;\n font-size: 0.95rem;\n font-weight: 600;\n color: #1f2937;\n}\n\n.session-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 1rem;\n font-size: 0.75rem;\n color: #6b7280;\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}\n\n.badge[_ngcontent-%COMP%] {\n padding: 0.25rem 0.5rem;\n border-radius: 12px;\n font-size: 0.625rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n.badge-user[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n}\n.badge-migration[_ngcontent-%COMP%] {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n}\n.badge-type[_ngcontent-%COMP%] {\n background: rgba(255, 152, 0, 0.1);\n color: #ff9800;\n}\n\n.action-btn[_ngcontent-%COMP%] {\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s;\n}\n.action-btn[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n color: #374151;\n}\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n color: #f44336;\n}\n\n.log-viewer-panel[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.log-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n background: #1e1e1e;\n color: #d4d4d4;\n padding: 0;\n min-height: 300px;\n height: 100%;\n position: relative;\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.log-content[_ngcontent-%COMP%] .cm-scroller {\n font-family: inherit;\n}\n.log-content[_ngcontent-%COMP%] .cm-content {\n background: #1e1e1e;\n color: #d4d4d4;\n}\n.log-content[_ngcontent-%COMP%] .cm-gutters {\n background: #252526;\n color: #858585;\n border-right: 1px solid #464647;\n}\n.log-content[_ngcontent-%COMP%] .cm-activeLineGutter {\n background: #2a2a2a;\n}\n.log-content[_ngcontent-%COMP%] .cm-activeLine {\n background: rgba(255, 255, 255, 0.04);\n}\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 4rem 2rem;\n}\n.empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n}\n.empty-state[_ngcontent-%COMP%] .empty-icon.warning[_ngcontent-%COMP%] {\n color: #ffc107;\n}\n.empty-state[_ngcontent-%COMP%] .empty-text[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n}\n.empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n color: #6b7280;\n margin: 0;\n}\n\n.info-box[_ngcontent-%COMP%] {\n background: #f3f4f6;\n border-radius: 8px;\n padding: 1.5rem;\n margin-top: 2rem;\n text-align: left;\n max-width: 500px;\n margin-left: auto;\n margin-right: auto;\n}\n.info-box[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 1rem 0;\n color: #1f2937;\n}\n.info-box[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n margin: 0;\n padding-left: 1.25rem;\n color: #374151;\n}\n.info-box[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n margin-bottom: 0.5rem;\n}\n.info-box[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: #e5e7eb;\n padding: 0.125rem 0.375rem;\n border-radius: 4px;\n font-size: 0.875rem;\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 min-height: 400px;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n position: relative;\n width: 60px;\n height: 60px;\n margin-bottom: 1rem;\n}\n.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%] {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n}\n.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%]:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n}\n.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%]:nth-child(2) {\n border-color: transparent #9c27b0 transparent transparent;\n animation-delay: -0.3s;\n}\n.loading-spinner[_ngcontent-%COMP%] .spinner-ring[_ngcontent-%COMP%]:nth-child(3) {\n border-color: transparent transparent #4caf50 transparent;\n animation-delay: -0.15s;\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.loading-text[_ngcontent-%COMP%] {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease;\n}\n\n.modal-dialog[_ngcontent-%COMP%] {\n background: white;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n animation: _ngcontent-%COMP%_slideUp 0.3s ease;\n}\n.modal-dialog.modal-large[_ngcontent-%COMP%] {\n max-width: 700px;\n}\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid #e5e7eb;\n}\n.modal-header[_ngcontent-%COMP%] .modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0;\n}\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%] {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n}\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:hover {\n background: #f3f4f6;\n color: #374151;\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\n max-height: 60vh;\n overflow-y: auto;\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n}\n\n.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: #374151;\n margin-bottom: 0.5rem;\n}\n\n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n}\n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.form-select[_ngcontent-%COMP%] {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n background: white;\n cursor: pointer;\n transition: all 0.2s;\n}\n.form-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.form-hint[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: #6b7280;\n margin-top: 0.25rem;\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.5rem;\n color: #374151;\n font-size: 0.95rem;\n cursor: pointer;\n}\n.checkbox-label[_ngcontent-%COMP%] input[type=checkbox][_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes _ngcontent-%COMP%_slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}"] });
|
|
1272
|
+
i0.ɵɵadvance();
|
|
1273
|
+
i0.ɵɵconditional(ctx.showStopConfirmDialog ? 10 : -1);
|
|
1274
|
+
} }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.CheckboxControlValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.LoadingComponent], styles: ["\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n \n\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n \n\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n \n\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n \n\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n \n\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n \n\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n \n\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n \n\n display: 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(--md-surface);\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 display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-bottom: 1.5rem;\n flex-wrap: wrap;\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(--md-corner-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n min-width: 44px;\n}\n\n\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-primary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #4BA5D4;\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(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\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(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-danger[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-danger[_ngcontent-%COMP%]:active:not(:disabled) {\n background: #EF9A9A;\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(--md-surface-container-low);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.stats-toggle-button[_ngcontent-%COMP%]:hover {\n background: var(--md-surface-container);\n border-color: var(--md-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\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(--md-corner-medium);\n background: var(--md-primary-container);\n color: var(--md-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(--md-primary);\n color: var(--md-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(--md-on-surface);\n margin: 0;\n}\n\n.stats-toggle-button.expanded[_ngcontent-%COMP%] .stats-toggle-title[_ngcontent-%COMP%] {\n color: var(--md-primary);\n}\n\n.stats-toggle-subtitle[_ngcontent-%COMP%] {\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n.stats-toggle-arrow[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n color: var(--md-on-surface-variant);\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(--md-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 \n\n .stats-toggle-button[_ngcontent-%COMP%] {\n display: none;\n }\n\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(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n padding: 1.25rem;\n box-shadow: var(--md-elevation-1);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--md-outline-variant);\n cursor: default;\n}\n\n.stat-icon[_ngcontent-%COMP%] {\n width: 56px;\n height: 56px;\n border-radius: var(--md-corner-medium);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n flex-shrink: 0;\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(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n.stat-icon-active[_ngcontent-%COMP%] {\n background: var(--md-primary-container);\n color: var(--md-primary);\n}\n\n.stat-icon-limit[_ngcontent-%COMP%] {\n background: var(--md-secondary-container);\n color: #B5751A;\n}\n\n.stat-icon-total[_ngcontent-%COMP%] {\n background: var(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n.stat-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.stat-content[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--md-on-surface);\n line-height: 1;\n letter-spacing: -0.02em;\n}\n\n@media (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.stat-content[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-top: 0.25rem;\n}\n\n\n\n\n\n.content-area[_ngcontent-%COMP%] {\n flex: 1;\n overflow: visible;\n min-height: 0;\n position: relative;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n padding: 1rem;\n}\n\n@media (min-width: 640px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .content-area[_ngcontent-%COMP%] {\n padding: 1.5rem;\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(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n overflow: hidden;\n background: var(--md-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(--md-surface-container-low);\n border-bottom: 1px solid var(--md-outline-variant);\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(--md-on-surface);\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 \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(--md-surface);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\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(--md-elevation-1);\n border-color: var(--md-primary);\n}\n\n.session-card.selected[_ngcontent-%COMP%] {\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--md-primary-container);\n}\n\n.session-card[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-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(--md-on-surface);\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(--md-on-surface-variant);\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(--md-corner-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(--md-primary-container);\n color: var(--md-primary);\n border: 1px solid var(--md-primary);\n}\n\n.badge-migration[_ngcontent-%COMP%] {\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n.badge-type[_ngcontent-%COMP%] {\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\n}\n\n\n\n\n\n.action-btn[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1rem;\n border-radius: var(--md-corner-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(--md-primary);\n color: var(--md-on-primary);\n}\n\n.action-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.action-btn-danger[_ngcontent-%COMP%]:hover {\n background: var(--md-error);\n color: var(--md-on-error);\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(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n overflow: hidden;\n background: var(--md-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: #1e1e1e;\n color: #d4d4d4;\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: #1e1e1e;\n color: #d4d4d4;\n}\n\n.log-content[_ngcontent-%COMP%] .cm-gutters {\n background: #252526;\n color: #858585;\n border-right: 1px solid #464647;\n}\n\n.log-content[_ngcontent-%COMP%] .cm-activeLineGutter {\n background: #2a2a2a;\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%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 4rem 2rem;\n gap: 1rem;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 0.5rem;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-icon.warning[_ngcontent-%COMP%] {\n color: var(--md-secondary);\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-text[_ngcontent-%COMP%] {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-subtext[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n max-width: 400px;\n}\n\n\n\n\n\n.info-box[_ngcontent-%COMP%] {\n background: var(--md-surface-container);\n border-radius: var(--md-corner-medium);\n padding: 1.5rem;\n margin-top: 1.5rem;\n text-align: left;\n max-width: 500px;\n border: 1px solid var(--md-outline-variant);\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(--md-on-surface);\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(--md-on-surface);\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(--md-surface-container-high);\n padding: 0.125rem 0.5rem;\n border-radius: var(--md-corner-extra-small);\n font-size: 0.8125rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n color: var(--md-on-surface);\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 min-height: 300px;\n}\n\n.loading-text[_ngcontent-%COMP%] {\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n margin-top: 1rem;\n}\n\n\n\n\n\n.modal-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.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(--md-surface);\n border-radius: var(--md-corner-extra-large);\n box-shadow: var(--md-elevation-5);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n animation: _ngcontent-%COMP%_slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\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: 20px;\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 display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid var(--md-outline-variant);\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-header[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n }\n}\n\n.modal-header[_ngcontent-%COMP%] .modal-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n\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(--md-on-surface-variant);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--md-corner-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(--md-primary);\n color: var(--md-on-primary);\n}\n\n.modal-action-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%] {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--md-corner-full);\n 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.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.modal-header[_ngcontent-%COMP%] .modal-close[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 1.5rem;\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 display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid var(--md-outline-variant);\n background: var(--md-surface-container-low);\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-footer[_ngcontent-%COMP%] {\n padding: 1rem 1.25rem;\n flex-direction: column;\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(--md-on-surface);\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(--md-outline-variant);\n border-radius: var(--md-corner-small);\n font-size: 1rem;\n background: var(--md-surface);\n color: var(--md-on-surface);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-input[_ngcontent-%COMP%]:hover, \n.form-select[_ngcontent-%COMP%]:hover, \n.form-textarea[_ngcontent-%COMP%]:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\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(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--md-surface);\n}\n\n.form-input[_ngcontent-%COMP%]::placeholder, \n.form-textarea[_ngcontent-%COMP%]::placeholder {\n color: var(--md-on-surface-variant);\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(--md-on-surface-variant);\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(--md-on-surface);\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(--md-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(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n background: var(--md-surface-container-low);\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(--md-on-surface);\n}\n\n.form-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--md-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(--md-surface);\n border-radius: var(--md-corner-extra-large);\n box-shadow: var(--md-elevation-5);\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: 20px;\n }\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: var(--md-secondary-container);\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: #B5751A;\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(--md-on-surface);\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n line-height: 1.6;\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--md-on-surface);\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(--md-surface-container);\n border-radius: var(--md-corner-small);\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\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%_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%_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@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\nbutton[_ngcontent-%COMP%]:focus-visible, \ninput[_ngcontent-%COMP%]:focus-visible, \nselect[_ngcontent-%COMP%]:focus-visible, \ntextarea[_ngcontent-%COMP%]:focus-visible, \na[_ngcontent-%COMP%]:focus-visible, \n[tabindex][_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\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}"] });
|
|
936
1275
|
};
|
|
937
1276
|
SqlLoggingComponent = __decorate([
|
|
938
1277
|
RegisterClass(BaseDashboard, 'SqlLogging')
|
|
@@ -940,7 +1279,10 @@ SqlLoggingComponent = __decorate([
|
|
|
940
1279
|
export { SqlLoggingComponent };
|
|
941
1280
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SqlLoggingComponent, [{
|
|
942
1281
|
type: Component,
|
|
943
|
-
args: [{ selector: 'mj-sql-logging', template: "<div class=\"sql-logging-container\">\n <!-- Action Buttons -->\n <div class=\"action-buttons\">\n <button class=\"btn-secondary\" (click)=\"loadActiveSessions()\" [disabled]=\"loading\">\n <i class=\"fa-solid fa-refresh\" [class.fa-spin]=\"loading\"></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 title=\"Start SQL logging session\"\n >\n <i class=\"fa-solid fa-play\"></i>\n Start New Session\n </button>\n }\n </div>\n\n <!-- Stats Cards -->\n @if (isOwner && configEnabled) {\n <div class=\"stats-grid\" style=\"display: flex\">\n <div class=\"stat-card\">\n <div class=\"stat-icon stat-icon-status\">\n <i class=\"fa-solid fa-power-off\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ configEnabled ? 'Enabled' : 'Disabled' }}</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\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ activeSessions.length }}</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\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ sqlLoggingConfig?.maxActiveSessions || 5 }}</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\"></i>\n </div>\n <div class=\"stat-content\">\n <div class=\"stat-value\">{{ getTotalStatementCount() }}</div>\n <div class=\"stat-label\">Total Statements</div>\n </div>\n </div>\n </div>\n }\n\n <!-- Loading State -->\n @if (loading && !activeSessions.length) {\n <div class=\"loading-container\">\n <div class=\"loading-spinner\">\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n </div>\n <div class=\"loading-text\">Loading SQL logging configuration...</div>\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\">\n <i class=\"fa-solid fa-lock empty-icon\"></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 \n class=\"btn-secondary\"\n (click)=\"refreshUserPermissions()\"\n style=\"margin-top: 1rem\"\n >\n <i class=\"fa-solid fa-sync\"></i>\n Refresh Permissions\n </button>\n </div>\n } @else if (!configEnabled) {\n <!-- Not enabled in config -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-exclamation-triangle empty-icon warning\"></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\">\n <i class=\"fa-solid fa-file-code empty-icon\"></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 \n class=\"btn-primary\"\n (click)=\"openStartSessionDialog()\"\n style=\"margin-top: 1rem\"\n >\n <i class=\"fa-solid fa-play\"></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\">\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)=\"stopAllSessions()\"\n [disabled]=\"loading\"\n title=\"Stop all sessions\"\n >\n <i class=\"fa-solid fa-stop\"></i>\n Stop All\n </button>\n }\n </div>\n <div class=\"sessions-list\">\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 >\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\"></i>\n {{ getSessionDuration(session.startTime) }}\n </span>\n <span class=\"meta-item\">\n <i class=\"fa-solid fa-database\"></i>\n {{ session.statementCount }} statements\n </span>\n </div>\n </div>\n <button \n class=\"action-btn action-btn-danger\"\n (click)=\"stopSession(session, $event)\"\n title=\"Stop session\"\n >\n <i class=\"fa-solid fa-stop\"></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\"></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\"></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\">\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 />\n Auto-refresh\n </label>\n <button \n class=\"action-btn\"\n (click)=\"loadSessionLog(selectedSession)\"\n title=\"Refresh log\"\n >\n <i class=\"fa-solid fa-sync\" [class.fa-spin]=\"loading\"></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 ></mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-arrow-left empty-icon\"></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 class=\"modal-backdrop\" (click)=\"showStartSessionDialog = false\">\n <div class=\"modal-dialog modal-large\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">\n <i class=\"fa-solid fa-play\"></i>\n Start SQL Logging Session\n </h3>\n <button class=\"modal-close\" (click)=\"showStartSessionDialog = false\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"modal-body\">\n <div class=\"form-group\">\n <label class=\"form-label\">Session Name</label>\n <input \n type=\"text\"\n class=\"form-input\" \n [(ngModel)]=\"newSessionOptions.sessionName\"\n placeholder=\"Enter a descriptive name for this session\"\n />\n </div>\n \n <div class=\"form-group\">\n <label class=\"form-label\">File Name</label>\n <input \n type=\"text\"\n class=\"form-input\" \n [(ngModel)]=\"newSessionOptions.fileName\"\n placeholder=\"sql-log-2024-01-01.sql\"\n />\n <div 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\">Statement Types</label>\n <select\n class=\"form-select\"\n [(ngModel)]=\"newSessionOptions.statementTypes\"\n >\n @for (option of statementTypeOptions; track option.value) {\n <option [value]=\"option.value\">{{ option.text }}</option>\n }\n </select>\n </div>\n \n <div class=\"form-checkboxes\">\n <label class=\"checkbox-label\">\n <input \n type=\"checkbox\" \n [(ngModel)]=\"newSessionOptions.filterToCurrentUser\"\n />\n Filter to my SQL statements only\n </label>\n \n <label class=\"checkbox-label\">\n <input \n type=\"checkbox\" \n [(ngModel)]=\"newSessionOptions.formatAsMigration\"\n />\n Format as migration file\n </label>\n \n <label class=\"checkbox-label\">\n <input \n type=\"checkbox\" \n [(ngModel)]=\"newSessionOptions.prettyPrint\"\n />\n Pretty print SQL statements\n </label>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button class=\"btn-secondary\" (click)=\"showStartSessionDialog = false\">\n Cancel\n </button>\n <button class=\"btn-primary\" (click)=\"startNewSession()\" [disabled]=\"loading\">\n <i class=\"fa-solid fa-play\"></i>\n Start Session\n </button>\n </div>\n </div>\n </div>\n }\n</div>", styles: ["@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n.sql-logging-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n max-height: 100%;\n overflow: hidden;\n position: relative;\n max-width: 1400px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.action-buttons {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-bottom: 1.5rem;\n}\n@media (max-width: 768px) {\n .action-buttons {\n justify-content: center;\n flex-wrap: wrap;\n }\n}\n\n.btn-primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #2196f3;\n color: white;\n}\n.btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-primary i {\n font-size: 0.875rem;\n}\n.btn-primary:hover {\n background-color: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(33, 150, 243, 0.3);\n}\n\n.btn-secondary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #ffffff;\n color: #374151;\n border: 1px solid #e5e7eb;\n}\n.btn-secondary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-secondary i {\n font-size: 0.875rem;\n}\n.btn-secondary:hover {\n background-color: #f9fafb;\n border-color: #2196f3;\n color: #2196f3;\n}\n\n.btn-danger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n padding: 0.625rem 1.25rem;\n font-size: 0.95rem;\n font-weight: 500;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n background-color: #f44336;\n color: white;\n}\n.btn-danger:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.btn-danger i {\n font-size: 0.875rem;\n}\n.btn-danger:hover {\n background-color: #d32f2f;\n}\n.btn-danger.btn-small {\n padding: 0.375rem 0.75rem;\n font-size: 0.875rem;\n}\n\n.stats-grid {\n display: grid !important;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 1.5rem;\n margin-bottom: 2rem;\n width: 100%;\n}\n@media (max-width: 768px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n gap: 1rem;\n }\n}\n\n.stat-card {\n background: white;\n border-radius: 12px;\n padding: 1.5rem;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n display: flex;\n margin-right: 10px;\n align-items: center;\n gap: 1rem;\n transition: all 0.3s ease;\n min-width: 0;\n}\n.stat-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);\n}\n\n.stat-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n}\n.stat-icon-status {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n}\n.stat-icon-active {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n}\n.stat-icon-limit {\n background: rgba(255, 152, 0, 0.1);\n color: #ff9800;\n}\n.stat-icon-total {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n}\n\n.stat-content {\n flex: 1;\n}\n.stat-content .stat-value {\n font-size: 2rem;\n font-weight: 700;\n color: #1f2937;\n line-height: 1;\n}\n.stat-content .stat-label {\n color: #6b7280;\n font-size: 0.875rem;\n margin-top: 0.25rem;\n}\n\n.content-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n background: white;\n border-radius: 12px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n padding: 1.5rem;\n min-height: 400px;\n}\n\n.sessions-layout {\n display: flex;\n gap: 1.5rem;\n height: calc(100vh - 450px);\n min-height: 400px;\n max-height: 600px;\n}\n@media (max-width: 1024px) {\n .sessions-layout {\n flex-direction: column;\n height: auto;\n max-height: none;\n }\n}\n\n.sessions-panel {\n flex: 0 0 400px;\n display: flex;\n flex-direction: column;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n overflow: hidden;\n}\n@media (max-width: 1024px) {\n .sessions-panel {\n flex: 1;\n max-height: 400px;\n }\n}\n\n.panel-header {\n padding: 1rem;\n background: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.panel-header .panel-title {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 600;\n color: #1f2937;\n}\n\n.panel-actions {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.sessions-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n padding: 0.75rem;\n}\n\n.session-card {\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n padding: 1rem;\n margin-bottom: 0.75rem;\n cursor: pointer;\n transition: all 0.2s;\n}\n.session-card:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.session-card.selected {\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\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}\n.session-info .session-title {\n margin: 0 0 0.5rem 0;\n font-size: 0.95rem;\n font-weight: 600;\n color: #1f2937;\n}\n\n.session-meta {\n display: flex;\n gap: 1rem;\n font-size: 0.75rem;\n color: #6b7280;\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}\n\n.badge {\n padding: 0.25rem 0.5rem;\n border-radius: 12px;\n font-size: 0.625rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n.badge-user {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n}\n.badge-migration {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n}\n.badge-type {\n background: rgba(255, 152, 0, 0.1);\n color: #ff9800;\n}\n\n.action-btn {\n padding: 0.375rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 0.875rem;\n border-radius: 4px;\n cursor: pointer;\n transition: all 0.2s;\n}\n.action-btn:hover {\n background: #f3f4f6;\n color: #374151;\n}\n.action-btn-danger:hover {\n color: #f44336;\n}\n\n.log-viewer-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.log-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n background: #1e1e1e;\n color: #d4d4d4;\n padding: 0;\n min-height: 300px;\n height: 100%;\n position: relative;\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.log-content ::ng-deep .cm-scroller {\n font-family: inherit;\n}\n.log-content ::ng-deep .cm-content {\n background: #1e1e1e;\n color: #d4d4d4;\n}\n.log-content ::ng-deep .cm-gutters {\n background: #252526;\n color: #858585;\n border-right: 1px solid #464647;\n}\n.log-content ::ng-deep .cm-activeLineGutter {\n background: #2a2a2a;\n}\n.log-content ::ng-deep .cm-activeLine {\n background: rgba(255, 255, 255, 0.04);\n}\n\n.empty-state {\n text-align: center;\n padding: 4rem 2rem;\n}\n.empty-state .empty-icon {\n font-size: 4rem;\n color: #e5e7eb;\n margin-bottom: 1rem;\n}\n.empty-state .empty-icon.warning {\n color: #ffc107;\n}\n.empty-state .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: #374151;\n margin: 0 0 0.5rem 0;\n}\n.empty-state .empty-subtext {\n color: #6b7280;\n margin: 0;\n}\n\n.info-box {\n background: #f3f4f6;\n border-radius: 8px;\n padding: 1.5rem;\n margin-top: 2rem;\n text-align: left;\n max-width: 500px;\n margin-left: auto;\n margin-right: auto;\n}\n.info-box h4 {\n margin: 0 0 1rem 0;\n color: #1f2937;\n}\n.info-box ol {\n margin: 0;\n padding-left: 1.25rem;\n color: #374151;\n}\n.info-box ol li {\n margin-bottom: 0.5rem;\n}\n.info-box code {\n background: #e5e7eb;\n padding: 0.125rem 0.375rem;\n border-radius: 4px;\n font-size: 0.875rem;\n}\n\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n min-height: 400px;\n}\n\n.loading-spinner {\n position: relative;\n width: 60px;\n height: 60px;\n margin-bottom: 1rem;\n}\n.loading-spinner .spinner-ring {\n position: absolute;\n width: 100%;\n height: 100%;\n border: 3px solid transparent;\n border-radius: 50%;\n animation: spin 1.5s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n}\n.loading-spinner .spinner-ring:nth-child(1) {\n border-color: #2196f3 transparent transparent transparent;\n animation-delay: -0.45s;\n}\n.loading-spinner .spinner-ring:nth-child(2) {\n border-color: transparent #9c27b0 transparent transparent;\n animation-delay: -0.3s;\n}\n.loading-spinner .spinner-ring:nth-child(3) {\n border-color: transparent transparent #4caf50 transparent;\n animation-delay: -0.15s;\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.loading-text {\n color: #6b7280;\n font-size: 0.95rem;\n}\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n animation: fadeIn 0.2s ease;\n}\n\n.modal-dialog {\n background: white;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n animation: slideUp 0.3s ease;\n}\n.modal-dialog.modal-large {\n max-width: 700px;\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid #e5e7eb;\n}\n.modal-header .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.25rem;\n font-weight: 600;\n color: #1f2937;\n margin: 0;\n}\n.modal-header .modal-close {\n padding: 0.5rem;\n border: none;\n background: transparent;\n color: #6b7280;\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n}\n.modal-header .modal-close:hover {\n background: #f3f4f6;\n color: #374151;\n}\n\n.modal-body {\n padding: 1.5rem;\n max-height: 60vh;\n overflow-y: auto;\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid #e5e7eb;\n background: #f9fafb;\n}\n\n.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: #374151;\n margin-bottom: 0.5rem;\n}\n\n.form-input {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n transition: all 0.2s;\n}\n.form-input:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.form-select {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n background: white;\n cursor: pointer;\n transition: all 0.2s;\n}\n.form-select:focus {\n outline: none;\n border-color: #2196f3;\n box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);\n}\n\n.form-hint {\n font-size: 0.75rem;\n color: #6b7280;\n margin-top: 0.25rem;\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.5rem;\n color: #374151;\n font-size: 0.95rem;\n cursor: pointer;\n}\n.checkbox-label input[type=checkbox] {\n cursor: pointer;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n"] }]
|
|
944
|
-
}], () => [{ type: i1.SharedService }],
|
|
1282
|
+
args: [{ 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\n class=\"action-btn action-btn-danger\"\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\n class=\"action-btn\"\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\n class=\"action-btn\"\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 SQL Logging Component - Material Design 3 Styles\n Following MD3 Design System with custom color palette and design tokens\n ============================================================================= */\n\n/* MD3 Design Tokens - Color Palette */\n:host {\n /* Primary - Deep Blue */\n --md-primary: #0076B6;\n --md-on-primary: #FFFFFF;\n --md-primary-container: #AAE7FD;\n --md-on-primary-container: #001F2A;\n\n /* Secondary - Light Orange */\n --md-secondary: #F5A623;\n --md-on-secondary: #FFFFFF;\n --md-secondary-container: #FFECD6;\n --md-on-secondary-container: #2D1600;\n\n /* Tertiary - Light Green */\n --md-tertiary: #4CAF50;\n --md-on-tertiary: #FFFFFF;\n --md-tertiary-container: #C8E6C9;\n --md-on-tertiary-container: #002204;\n\n /* Error - Red */\n --md-error: #D32F2F;\n --md-on-error: #FFFFFF;\n --md-error-container: #FFCDD2;\n --md-on-error-container: #410002;\n\n /* Surface Colors */\n --md-surface: #FAFCFF;\n --md-surface-container-lowest: #FFFFFF;\n --md-surface-container-low: #F3F5F9;\n --md-surface-container: #EDF0F4;\n --md-surface-container-high: #E7EAEE;\n --md-surface-container-highest: #E1E3E8;\n --md-on-surface: #191C20;\n --md-on-surface-variant: #43474E;\n --md-outline: #74777F;\n --md-outline-variant: #C4C6D0;\n\n /* Elevation (Box Shadows) */\n --md-elevation-1: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);\n --md-elevation-2: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n --md-elevation-3: 0 4px 8px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.08);\n --md-elevation-4: 0 6px 12px rgba(0, 0, 0, 0.1), 0 12px 24px rgba(0, 0, 0, 0.08);\n --md-elevation-5: 0 8px 16px rgba(0, 0, 0, 0.12), 0 16px 32px rgba(0, 0, 0, 0.1);\n\n /* Corner Radii */\n --md-corner-extra-small: 4px;\n --md-corner-small: 8px;\n --md-corner-medium: 12px;\n --md-corner-large: 16px;\n --md-corner-extra-large: 28px;\n --md-corner-full: 9999px;\n\n /* Host element layout */\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(--md-surface);\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\n ----------------------------------------------------------------------------- */\n.action-buttons {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-bottom: 1.5rem;\n flex-wrap: wrap;\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 - MD3 Pattern\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(--md-corner-full);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n min-width: 44px;\n}\n\n/* Primary Button - Dark blue, lightens on hover */\n.btn-primary {\n background: var(--md-primary);\n color: var(--md-on-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: #3395C8;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-primary:active:not(:disabled) {\n background: #4BA5D4;\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 - Light, darkens/fills on hover */\n.btn-secondary {\n background: var(--md-surface);\n color: var(--md-primary);\n border: 1px solid var(--md-outline);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--md-primary);\n color: var(--md-on-primary);\n border-color: var(--md-primary);\n}\n\n.btn-secondary:active:not(:disabled) {\n background: #005A8C;\n border-color: #005A8C;\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 - Dark red, lightens on hover */\n.btn-danger {\n background: var(--md-error);\n color: var(--md-on-error);\n box-shadow: var(--md-elevation-1);\n}\n\n.btn-danger:hover:not(:disabled) {\n background: #E57373;\n box-shadow: var(--md-elevation-2);\n}\n\n.btn-danger:active:not(:disabled) {\n background: #EF9A9A;\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 - MD3 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(--md-surface-container-low);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 56px;\n}\n\n.stats-toggle-button:hover {\n background: var(--md-surface-container);\n border-color: var(--md-primary);\n box-shadow: var(--md-elevation-1);\n}\n\n.stats-toggle-button.expanded {\n border-color: var(--md-primary);\n background: var(--md-primary-container);\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(--md-corner-medium);\n background: var(--md-primary-container);\n color: var(--md-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(--md-primary);\n color: var(--md-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(--md-on-surface);\n margin: 0;\n}\n\n.stats-toggle-button.expanded .stats-toggle-title {\n color: var(--md-primary);\n}\n\n.stats-toggle-subtitle {\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n}\n\n.stats-toggle-arrow {\n font-size: 1.25rem;\n color: var(--md-on-surface-variant);\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(--md-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 /* Hide toggle button on desktop - stats always visible */\n .stats-toggle-button {\n display: none;\n }\n\n /* Always show stats grid on desktop */\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 - Non-interactive */\n.stat-card {\n background: var(--md-surface-container-low);\n border-radius: var(--md-corner-medium);\n padding: 1.25rem;\n box-shadow: var(--md-elevation-1);\n display: flex;\n align-items: center;\n gap: 1rem;\n border: 1px solid var(--md-outline-variant);\n cursor: default;\n}\n\n.stat-icon {\n width: 56px;\n height: 56px;\n border-radius: var(--md-corner-medium);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.5rem;\n flex-shrink: 0;\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(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n.stat-icon-active {\n background: var(--md-primary-container);\n color: var(--md-primary);\n}\n\n.stat-icon-limit {\n background: var(--md-secondary-container);\n color: #B5751A;\n}\n\n.stat-icon-total {\n background: var(--md-tertiary-container);\n color: var(--md-tertiary);\n}\n\n.stat-content {\n flex: 1;\n min-width: 0;\n}\n\n.stat-content .stat-value {\n font-size: 1.75rem;\n font-weight: 700;\n color: var(--md-on-surface);\n line-height: 1;\n letter-spacing: -0.02em;\n}\n\n@media (max-width: 639px) {\n .stat-content .stat-value {\n font-size: 1.5rem;\n font-weight: 700;\n }\n}\n\n.stat-content .stat-label {\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--md-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin-top: 0.25rem;\n}\n\n/* -----------------------------------------------------------------------------\n Content Area\n ----------------------------------------------------------------------------- */\n.content-area {\n flex: 1;\n overflow: visible;\n min-height: 0;\n position: relative;\n background: var(--md-surface-container);\n border-radius: var(--md-corner-medium);\n border: 1px solid var(--md-outline-variant);\n padding: 1rem;\n}\n\n@media (min-width: 640px) {\n .content-area {\n padding: 1.25rem;\n }\n}\n\n@media (min-width: 768px) {\n .content-area {\n padding: 1.5rem;\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(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n overflow: hidden;\n background: var(--md-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(--md-surface-container-low);\n border-bottom: 1px solid var(--md-outline-variant);\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(--md-on-surface);\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 /* Hide checkbox label text on mobile, show only checkbox */\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(--md-surface);\n border: 1px solid var(--md-outline-variant);\n border-radius: var(--md-corner-small);\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(--md-elevation-1);\n border-color: var(--md-primary);\n}\n\n.session-card.selected {\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--md-primary-container);\n}\n\n.session-card:focus-visible {\n outline: 2px solid var(--md-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(--md-on-surface);\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(--md-on-surface-variant);\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 - MD3 Chips\n ----------------------------------------------------------------------------- */\n.badge {\n padding: 0.375rem 0.875rem;\n border-radius: var(--md-corner-full);\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.badge-user {\n background: var(--md-primary-container);\n color: var(--md-primary);\n border: 1px solid var(--md-primary);\n}\n\n.badge-migration {\n background: var(--md-tertiary-container);\n color: #1B5E20;\n border: 1px solid var(--md-tertiary);\n}\n\n.badge-type {\n background: var(--md-secondary-container);\n color: #7A4D0C;\n border: 1px solid var(--md-secondary);\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(--md-on-surface-variant);\n font-size: 1rem;\n border-radius: var(--md-corner-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(--md-primary);\n color: var(--md-on-primary);\n}\n\n.action-btn:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.action-btn-danger:hover {\n background: var(--md-error);\n color: var(--md-on-error);\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(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n overflow: hidden;\n background: var(--md-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 (per design guide exception) */\n.log-content {\n flex: 1;\n overflow: hidden;\n min-height: 300px;\n height: 100%;\n position: relative;\n background: #1e1e1e;\n color: #d4d4d4;\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: #1e1e1e;\n color: #d4d4d4;\n}\n\n.log-content ::ng-deep .cm-gutters {\n background: #252526;\n color: #858585;\n border-right: 1px solid #464647;\n}\n\n.log-content ::ng-deep .cm-activeLineGutter {\n background: #2a2a2a;\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 - MD3 Pattern\n ----------------------------------------------------------------------------- */\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 4rem 2rem;\n gap: 1rem;\n}\n\n.empty-state .empty-icon {\n font-size: 4rem;\n color: var(--md-outline-variant);\n margin-bottom: 0.5rem;\n}\n\n.empty-state .empty-icon.warning {\n color: var(--md-secondary);\n}\n\n.empty-state .empty-text {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n.empty-state .empty-subtext {\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n margin: 0;\n max-width: 400px;\n}\n\n/* -----------------------------------------------------------------------------\n Info Box\n ----------------------------------------------------------------------------- */\n.info-box {\n background: var(--md-surface-container);\n border-radius: var(--md-corner-medium);\n padding: 1.5rem;\n margin-top: 1.5rem;\n text-align: left;\n max-width: 500px;\n border: 1px solid var(--md-outline-variant);\n}\n\n.info-box h4 {\n margin: 0 0 1rem 0;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--md-on-surface);\n}\n\n.info-box ol {\n margin: 0;\n padding-left: 1.25rem;\n font-size: 1rem;\n color: var(--md-on-surface);\n}\n\n.info-box ol li {\n margin-bottom: 0.5rem;\n}\n\n.info-box code {\n background: var(--md-surface-container-high);\n padding: 0.125rem 0.5rem;\n border-radius: var(--md-corner-extra-small);\n font-size: 0.8125rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n color: var(--md-on-surface);\n}\n\n/* -----------------------------------------------------------------------------\n Loading Container - Uses mj-loading component\n ----------------------------------------------------------------------------- */\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n min-height: 300px;\n}\n\n.loading-text {\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n margin-top: 1rem;\n}\n\n/* -----------------------------------------------------------------------------\n Modal Dialogs - MD3 Pattern\n ----------------------------------------------------------------------------- */\n.modal-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.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(--md-surface);\n border-radius: var(--md-corner-extra-large);\n box-shadow: var(--md-elevation-5);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n animation: slideUp 0.3s cubic-bezier(0, 0, 0.2, 1);\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: 20px;\n }\n\n .modal-dialog.fullscreen {\n border-radius: 0;\n max-height: 100vh;\n }\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 1.5rem;\n border-bottom: 1px solid var(--md-outline-variant);\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 .modal-title {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n font-size: 1.375rem;\n font-weight: 600;\n color: var(--md-on-surface);\n margin: 0;\n}\n\n/* Modal Header 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(--md-on-surface-variant);\n font-size: 1.125rem;\n cursor: pointer;\n border-radius: var(--md-corner-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(--md-primary);\n color: var(--md-on-primary);\n}\n\n.modal-action-btn:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.modal-header .modal-close {\n padding: 0.625rem;\n border: none;\n background: transparent;\n color: var(--md-on-surface-variant);\n font-size: 1.25rem;\n cursor: pointer;\n border-radius: var(--md-corner-full);\n 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.modal-header .modal-close:hover {\n background: var(--md-primary);\n color: var(--md-on-primary);\n}\n\n.modal-header .modal-close:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\n}\n\n.modal-body {\n padding: 1.5rem;\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 display: flex;\n justify-content: flex-end;\n gap: 0.75rem;\n padding: 1.5rem;\n border-top: 1px solid var(--md-outline-variant);\n background: var(--md-surface-container-low);\n flex-shrink: 0;\n}\n\n@media (max-width: 639px) {\n .modal-footer {\n padding: 1rem 1.25rem;\n flex-direction: column;\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 - MD3 Pattern\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(--md-on-surface);\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(--md-outline-variant);\n border-radius: var(--md-corner-small);\n font-size: 1rem;\n background: var(--md-surface);\n color: var(--md-on-surface);\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.form-input:hover,\n.form-select:hover,\n.form-textarea:hover {\n border-color: var(--md-primary);\n background: var(--md-surface-container-lowest);\n}\n\n.form-input:focus,\n.form-select:focus,\n.form-textarea:focus {\n outline: none;\n border-color: var(--md-primary);\n box-shadow: 0 0 0 3px rgba(0, 118, 182, 0.2);\n background: var(--md-surface);\n}\n\n.form-input::placeholder,\n.form-textarea::placeholder {\n color: var(--md-on-surface-variant);\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(--md-on-surface-variant);\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(--md-on-surface);\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(--md-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(--md-outline-variant);\n border-radius: var(--md-corner-medium);\n background: var(--md-surface-container-low);\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(--md-on-surface);\n}\n\n.form-section-title i {\n color: var(--md-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 - MD3 Pattern\n ----------------------------------------------------------------------------- */\n.confirm-dialog {\n background: var(--md-surface);\n border-radius: var(--md-corner-extra-large);\n box-shadow: var(--md-elevation-5);\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: 20px;\n }\n}\n\n.confirm-dialog-icon {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: var(--md-secondary-container);\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: #B5751A;\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(--md-on-surface);\n}\n\n.confirm-dialog-message {\n margin: 0;\n font-size: 1rem;\n color: var(--md-on-surface-variant);\n line-height: 1.6;\n}\n\n.confirm-dialog-message strong {\n color: var(--md-on-surface);\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(--md-surface-container);\n border-radius: var(--md-corner-small);\n font-size: 0.8125rem;\n color: var(--md-on-surface-variant);\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 Animations - MD3 Easing\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 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 Reduced Motion Support\n ----------------------------------------------------------------------------- */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n\n/* -----------------------------------------------------------------------------\n Focus Indicators - Accessibility\n ----------------------------------------------------------------------------- */\nbutton:focus-visible,\ninput:focus-visible,\nselect:focus-visible,\ntextarea:focus-visible,\na:focus-visible,\n[tabindex]:focus-visible {\n outline: 2px solid var(--md-primary);\n outline-offset: 2px;\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"] }]
|
|
1283
|
+
}], () => [{ type: i1.SharedService }, { type: i0.ChangeDetectorRef }], { onEscapeKey: [{
|
|
1284
|
+
type: HostListener,
|
|
1285
|
+
args: ['document:keydown.escape']
|
|
1286
|
+
}] }); })();
|
|
945
1287
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SqlLoggingComponent, { className: "SqlLoggingComponent", filePath: "src/lib/sql-logging/sql-logging.component.ts", lineNumber: 65 }); })();
|
|
946
1288
|
//# sourceMappingURL=sql-logging.component.js.map
|