@memberjunction/ng-explorer-settings 3.1.0 → 3.2.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.
@@ -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';
@@ -145,7 +145,7 @@ function SqlLoggingComponent_Conditional_8_Conditional_3_Template(rf, ctx) { if
145
145
  function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template(rf, ctx) { if (rf & 1) {
146
146
  const _r5 = i0.ɵɵgetCurrentView();
147
147
  i0.ɵɵelementStart(0, "button", 44);
148
- i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.stopAllSessions()); });
148
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openStopAllSessionsConfirm()); });
149
149
  i0.ɵɵelement(1, "i", 45);
150
150
  i0.ɵɵtext(2, " Stop All ");
151
151
  i0.ɵɵelementEnd();
@@ -181,7 +181,7 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template(rf, ctx)
181
181
  i0.ɵɵtext(11);
182
182
  i0.ɵɵelementEnd()()();
183
183
  i0.ɵɵelementStart(12, "button", 53);
184
- i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template_button_click_12_listener($event) { const session_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.stopSession(session_r7, $event)); });
184
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template_button_click_12_listener($event) { const session_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.openStopSessionConfirm(session_r7, $event)); });
185
185
  i0.ɵɵelement(13, "i", 45);
186
186
  i0.ɵɵelementEnd()();
187
187
  i0.ɵɵelementStart(14, "div", 54);
@@ -219,9 +219,13 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template
219
219
  i0.ɵɵelementStart(7, "button", 63);
220
220
  i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.loadSessionLog(ctx_r1.selectedSession)); });
221
221
  i0.ɵɵelement(8, "i", 32);
222
+ i0.ɵɵelementEnd();
223
+ i0.ɵɵelementStart(9, "button", 64);
224
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleLogViewerExpand()); });
225
+ i0.ɵɵelement(10, "i", 65);
222
226
  i0.ɵɵelementEnd()()();
223
- i0.ɵɵelementStart(9, "div", 64);
224
- i0.ɵɵelement(10, "mj-code-editor", 65);
227
+ i0.ɵɵelementStart(11, "div", 66);
228
+ i0.ɵɵelement(12, "mj-code-editor", 67);
225
229
  i0.ɵɵelementEnd();
226
230
  } if (rf & 2) {
227
231
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -231,12 +235,16 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template
231
235
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.autoRefresh);
232
236
  i0.ɵɵadvance(3);
233
237
  i0.ɵɵclassProp("fa-spin", ctx_r1.loading);
238
+ i0.ɵɵadvance();
239
+ i0.ɵɵproperty("title", ctx_r1.isLogViewerExpanded ? "Collapse" : "Expand");
240
+ i0.ɵɵadvance();
241
+ i0.ɵɵclassProp("fa-expand", !ctx_r1.isLogViewerExpanded)("fa-compress", ctx_r1.isLogViewerExpanded);
234
242
  i0.ɵɵadvance(2);
235
243
  i0.ɵɵproperty("value", ctx_r1.logContent)("readonly", true)("disabled", true)("language", "sql")("setup", "basic")("lineWrapping", true)("highlightWhitespace", false);
236
244
  } }
237
245
  function SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_11_Template(rf, ctx) { if (rf & 1) {
238
246
  i0.ɵɵelementStart(0, "div", 26);
239
- i0.ɵɵelement(1, "i", 66);
247
+ i0.ɵɵelement(1, "i", 68);
240
248
  i0.ɵɵelementStart(2, "p", 29);
241
249
  i0.ɵɵtext(3, "Select a Session");
242
250
  i0.ɵɵelementEnd();
@@ -254,7 +262,7 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if
254
262
  i0.ɵɵrepeaterCreate(7, SqlLoggingComponent_Conditional_8_Conditional_4_For_8_Template, 19, 8, "div", 42, _forTrack0);
255
263
  i0.ɵɵelementEnd()();
256
264
  i0.ɵɵelementStart(9, "div", 43);
257
- i0.ɵɵtemplate(10, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template, 11, 11)(11, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_11_Template, 6, 0, "div", 26);
265
+ i0.ɵɵtemplate(10, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_10_Template, 13, 16)(11, SqlLoggingComponent_Conditional_8_Conditional_4_Conditional_11_Template, 6, 0, "div", 26);
258
266
  i0.ɵɵelementEnd()();
259
267
  } if (rf & 2) {
260
268
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -262,12 +270,14 @@ function SqlLoggingComponent_Conditional_8_Conditional_4_Template(rf, ctx) { if
262
270
  i0.ɵɵconditional(ctx_r1.activeSessions.length > 0 ? 5 : -1);
263
271
  i0.ɵɵadvance(2);
264
272
  i0.ɵɵrepeater(ctx_r1.activeSessions);
265
- i0.ɵɵadvance(3);
273
+ i0.ɵɵadvance(2);
274
+ i0.ɵɵclassProp("expanded", ctx_r1.isLogViewerExpanded);
275
+ i0.ɵɵadvance();
266
276
  i0.ɵɵconditional(ctx_r1.selectedSession ? 10 : 11);
267
277
  } }
268
278
  function SqlLoggingComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
269
279
  i0.ɵɵelementStart(0, "div", 7);
270
- i0.ɵɵtemplate(1, SqlLoggingComponent_Conditional_8_Conditional_1_Template, 9, 0, "div", 26)(2, SqlLoggingComponent_Conditional_8_Conditional_2_Template, 19, 0, "div", 26)(3, SqlLoggingComponent_Conditional_8_Conditional_3_Template, 9, 0, "div", 26)(4, SqlLoggingComponent_Conditional_8_Conditional_4_Template, 12, 2, "div", 27);
280
+ i0.ɵɵtemplate(1, SqlLoggingComponent_Conditional_8_Conditional_1_Template, 9, 0, "div", 26)(2, SqlLoggingComponent_Conditional_8_Conditional_2_Template, 19, 0, "div", 26)(3, SqlLoggingComponent_Conditional_8_Conditional_3_Template, 9, 0, "div", 26)(4, SqlLoggingComponent_Conditional_8_Conditional_4_Template, 12, 4, "div", 27);
271
281
  i0.ɵɵelementEnd();
272
282
  } if (rf & 2) {
273
283
  const ctx_r1 = i0.ɵɵnextContext();
@@ -275,7 +285,7 @@ function SqlLoggingComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
275
285
  i0.ɵɵconditional(!ctx_r1.isOwner ? 1 : !ctx_r1.configEnabled ? 2 : ctx_r1.activeSessions.length === 0 ? 3 : 4);
276
286
  } }
277
287
  function SqlLoggingComponent_Conditional_9_For_24_Template(rf, ctx) { if (rf & 1) {
278
- i0.ɵɵelementStart(0, "option", 80);
288
+ i0.ɵɵelementStart(0, "option", 82);
279
289
  i0.ɵɵtext(1);
280
290
  i0.ɵɵelementEnd();
281
291
  } if (rf & 2) {
@@ -284,43 +294,69 @@ function SqlLoggingComponent_Conditional_9_For_24_Template(rf, ctx) { if (rf & 1
284
294
  i0.ɵɵadvance();
285
295
  i0.ɵɵtextInterpolate(option_r10.text);
286
296
  } }
297
+ function SqlLoggingComponent_Conditional_9_For_44_Template(rf, ctx) { if (rf & 1) {
298
+ i0.ɵɵelementStart(0, "option", 82);
299
+ i0.ɵɵtext(1);
300
+ i0.ɵɵelementEnd();
301
+ } if (rf & 2) {
302
+ const option_r11 = ctx.$implicit;
303
+ i0.ɵɵproperty("value", option_r11.value);
304
+ i0.ɵɵadvance();
305
+ i0.ɵɵtextInterpolate(option_r11.text);
306
+ } }
307
+ function SqlLoggingComponent_Conditional_9_Conditional_57_Template(rf, ctx) { if (rf & 1) {
308
+ const _r12 = i0.ɵɵgetCurrentView();
309
+ i0.ɵɵelementStart(0, "div", 76)(1, "label", 77);
310
+ i0.ɵɵtext(2, "Default Schema Name");
311
+ i0.ɵɵelementEnd();
312
+ i0.ɵɵelementStart(3, "input", 93);
313
+ i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Conditional_57_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.defaultSchemaName, $event) || (ctx_r1.newSessionOptions.defaultSchemaName = $event); return i0.ɵɵresetView($event); });
314
+ i0.ɵɵelementEnd();
315
+ i0.ɵɵelementStart(4, "div", 80);
316
+ i0.ɵɵtext(5, " Schema name to replace with ${flyway:defaultSchema} placeholder. ");
317
+ i0.ɵɵelementEnd()();
318
+ } if (rf & 2) {
319
+ const ctx_r1 = i0.ɵɵnextContext(2);
320
+ i0.ɵɵadvance(3);
321
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.defaultSchemaName);
322
+ } }
287
323
  function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
288
324
  const _r9 = i0.ɵɵgetCurrentView();
289
- i0.ɵɵelementStart(0, "div", 67);
325
+ i0.ɵɵelementStart(0, "div", 69);
290
326
  i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
291
- i0.ɵɵelementStart(1, "div", 68);
327
+ i0.ɵɵelementStart(1, "div", 70);
292
328
  i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r9); return i0.ɵɵresetView($event.stopPropagation()); });
293
- i0.ɵɵelementStart(2, "div", 69)(3, "h3", 70);
329
+ i0.ɵɵelementStart(2, "div", 71)(3, "h3", 72);
294
330
  i0.ɵɵelement(4, "i", 10);
295
331
  i0.ɵɵtext(5, " Start SQL Logging Session ");
296
332
  i0.ɵɵelementEnd();
297
- i0.ɵɵelementStart(6, "button", 71);
333
+ i0.ɵɵelementStart(6, "button", 73);
298
334
  i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
299
- i0.ɵɵelement(7, "i", 72);
335
+ i0.ɵɵelement(7, "i", 74);
300
336
  i0.ɵɵelementEnd()();
301
- i0.ɵɵelementStart(8, "div", 73)(9, "div", 74)(10, "label", 75);
337
+ i0.ɵɵelementStart(8, "div", 75)(9, "div", 76)(10, "label", 77);
302
338
  i0.ɵɵtext(11, "Session Name");
303
339
  i0.ɵɵelementEnd();
304
- i0.ɵɵelementStart(12, "input", 76);
340
+ i0.ɵɵelementStart(12, "input", 78);
305
341
  i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_input_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.sessionName, $event) || (ctx_r1.newSessionOptions.sessionName = $event); return i0.ɵɵresetView($event); });
306
342
  i0.ɵɵelementEnd()();
307
- i0.ɵɵelementStart(13, "div", 74)(14, "label", 75);
343
+ i0.ɵɵelementStart(13, "div", 76)(14, "label", 77);
308
344
  i0.ɵɵtext(15, "File Name");
309
345
  i0.ɵɵelementEnd();
310
- i0.ɵɵelementStart(16, "input", 77);
346
+ i0.ɵɵelementStart(16, "input", 79);
311
347
  i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_input_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.fileName, $event) || (ctx_r1.newSessionOptions.fileName = $event); return i0.ɵɵresetView($event); });
312
348
  i0.ɵɵelementEnd();
313
- i0.ɵɵelementStart(17, "div", 78);
349
+ i0.ɵɵelementStart(17, "div", 80);
314
350
  i0.ɵɵtext(18, "The SQL log will be saved to this file");
315
351
  i0.ɵɵelementEnd()();
316
- i0.ɵɵelementStart(19, "div", 74)(20, "label", 75);
352
+ i0.ɵɵelementStart(19, "div", 76)(20, "label", 77);
317
353
  i0.ɵɵtext(21, "Statement Types");
318
354
  i0.ɵɵelementEnd();
319
- i0.ɵɵelementStart(22, "select", 79);
355
+ i0.ɵɵelementStart(22, "select", 81);
320
356
  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);
357
+ i0.ɵɵrepeaterCreate(23, SqlLoggingComponent_Conditional_9_For_24_Template, 2, 2, "option", 82, _forTrack1);
322
358
  i0.ɵɵelementEnd()();
323
- i0.ɵɵelementStart(25, "div", 81)(26, "label", 61)(27, "input", 62);
359
+ i0.ɵɵelementStart(25, "div", 83)(26, "label", 61)(27, "input", 62);
324
360
  i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_input_ngModelChange_27_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.filterToCurrentUser, $event) || (ctx_r1.newSessionOptions.filterToCurrentUser = $event); return i0.ɵɵresetView($event); });
325
361
  i0.ɵɵelementEnd();
326
362
  i0.ɵɵtext(28, " Filter to my SQL statements only ");
@@ -334,15 +370,51 @@ function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
334
370
  i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_input_ngModelChange_33_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.prettyPrint, $event) || (ctx_r1.newSessionOptions.prettyPrint = $event); return i0.ɵɵresetView($event); });
335
371
  i0.ɵɵelementEnd();
336
372
  i0.ɵɵtext(34, " Pretty print SQL statements ");
373
+ i0.ɵɵelementEnd()();
374
+ i0.ɵɵelementStart(35, "div", 84)(36, "h4", 85);
375
+ i0.ɵɵelement(37, "i", 86);
376
+ i0.ɵɵtext(38, " SQL Pattern Filtering ");
377
+ i0.ɵɵelementEnd();
378
+ i0.ɵɵelementStart(39, "div", 76)(40, "label", 77);
379
+ i0.ɵɵtext(41, "Filter Mode");
380
+ i0.ɵɵelementEnd();
381
+ i0.ɵɵelementStart(42, "select", 81);
382
+ i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_select_ngModelChange_42_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.filterType, $event) || (ctx_r1.newSessionOptions.filterType = $event); return i0.ɵɵresetView($event); });
383
+ i0.ɵɵrepeaterCreate(43, SqlLoggingComponent_Conditional_9_For_44_Template, 2, 2, "option", 82, _forTrack1);
384
+ i0.ɵɵelementEnd();
385
+ i0.ɵɵelementStart(45, "div", 80);
386
+ i0.ɵɵtext(46, " Exclude: Skip SQL matching any pattern. Include: Only log SQL matching a pattern. ");
387
+ i0.ɵɵelementEnd()();
388
+ i0.ɵɵelementStart(47, "div", 76)(48, "label", 77);
389
+ i0.ɵɵtext(49, "Filter Patterns (one per line or comma-separated)");
390
+ i0.ɵɵelementEnd();
391
+ i0.ɵɵelementStart(50, "textarea", 87);
392
+ i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_textarea_ngModelChange_50_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.filterPatterns, $event) || (ctx_r1.newSessionOptions.filterPatterns = $event); return i0.ɵɵresetView($event); });
393
+ i0.ɵɵelementEnd();
394
+ i0.ɵɵelementStart(51, "div", 80);
395
+ i0.ɵɵtext(52, " Supports wildcards (*) and regex (/pattern/flags). Example: *spCreate* matches any SP starting with spCreate. ");
337
396
  i0.ɵɵelementEnd()()();
338
- i0.ɵɵelementStart(35, "div", 82)(36, "button", 83);
339
- i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_36_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
340
- i0.ɵɵtext(37, " Cancel ");
341
- i0.ɵɵelementEnd();
342
- i0.ɵɵelementStart(38, "button", 84);
343
- i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_38_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startNewSession()); });
344
- i0.ɵɵelement(39, "i", 10);
345
- i0.ɵɵtext(40, " Start Session ");
397
+ i0.ɵɵelementStart(53, "div", 84)(54, "h4", 85);
398
+ i0.ɵɵelement(55, "i", 88);
399
+ i0.ɵɵtext(56, " Advanced Options ");
400
+ i0.ɵɵelementEnd();
401
+ i0.ɵɵtemplate(57, SqlLoggingComponent_Conditional_9_Conditional_57_Template, 6, 1, "div", 76);
402
+ i0.ɵɵelementStart(58, "div", 83)(59, "label", 61)(60, "input", 62);
403
+ i0.ɵɵtwoWayListener("ngModelChange", function SqlLoggingComponent_Conditional_9_Template_input_ngModelChange_60_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r1.newSessionOptions.verboseOutput, $event) || (ctx_r1.newSessionOptions.verboseOutput = $event); return i0.ɵɵresetView($event); });
404
+ i0.ɵɵelementEnd();
405
+ i0.ɵɵtext(61, " Verbose Debug Output ");
406
+ i0.ɵɵelementEnd();
407
+ i0.ɵɵelementStart(62, "div", 89);
408
+ i0.ɵɵtext(63, " Log detailed filter decisions to server console (for debugging). ");
409
+ i0.ɵɵelementEnd()()()();
410
+ i0.ɵɵelementStart(64, "div", 90)(65, "button", 91);
411
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_65_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.startNewSession()); });
412
+ i0.ɵɵelement(66, "i", 10);
413
+ i0.ɵɵtext(67, " Start Session ");
414
+ i0.ɵɵelementEnd();
415
+ i0.ɵɵelementStart(68, "button", 92);
416
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_9_Template_button_click_68_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.showStartSessionDialog = false); });
417
+ i0.ɵɵtext(69, " Cancel ");
346
418
  i0.ɵɵelementEnd()()()();
347
419
  } if (rf & 2) {
348
420
  const ctx_r1 = i0.ɵɵnextContext();
@@ -360,9 +432,106 @@ function SqlLoggingComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
360
432
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.formatAsMigration);
361
433
  i0.ɵɵadvance(3);
362
434
  i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.prettyPrint);
435
+ i0.ɵɵadvance(9);
436
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.filterType);
437
+ i0.ɵɵadvance();
438
+ i0.ɵɵrepeater(ctx_r1.filterTypeOptions);
439
+ i0.ɵɵadvance(7);
440
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.filterPatterns);
441
+ i0.ɵɵadvance(7);
442
+ i0.ɵɵconditional(ctx_r1.newSessionOptions.formatAsMigration ? 57 : -1);
443
+ i0.ɵɵadvance(3);
444
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.newSessionOptions.verboseOutput);
363
445
  i0.ɵɵadvance(5);
364
446
  i0.ɵɵproperty("disabled", ctx_r1.loading);
365
447
  } }
448
+ function SqlLoggingComponent_Conditional_10_Conditional_6_Template(rf, ctx) { if (rf & 1) {
449
+ i0.ɵɵtext(0, " Stop All Sessions? ");
450
+ } }
451
+ function SqlLoggingComponent_Conditional_10_Conditional_7_Template(rf, ctx) { if (rf & 1) {
452
+ i0.ɵɵtext(0, " Stop Session? ");
453
+ } }
454
+ function SqlLoggingComponent_Conditional_10_Conditional_9_Template(rf, ctx) { if (rf & 1) {
455
+ i0.ɵɵtext(0, " Are you sure you want to stop ");
456
+ i0.ɵɵelementStart(1, "strong");
457
+ i0.ɵɵtext(2);
458
+ i0.ɵɵelementEnd();
459
+ i0.ɵɵtext(3, " SQL logging sessions? This action cannot be undone. ");
460
+ } if (rf & 2) {
461
+ const ctx_r1 = i0.ɵɵnextContext(2);
462
+ i0.ɵɵadvance(2);
463
+ i0.ɵɵtextInterpolate1("all ", ctx_r1.activeSessions.length, " active");
464
+ } }
465
+ function SqlLoggingComponent_Conditional_10_Conditional_10_Template(rf, ctx) { if (rf & 1) {
466
+ i0.ɵɵtext(0, " Are you sure you want to stop the session ");
467
+ i0.ɵɵelementStart(1, "strong");
468
+ i0.ɵɵtext(2);
469
+ i0.ɵɵelementEnd();
470
+ i0.ɵɵtext(3, "? ");
471
+ i0.ɵɵelementStart(4, "span", 102);
472
+ i0.ɵɵtext(5);
473
+ i0.ɵɵelementEnd();
474
+ } if (rf & 2) {
475
+ const ctx_r1 = i0.ɵɵnextContext(2);
476
+ i0.ɵɵadvance(2);
477
+ i0.ɵɵtextInterpolate1("\"", ctx_r1.sessionToStop.sessionName, "\"");
478
+ i0.ɵɵadvance(3);
479
+ i0.ɵɵtextInterpolate1(" This session has captured ", ctx_r1.sessionToStop.statementCount, " SQL statements. ");
480
+ } }
481
+ function SqlLoggingComponent_Conditional_10_Conditional_13_Template(rf, ctx) { if (rf & 1) {
482
+ i0.ɵɵelement(0, "i", 103);
483
+ i0.ɵɵtext(1, " Stopping... ");
484
+ } }
485
+ function SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
486
+ i0.ɵɵtext(0, " Stop All Sessions ");
487
+ } }
488
+ function SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_2_Template(rf, ctx) { if (rf & 1) {
489
+ i0.ɵɵtext(0, " Stop Session ");
490
+ } }
491
+ function SqlLoggingComponent_Conditional_10_Conditional_14_Template(rf, ctx) { if (rf & 1) {
492
+ i0.ɵɵelement(0, "i", 45);
493
+ i0.ɵɵtemplate(1, SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_1_Template, 1, 0)(2, SqlLoggingComponent_Conditional_10_Conditional_14_Conditional_2_Template, 1, 0);
494
+ } if (rf & 2) {
495
+ const ctx_r1 = i0.ɵɵnextContext(2);
496
+ i0.ɵɵadvance();
497
+ i0.ɵɵconditional(ctx_r1.isStoppingAll ? 1 : 2);
498
+ } }
499
+ function SqlLoggingComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
500
+ const _r13 = i0.ɵɵgetCurrentView();
501
+ i0.ɵɵelementStart(0, "div", 69);
502
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelStopConfirm()); });
503
+ i0.ɵɵelementStart(1, "div", 94);
504
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r13); return i0.ɵɵresetView($event.stopPropagation()); });
505
+ i0.ɵɵelementStart(2, "div", 95);
506
+ i0.ɵɵelement(3, "i", 96);
507
+ i0.ɵɵelementEnd();
508
+ i0.ɵɵelementStart(4, "div", 97)(5, "h3", 98);
509
+ i0.ɵɵtemplate(6, SqlLoggingComponent_Conditional_10_Conditional_6_Template, 1, 0)(7, SqlLoggingComponent_Conditional_10_Conditional_7_Template, 1, 0);
510
+ i0.ɵɵelementEnd();
511
+ i0.ɵɵelementStart(8, "p", 99);
512
+ i0.ɵɵtemplate(9, SqlLoggingComponent_Conditional_10_Conditional_9_Template, 4, 1)(10, SqlLoggingComponent_Conditional_10_Conditional_10_Template, 6, 2);
513
+ i0.ɵɵelementEnd()();
514
+ i0.ɵɵelementStart(11, "div", 100)(12, "button", 101);
515
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.confirmStopSession()); });
516
+ i0.ɵɵtemplate(13, SqlLoggingComponent_Conditional_10_Conditional_13_Template, 2, 0)(14, SqlLoggingComponent_Conditional_10_Conditional_14_Template, 3, 1);
517
+ i0.ɵɵelementEnd();
518
+ i0.ɵɵelementStart(15, "button", 2);
519
+ i0.ɵɵlistener("click", function SqlLoggingComponent_Conditional_10_Template_button_click_15_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.cancelStopConfirm()); });
520
+ i0.ɵɵtext(16, " Cancel ");
521
+ i0.ɵɵelementEnd()()()();
522
+ } if (rf & 2) {
523
+ const ctx_r1 = i0.ɵɵnextContext();
524
+ i0.ɵɵadvance(6);
525
+ i0.ɵɵconditional(ctx_r1.isStoppingAll ? 6 : 7);
526
+ i0.ɵɵadvance(3);
527
+ i0.ɵɵconditional(ctx_r1.isStoppingAll ? 9 : ctx_r1.sessionToStop ? 10 : -1);
528
+ i0.ɵɵadvance(3);
529
+ i0.ɵɵproperty("disabled", ctx_r1.loading);
530
+ i0.ɵɵadvance();
531
+ i0.ɵɵconditional(ctx_r1.loading ? 13 : 14);
532
+ i0.ɵɵadvance(2);
533
+ i0.ɵɵproperty("disabled", ctx_r1.loading);
534
+ } }
366
535
  /**
367
536
  * Angular component for managing SQL logging sessions in MemberJunction.
368
537
  *
@@ -407,6 +576,14 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
407
576
  refreshInterval = 5000; // 5 seconds
408
577
  /** Whether the start session dialog is currently visible */
409
578
  showStartSessionDialog = false;
579
+ /** Whether the log viewer is in expanded (fullscreen) mode */
580
+ isLogViewerExpanded = false;
581
+ /** Whether the stop session confirmation dialog is visible */
582
+ showStopConfirmDialog = false;
583
+ /** Session pending stop confirmation (single session or null for all) */
584
+ sessionToStop = null;
585
+ /** Whether stopping all sessions (vs single session) */
586
+ isStoppingAll = false;
410
587
  /** Options for creating a new SQL logging session */
411
588
  newSessionOptions = {
412
589
  /** Custom filename for the log file */
@@ -420,7 +597,12 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
420
597
  /** Whether to format SQL with proper indentation */
421
598
  prettyPrint: true,
422
599
  /** Human-readable name for the session */
423
- sessionName: ''
600
+ sessionName: '',
601
+ /** Regex filter options */
602
+ filterPatterns: '', // Comma or newline separated patterns
603
+ filterType: 'exclude',
604
+ verboseOutput: false,
605
+ defaultSchemaName: '__mj', // Default MJ schema
424
606
  };
425
607
  /** Available options for SQL statement type filtering */
426
608
  statementTypeOptions = [
@@ -428,6 +610,11 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
428
610
  { text: 'Queries Only', value: 'queries' },
429
611
  { text: 'Mutations Only', value: 'mutations' }
430
612
  ];
613
+ /** Options for Regex filter */
614
+ filterTypeOptions = [
615
+ { text: 'Exclude Matching (default)', value: 'exclude' },
616
+ { text: 'Include Matching Only', value: 'include' }
617
+ ];
431
618
  constructor(sharedService) {
432
619
  super();
433
620
  this.sharedService = sharedService;
@@ -553,7 +740,12 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
553
740
  formatAsMigration: this.newSessionOptions.formatAsMigration,
554
741
  statementTypes: this.newSessionOptions.statementTypes,
555
742
  prettyPrint: this.newSessionOptions.prettyPrint,
556
- sessionName: this.newSessionOptions.sessionName
743
+ sessionName: this.newSessionOptions.sessionName,
744
+ // Regex Filter Option
745
+ filterPatterns: this.parseFilterPatterns(this.newSessionOptions.filterPatterns),
746
+ filterType: this.newSessionOptions.filterType,
747
+ verboseOutput: this.newSessionOptions.verboseOutput,
748
+ defaultSchemaName: this.newSessionOptions.defaultSchemaName,
557
749
  }
558
750
  }
559
751
  };
@@ -579,18 +771,12 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
579
771
  }
580
772
  }
581
773
  /**
582
- * Stops a specific SQL logging session.
774
+ * Executes the stop operation for a specific SQL logging session.
775
+ * Called after user confirms via the confirmation dialog.
583
776
  *
584
777
  * @param session - The session object to stop
585
- * @param event - Optional event to stop propagation
586
778
  */
587
- async stopSession(session, event) {
588
- if (event) {
589
- event.stopPropagation();
590
- }
591
- if (!confirm(`Stop SQL logging session "${session.sessionName}"?`)) {
592
- return;
593
- }
779
+ async executeStopSession(session) {
594
780
  try {
595
781
  this.loading = true;
596
782
  const dataProvider = Metadata.Provider;
@@ -611,21 +797,19 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
611
797
  await this.loadActiveSessions();
612
798
  }
613
799
  catch (error) {
800
+ const errorMessage = error instanceof Error ? error.message : 'Failed to stop SQL logging session';
614
801
  console.error('Error stopping SQL logging session:', error);
615
- MJNotificationService.Instance.CreateSimpleNotification(`Error: ${error.message || 'Failed to stop SQL logging session'}`, 'error', 5000);
802
+ MJNotificationService.Instance.CreateSimpleNotification(`Error: ${errorMessage}`, 'error', 5000);
616
803
  }
617
804
  finally {
618
805
  this.loading = false;
619
806
  }
620
807
  }
621
808
  /**
622
- * Stops all currently active SQL logging sessions.
623
- * Prompts for confirmation before proceeding.
809
+ * Executes the stop operation for all active SQL logging sessions.
810
+ * Called after user confirms via the confirmation dialog.
624
811
  */
625
- async stopAllSessions() {
626
- if (!confirm('Stop ALL active SQL logging sessions?')) {
627
- return;
628
- }
812
+ async executeStopAllSessions() {
629
813
  try {
630
814
  this.loading = true;
631
815
  const dataProvider = Metadata.Provider;
@@ -644,8 +828,9 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
644
828
  await this.loadActiveSessions();
645
829
  }
646
830
  catch (error) {
831
+ const errorMessage = error instanceof Error ? error.message : 'Failed to stop all SQL logging sessions';
647
832
  console.error('Error stopping all SQL logging sessions:', error);
648
- MJNotificationService.Instance.CreateSimpleNotification(`Error: ${error.message || 'Failed to stop all SQL logging sessions'}`, 'error', 5000);
833
+ MJNotificationService.Instance.CreateSimpleNotification(`Error: ${errorMessage}`, 'error', 5000);
649
834
  }
650
835
  finally {
651
836
  this.loading = false;
@@ -872,12 +1057,89 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
872
1057
  }
873
1058
  /**
874
1059
  * Calculates the total number of SQL statements across all active sessions.
875
- *
876
1060
  * @returns Total statement count
877
1061
  */
878
1062
  getTotalStatementCount() {
879
1063
  return this.activeSessions.reduce((sum, session) => sum + (session.statementCount || 0), 0);
880
1064
  }
1065
+ /**
1066
+ * Parses a string of filter patterns (comma or newline separated) into an array
1067
+ * @param patternsString - Comma or newline separated patterns
1068
+ * @returns Array of pattern strings, or undefined if empty
1069
+ */
1070
+ parseFilterPatterns(patternsString) {
1071
+ if (!patternsString || !patternsString.trim()) {
1072
+ return undefined;
1073
+ }
1074
+ /** Split by comma or newline, trim whitespace, filter empty */
1075
+ return patternsString
1076
+ .split(/[,\n]/)
1077
+ .map((p) => p.trim())
1078
+ .filter((p) => p.length > 0);
1079
+ }
1080
+ /**
1081
+ * Toggles the log viewer between normal and expanded (fullscreen) mode.
1082
+ */
1083
+ toggleLogViewerExpand() {
1084
+ this.isLogViewerExpanded = !this.isLogViewerExpanded;
1085
+ }
1086
+ /**
1087
+ * Handles keyboard events for the component.
1088
+ * Closes expanded log viewer or confirmation dialog when Escape is pressed.
1089
+ */
1090
+ onEscapeKey() {
1091
+ if (this.showStopConfirmDialog) {
1092
+ this.cancelStopConfirm();
1093
+ }
1094
+ else if (this.isLogViewerExpanded) {
1095
+ this.isLogViewerExpanded = false;
1096
+ }
1097
+ else if (this.showStartSessionDialog) {
1098
+ this.showStartSessionDialog = false;
1099
+ }
1100
+ }
1101
+ /**
1102
+ * Opens the confirmation dialog for stopping a single session.
1103
+ *
1104
+ * @param session - The session to stop
1105
+ * @param event - Optional event to stop propagation
1106
+ */
1107
+ openStopSessionConfirm(session, event) {
1108
+ if (event) {
1109
+ event.stopPropagation();
1110
+ }
1111
+ this.sessionToStop = session;
1112
+ this.isStoppingAll = false;
1113
+ this.showStopConfirmDialog = true;
1114
+ }
1115
+ /**
1116
+ * Opens the confirmation dialog for stopping all sessions.
1117
+ */
1118
+ openStopAllSessionsConfirm() {
1119
+ this.sessionToStop = null;
1120
+ this.isStoppingAll = true;
1121
+ this.showStopConfirmDialog = true;
1122
+ }
1123
+ /**
1124
+ * Closes the stop confirmation dialog without taking action.
1125
+ */
1126
+ cancelStopConfirm() {
1127
+ this.showStopConfirmDialog = false;
1128
+ this.sessionToStop = null;
1129
+ this.isStoppingAll = false;
1130
+ }
1131
+ /**
1132
+ * Confirms and executes the stop action (single session or all sessions).
1133
+ */
1134
+ async confirmStopSession() {
1135
+ if (this.isStoppingAll) {
1136
+ await this.executeStopAllSessions();
1137
+ }
1138
+ else if (this.sessionToStop) {
1139
+ await this.executeStopSession(this.sessionToStop);
1140
+ }
1141
+ this.cancelStopConfirm();
1142
+ }
881
1143
  /**
882
1144
  * Debug method to test contextUser flow for SQL filtering.
883
1145
  * This shows how the new architecture handles user context without storing email in provider.
@@ -907,7 +1169,9 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
907
1169
  }
908
1170
  }
909
1171
  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"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 10, vars: 8, consts: [[1, "sql-logging-container"], [1, "action-buttons"], [1, "btn-secondary", 3, "click", "disabled"], [1, "fa-solid", "fa-refresh"], ["title", "Start SQL logging session", 1, "btn-primary", 3, "disabled"], [1, "stats-grid", 2, "display", "flex"], [1, "loading-container"], [1, "content-area"], [1, "modal-backdrop"], ["title", "Start SQL logging session", 1, "btn-primary", 3, "click", "disabled"], [1, "fa-solid", "fa-play"], [1, "stat-card"], [1, "stat-icon", "stat-icon-status"], [1, "fa-solid", "fa-power-off"], [1, "stat-content"], [1, "stat-value"], [1, "stat-label"], [1, "stat-icon", "stat-icon-active"], [1, "fa-solid", "fa-play-circle"], [1, "stat-icon", "stat-icon-limit"], [1, "fa-solid", "fa-gauge-high"], [1, "stat-icon", "stat-icon-total"], [1, "fa-solid", "fa-database"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "empty-state"], [1, "sessions-layout"], [1, "fa-solid", "fa-lock", "empty-icon"], [1, "empty-text"], [1, "empty-subtext"], [1, "btn-secondary", 2, "margin-top", "1rem", 3, "click"], [1, "fa-solid", "fa-sync"], [1, "fa-solid", "fa-exclamation-triangle", "empty-icon", "warning"], [1, "info-box"], [1, "fa-solid", "fa-file-code", "empty-icon"], [1, "btn-primary", 2, "margin-top", "1rem", 3, "click"], [1, "sessions-panel"], [1, "panel-header"], [1, "panel-title"], ["title", "Stop all sessions", 1, "btn-danger", "btn-small", 3, "disabled"], [1, "sessions-list"], [1, "session-card", 3, "selected"], [1, "log-viewer-panel"], ["title", "Stop all sessions", 1, "btn-danger", "btn-small", 3, "click", "disabled"], [1, "fa-solid", "fa-stop"], [1, "session-card", 3, "click"], [1, "session-header"], [1, "session-info"], [1, "session-title"], [1, "session-meta"], [1, "meta-item"], [1, "fa-solid", "fa-clock"], ["title", "Stop session", 1, "action-btn", "action-btn-danger", 3, "click"], [1, "session-badges"], [1, "badge", "badge-user"], [1, "badge", "badge-migration"], [1, "badge", "badge-type"], [1, "fa-solid", "fa-user"], [1, "fa-solid", "fa-code-branch"], [1, "panel-actions"], [1, "checkbox-label"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], ["title", "Refresh log", 1, "action-btn", 3, "click"], [1, "log-content"], [2, "height", "100%", 3, "value", "readonly", "disabled", "language", "setup", "lineWrapping", "highlightWhitespace"], [1, "fa-solid", "fa-arrow-left", "empty-icon"], [1, "modal-backdrop", 3, "click"], [1, "modal-dialog", "modal-large", 3, "click"], [1, "modal-header"], [1, "modal-title"], [1, "modal-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [1, "form-group"], [1, "form-label"], ["type", "text", "placeholder", "Enter a descriptive name for this session", 1, "form-input", 3, "ngModelChange", "ngModel"], ["type", "text", "placeholder", "sql-log-2024-01-01.sql", 1, "form-input", 3, "ngModelChange", "ngModel"], [1, "form-hint"], [1, "form-select", 3, "ngModelChange", "ngModel"], [3, "value"], [1, "form-checkboxes"], [1, "modal-footer"], [1, "btn-secondary", 3, "click"], [1, "btn-primary", 3, "click", "disabled"]], template: function SqlLoggingComponent_Template(rf, ctx) { if (rf & 1) {
1172
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SqlLoggingComponent, selectors: [["mj-sql-logging"]], hostBindings: function SqlLoggingComponent_HostBindings(rf, ctx) { if (rf & 1) {
1173
+ i0.ɵɵlistener("keydown.escape", function SqlLoggingComponent_keydown_escape_HostBindingHandler() { return ctx.onEscapeKey(); }, false, i0.ɵɵresolveDocument);
1174
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 11, vars: 9, consts: [[1, "sql-logging-container"], [1, "action-buttons"], [1, "btn-secondary", 3, "click", "disabled"], [1, "fa-solid", "fa-refresh"], ["title", "Start SQL logging session", 1, "btn-primary", 3, "disabled"], [1, "stats-grid", 2, "display", "flex"], [1, "loading-container"], [1, "content-area"], [1, "modal-backdrop"], ["title", "Start SQL logging session", 1, "btn-primary", 3, "click", "disabled"], [1, "fa-solid", "fa-play"], [1, "stat-card"], [1, "stat-icon", "stat-icon-status"], [1, "fa-solid", "fa-power-off"], [1, "stat-content"], [1, "stat-value"], [1, "stat-label"], [1, "stat-icon", "stat-icon-active"], [1, "fa-solid", "fa-play-circle"], [1, "stat-icon", "stat-icon-limit"], [1, "fa-solid", "fa-gauge-high"], [1, "stat-icon", "stat-icon-total"], [1, "fa-solid", "fa-database"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "empty-state"], [1, "sessions-layout"], [1, "fa-solid", "fa-lock", "empty-icon"], [1, "empty-text"], [1, "empty-subtext"], [1, "btn-secondary", 2, "margin-top", "1rem", 3, "click"], [1, "fa-solid", "fa-sync"], [1, "fa-solid", "fa-exclamation-triangle", "empty-icon", "warning"], [1, "info-box"], [1, "fa-solid", "fa-file-code", "empty-icon"], [1, "btn-primary", 2, "margin-top", "1rem", 3, "click"], [1, "sessions-panel"], [1, "panel-header"], [1, "panel-title"], ["title", "Stop all sessions", 1, "btn-danger", "btn-small", 3, "disabled"], [1, "sessions-list"], [1, "session-card", 3, "selected"], [1, "log-viewer-panel"], ["title", "Stop all sessions", 1, "btn-danger", "btn-small", 3, "click", "disabled"], [1, "fa-solid", "fa-stop"], [1, "session-card", 3, "click"], [1, "session-header"], [1, "session-info"], [1, "session-title"], [1, "session-meta"], [1, "meta-item"], [1, "fa-solid", "fa-clock"], ["title", "Stop session", 1, "action-btn", "action-btn-danger", 3, "click"], [1, "session-badges"], [1, "badge", "badge-user"], [1, "badge", "badge-migration"], [1, "badge", "badge-type"], [1, "fa-solid", "fa-user"], [1, "fa-solid", "fa-code-branch"], [1, "panel-actions"], [1, "checkbox-label"], ["type", "checkbox", 3, "ngModelChange", "ngModel"], ["title", "Refresh log", 1, "action-btn", 3, "click"], [1, "action-btn", 3, "click", "title"], [1, "fa-solid"], [1, "log-content"], [2, "height", "100%", 3, "value", "readonly", "disabled", "language", "setup", "lineWrapping", "highlightWhitespace"], [1, "fa-solid", "fa-arrow-left", "empty-icon"], [1, "modal-backdrop", 3, "click"], [1, "modal-dialog", "modal-large", 3, "click"], [1, "modal-header"], [1, "modal-title"], [1, "modal-close", 3, "click"], [1, "fa-solid", "fa-times"], [1, "modal-body"], [1, "form-group"], [1, "form-label"], ["type", "text", "placeholder", "Enter a descriptive name for this session", 1, "form-input", 3, "ngModelChange", "ngModel"], ["type", "text", "placeholder", "sql-log-2024-01-01.sql", 1, "form-input", 3, "ngModelChange", "ngModel"], [1, "form-hint"], [1, "form-select", 3, "ngModelChange", "ngModel"], [3, "value"], [1, "form-checkboxes"], [1, "form-section"], [1, "form-section-title"], [1, "fa-solid", "fa-filter"], ["rows", "4", "placeholder", "Examples:\n*AIPrompt*\n/spCreate.*Run/i\nSELECT * FROM vwMetadata", 1, "form-textarea", 3, "ngModelChange", "ngModel"], [1, "fa-solid", "fa-cog"], [1, "form-hint", 2, "margin-left", "1.5rem"], [1, "modal-footer"], [1, "btn-primary", 3, "click", "disabled"], [1, "btn-secondary", 3, "click"], ["type", "text", "placeholder", "__mj", 1, "form-input", 3, "ngModelChange", "ngModel"], [1, "confirm-dialog", 3, "click"], [1, "confirm-dialog-icon"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "confirm-dialog-content"], [1, "confirm-dialog-title"], [1, "confirm-dialog-message"], [1, "confirm-dialog-actions"], [1, "btn-danger", 3, "click", "disabled"], [1, "confirm-dialog-details"], [1, "fa-solid", "fa-spinner", "fa-spin"]], template: function SqlLoggingComponent_Template(rf, ctx) { if (rf & 1) {
911
1175
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "button", 2);
912
1176
  i0.ɵɵlistener("click", function SqlLoggingComponent_Template_button_click_2_listener() { return ctx.loadActiveSessions(); });
913
1177
  i0.ɵɵelement(3, "i", 3);
@@ -915,7 +1179,7 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
915
1179
  i0.ɵɵelementEnd();
916
1180
  i0.ɵɵtemplate(5, SqlLoggingComponent_Conditional_5_Template, 3, 1, "button", 4);
917
1181
  i0.ɵɵelementEnd();
918
- i0.ɵɵtemplate(6, SqlLoggingComponent_Conditional_6_Template, 33, 4, "div", 5)(7, SqlLoggingComponent_Conditional_7_Template, 7, 0, "div", 6)(8, SqlLoggingComponent_Conditional_8_Template, 5, 1, "div", 7)(9, SqlLoggingComponent_Conditional_9_Template, 41, 7, "div", 8);
1182
+ i0.ɵɵtemplate(6, SqlLoggingComponent_Conditional_6_Template, 33, 4, "div", 5)(7, SqlLoggingComponent_Conditional_7_Template, 7, 0, "div", 6)(8, SqlLoggingComponent_Conditional_8_Template, 5, 1, "div", 7)(9, SqlLoggingComponent_Conditional_9_Template, 70, 11, "div", 8)(10, SqlLoggingComponent_Conditional_10_Template, 17, 5, "div", 8);
919
1183
  i0.ɵɵelementEnd();
920
1184
  } if (rf & 2) {
921
1185
  i0.ɵɵadvance(2);
@@ -932,7 +1196,9 @@ let SqlLoggingComponent = class SqlLoggingComponent extends BaseDashboard {
932
1196
  i0.ɵɵconditional(!ctx.loading || ctx.activeSessions.length > 0 ? 8 : -1);
933
1197
  i0.ɵɵadvance();
934
1198
  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}"] });
1199
+ i0.ɵɵadvance();
1200
+ i0.ɵɵconditional(ctx.showStopConfirmDialog ? 10 : -1);
1201
+ } }, 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\n\n.form-section[_ngcontent-%COMP%] {\n margin-top: 1.5rem;\n padding: 1.25rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #f9fafb;\n}\n\n.form-section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin: 0 0 1rem 0;\n font-size: 1rem;\n font-weight: 600;\n color: #374151;\n}\n\n.form-section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6b7280;\n}\n\n.form-textarea[_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 font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n resize: vertical;\n transition: all 0.2s;\n}\n\n.form-textarea[_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-textarea[_ngcontent-%COMP%]::placeholder {\n color: #9ca3af;\n font-style: italic;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes _ngcontent-%COMP%_slideUp {\n from {\n transform: translateY(20px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n\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 ease;\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@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\n\n.confirm-dialog[_ngcontent-%COMP%] {\n background: white;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 420px;\n width: 90%;\n padding: 2rem;\n text-align: center;\n animation: _ngcontent-%COMP%_dialogBounce 0.3s ease;\n}\n\n@keyframes _ngcontent-%COMP%_dialogBounce {\n 0% {\n transform: scale(0.9) translateY(10px);\n opacity: 0;\n }\n 50% {\n transform: scale(1.02) translateY(-5px);\n }\n 100% {\n transform: scale(1) translateY(0);\n opacity: 1;\n }\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n box-shadow: 0 4px 12px rgba(255, 152, 0, 0.2);\n}\n\n.confirm-dialog-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.75rem;\n color: #f57c00;\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: 700;\n color: #1f2937;\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 0.95rem;\n color: #4b5563;\n line-height: 1.6;\n}\n\n.confirm-dialog-message[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n color: #1f2937;\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: #f3f4f6;\n border-radius: 8px;\n font-size: 0.875rem;\n color: #6b7280;\n}\n\n.confirm-dialog-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 0.75rem;\n justify-content: center;\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}"] });
936
1202
  };
937
1203
  SqlLoggingComponent = __decorate([
938
1204
  RegisterClass(BaseDashboard, 'SqlLogging')
@@ -940,7 +1206,10 @@ SqlLoggingComponent = __decorate([
940
1206
  export { SqlLoggingComponent };
941
1207
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SqlLoggingComponent, [{
942
1208
  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 }], null); })();
1209
+ 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)=\"openStopAllSessionsConfirm()\"\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)=\"openStopSessionConfirm(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\" [class.expanded]=\"isLogViewerExpanded\">\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 <button\n class=\"action-btn\"\n (click)=\"toggleLogViewerExpand()\"\n [title]=\"isLogViewerExpanded ? 'Collapse' : 'Expand'\"\n >\n <i class=\"fa-solid\" [class.fa-expand]=\"!isLogViewerExpanded\" [class.fa-compress]=\"isLogViewerExpanded\"></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\n <!-- SQL Pattern Filtering Section -->\n <div class=\"form-section\">\n <h4 class=\"form-section-title\">\n <i class=\"fa-solid fa-filter\"></i>\n SQL Pattern Filtering\n </h4>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Filter Mode</label>\n <select\n class=\"form-select\"\n [(ngModel)]=\"newSessionOptions.filterType\"\n >\n @for (option of filterTypeOptions; track option.value) {\n <option [value]=\"option.value\">{{ option.text }}</option>\n }\n </select>\n <div class=\"form-hint\">\n Exclude: Skip SQL matching any pattern. Include: Only log SQL matching a pattern.\n </div>\n </div>\n\n <div class=\"form-group\">\n <label class=\"form-label\">Filter Patterns (one per line or comma-separated)</label>\n <textarea\n class=\"form-textarea\"\n [(ngModel)]=\"newSessionOptions.filterPatterns\"\n rows=\"4\"\n placeholder=\"Examples:&#10;*AIPrompt*&#10;/spCreate.*Run/i&#10;SELECT * FROM vwMetadata\"\n ></textarea>\n <div class=\"form-hint\">\n Supports wildcards (*) and regex (/pattern/flags).\n Example: *spCreate* matches any SP starting with spCreate.\n </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\"></i>\n Advanced Options\n </h4>\n\n @if (newSessionOptions.formatAsMigration) {\n <div class=\"form-group\">\n <label class=\"form-label\">Default Schema Name</label>\n <input\n type=\"text\"\n class=\"form-input\"\n [(ngModel)]=\"newSessionOptions.defaultSchemaName\"\n placeholder=\"__mj\"\n />\n <div class=\"form-hint\">\n Schema name to replace with $&#123;flyway:defaultSchema&#125; placeholder.\n </div>\n </div>\n }\n\n <div class=\"form-checkboxes\">\n <label class=\"checkbox-label\">\n <input\n type=\"checkbox\"\n [(ngModel)]=\"newSessionOptions.verboseOutput\"\n />\n Verbose Debug Output\n </label>\n <div class=\"form-hint\" style=\"margin-left: 1.5rem;\">\n Log detailed filter decisions to server console (for debugging).\n </div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button class=\"btn-primary\" (click)=\"startNewSession()\" [disabled]=\"loading\">\n <i class=\"fa-solid fa-play\"></i>\n Start Session\n </button>\n <button class=\"btn-secondary\" (click)=\"showStartSessionDialog = false\">\n Cancel\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- Stop Session Confirmation Dialog -->\n @if (showStopConfirmDialog) {\n <div class=\"modal-backdrop\" (click)=\"cancelStopConfirm()\">\n <div class=\"confirm-dialog\" (click)=\"$event.stopPropagation()\">\n <div class=\"confirm-dialog-icon\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n </div>\n <div class=\"confirm-dialog-content\">\n <h3 class=\"confirm-dialog-title\">\n @if (isStoppingAll) {\n Stop All Sessions?\n } @else {\n Stop Session?\n }\n </h3>\n <p class=\"confirm-dialog-message\">\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\">\n This session has captured {{ sessionToStop.statementCount }} SQL statements.\n </span>\n }\n </p>\n </div>\n <div class=\"confirm-dialog-actions\">\n <button\n class=\"btn-danger\"\n (click)=\"confirmStopSession()\"\n [disabled]=\"loading\"\n >\n @if (loading) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Stopping...\n } @else {\n <i class=\"fa-solid fa-stop\"></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\">\n Cancel\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/* Form Section Styles */\n.form-section {\n margin-top: 1.5rem;\n padding: 1.25rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #f9fafb;\n}\n\n.form-section-title {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin: 0 0 1rem 0;\n font-size: 1rem;\n font-weight: 600;\n color: #374151;\n}\n\n.form-section-title i {\n color: #6b7280;\n}\n\n.form-textarea {\n width: 100%;\n padding: 0.75rem 1rem;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n font-size: 0.95rem;\n font-family: \"Consolas\", \"Monaco\", \"Courier New\", monospace;\n resize: vertical;\n transition: all 0.2s;\n}\n\n.form-textarea: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-textarea::placeholder {\n color: #9ca3af;\n font-style: italic;\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\n/* Expanded Log Viewer Styles */\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 ease;\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@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/* Confirmation Dialog Styles */\n.confirm-dialog {\n background: white;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 420px;\n width: 90%;\n padding: 2rem;\n text-align: center;\n animation: dialogBounce 0.3s ease;\n}\n\n@keyframes dialogBounce {\n 0% {\n transform: scale(0.9) translateY(10px);\n opacity: 0;\n }\n 50% {\n transform: scale(1.02) translateY(-5px);\n }\n 100% {\n transform: scale(1) translateY(0);\n opacity: 1;\n }\n}\n\n.confirm-dialog-icon {\n width: 64px;\n height: 64px;\n border-radius: 50%;\n background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n box-shadow: 0 4px 12px rgba(255, 152, 0, 0.2);\n}\n\n.confirm-dialog-icon i {\n font-size: 1.75rem;\n color: #f57c00;\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: 700;\n color: #1f2937;\n}\n\n.confirm-dialog-message {\n margin: 0;\n font-size: 0.95rem;\n color: #4b5563;\n line-height: 1.6;\n}\n\n.confirm-dialog-message strong {\n color: #1f2937;\n font-weight: 600;\n}\n\n.confirm-dialog-details {\n display: block;\n margin-top: 0.75rem;\n padding: 0.75rem;\n background: #f3f4f6;\n border-radius: 8px;\n font-size: 0.875rem;\n color: #6b7280;\n}\n\n.confirm-dialog-actions {\n display: flex;\n gap: 0.75rem;\n justify-content: center;\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"] }]
1210
+ }], () => [{ type: i1.SharedService }], { onEscapeKey: [{
1211
+ type: HostListener,
1212
+ args: ['document:keydown.escape']
1213
+ }] }); })();
945
1214
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SqlLoggingComponent, { className: "SqlLoggingComponent", filePath: "src/lib/sql-logging/sql-logging.component.ts", lineNumber: 65 }); })();
946
1215
  //# sourceMappingURL=sql-logging.component.js.map