@memberjunction/ng-query-viewer 5.10.1 → 5.11.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.
@@ -5,6 +5,8 @@ import { debounceTime, takeUntil } from 'rxjs/operators';
5
5
  import { UserInfoEngine } from '@memberjunction/core-entities';
6
6
  import * as i0 from "@angular/core";
7
7
  import * as i1 from "@memberjunction/ng-markdown";
8
+ import * as i2 from "@memberjunction/ng-code-editor";
9
+ const _forTrack0 = ($index, $item) => $item.ID;
8
10
  function QueryInfoPanelComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
9
11
  const _r1 = i0.ɵɵgetCurrentView();
10
12
  i0.ɵɵelementStart(0, "div", 2);
@@ -273,13 +275,14 @@ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_23_Tem
273
275
  i0.ɵɵconditional(ctx_r1.QueryInfo.Parameters.length ? 1 : 2);
274
276
  } }
275
277
  function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_1_Template(rf, ctx) { if (rf & 1) {
276
- i0.ɵɵelementStart(0, "div", 55)(1, "pre", 56);
277
- i0.ɵɵtext(2);
278
+ const _r8 = i0.ɵɵgetCurrentView();
279
+ i0.ɵɵelementStart(0, "div", 55)(1, "mj-code-editor", 56);
280
+ i0.ɵɵlistener("CompositionTokenClick", function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_1_Template_mj_code_editor_CompositionTokenClick_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnCompositionTokenClick($event)); });
278
281
  i0.ɵɵelementEnd()();
279
282
  } if (rf & 2) {
280
283
  const ctx_r1 = i0.ɵɵnextContext(4);
281
- i0.ɵɵadvance(2);
282
- i0.ɵɵtextInterpolate(ctx_r1.QueryInfo.SQL);
284
+ i0.ɵɵadvance();
285
+ i0.ɵɵproperty("value", ctx_r1.QueryInfo.SQL)("readonly", true)("language", "sql");
283
286
  } }
284
287
  function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_2_Template(rf, ctx) { if (rf & 1) {
285
288
  i0.ɵɵelementStart(0, "div", 35);
@@ -290,13 +293,76 @@ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Con
290
293
  } }
291
294
  function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Template(rf, ctx) { if (rf & 1) {
292
295
  i0.ɵɵelementStart(0, "div", 22);
293
- i0.ɵɵconditionalCreate(1, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_1_Template, 3, 1, "div", 55)(2, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_2_Template, 4, 0, "div", 35);
296
+ i0.ɵɵconditionalCreate(1, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_1_Template, 2, 3, "div", 55)(2, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Conditional_2_Template, 4, 0, "div", 35);
294
297
  i0.ɵɵelementEnd();
295
298
  } if (rf & 2) {
296
299
  const ctx_r1 = i0.ɵɵnextContext(3);
297
300
  i0.ɵɵadvance();
298
301
  i0.ɵɵconditional(ctx_r1.QueryInfo.SQL ? 1 : 2);
299
302
  } }
303
+ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_For_3_Conditional_5_Template(rf, ctx) { if (rf & 1) {
304
+ i0.ɵɵelementStart(0, "span", 66);
305
+ i0.ɵɵtext(1);
306
+ i0.ɵɵelementEnd();
307
+ } if (rf & 2) {
308
+ const dep_r11 = i0.ɵɵnextContext().$implicit;
309
+ i0.ɵɵadvance();
310
+ i0.ɵɵtextInterpolate1(" via ", dep_r11.ReferencePath, " ");
311
+ } }
312
+ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_For_3_Template(rf, ctx) { if (rf & 1) {
313
+ const _r10 = i0.ɵɵgetCurrentView();
314
+ i0.ɵɵelementStart(0, "div", 62);
315
+ i0.ɵɵlistener("click", function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_For_3_Template_div_click_0_listener() { const dep_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.OnDependentQueryClick(dep_r11)); });
316
+ i0.ɵɵelementStart(1, "div", 63);
317
+ i0.ɵɵelement(2, "i", 64);
318
+ i0.ɵɵelementStart(3, "span", 65);
319
+ i0.ɵɵtext(4);
320
+ i0.ɵɵelementEnd()();
321
+ i0.ɵɵconditionalCreate(5, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_For_3_Conditional_5_Template, 2, 1, "span", 66);
322
+ i0.ɵɵelementEnd();
323
+ } if (rf & 2) {
324
+ const dep_r11 = ctx.$implicit;
325
+ i0.ɵɵadvance(4);
326
+ i0.ɵɵtextInterpolate(dep_r11.Query);
327
+ i0.ɵɵadvance();
328
+ i0.ɵɵconditional(dep_r11.ReferencePath ? 5 : -1);
329
+ } }
330
+ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_Template(rf, ctx) { if (rf & 1) {
331
+ i0.ɵɵelementStart(0, "div", 22)(1, "div", 58);
332
+ i0.ɵɵrepeaterCreate(2, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_For_3_Template, 6, 2, "div", 59, _forTrack0);
333
+ i0.ɵɵelementEnd();
334
+ i0.ɵɵelementStart(4, "div", 60);
335
+ i0.ɵɵelement(5, "i", 61);
336
+ i0.ɵɵtext(6, " These queries reference this query via composition ");
337
+ i0.ɵɵelementEnd()();
338
+ } if (rf & 2) {
339
+ const ctx_r1 = i0.ɵɵnextContext(4);
340
+ i0.ɵɵadvance(2);
341
+ i0.ɵɵrepeater(ctx_r1.QueryInfo.Dependents);
342
+ } }
343
+ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Template(rf, ctx) { if (rf & 1) {
344
+ const _r9 = i0.ɵɵgetCurrentView();
345
+ i0.ɵɵelementStart(0, "div", 18)(1, "div", 19);
346
+ i0.ɵɵlistener("click", function QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleSection("dependents")); });
347
+ i0.ɵɵelement(2, "i", 20);
348
+ i0.ɵɵelementStart(3, "span", 21);
349
+ i0.ɵɵtext(4, "Dependent Queries");
350
+ i0.ɵɵelementEnd();
351
+ i0.ɵɵelementStart(5, "span", 24);
352
+ i0.ɵɵtext(6);
353
+ i0.ɵɵelementEnd()();
354
+ i0.ɵɵconditionalCreate(7, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Conditional_7_Template, 7, 0, "div", 22);
355
+ i0.ɵɵelementEnd();
356
+ } if (rf & 2) {
357
+ const ctx_r1 = i0.ɵɵnextContext(3);
358
+ i0.ɵɵclassProp("expanded", ctx_r1.IsSectionExpanded("dependents"));
359
+ i0.ɵɵadvance(2);
360
+ i0.ɵɵclassProp("fa-chevron-down", ctx_r1.IsSectionExpanded("dependents"))("fa-chevron-right", !ctx_r1.IsSectionExpanded("dependents"));
361
+ i0.ɵɵadvance(4);
362
+ i0.ɵɵtextInterpolate1("(", ctx_r1.QueryInfo.Dependents.length, ")");
363
+ i0.ɵɵadvance();
364
+ i0.ɵɵconditional(ctx_r1.IsSectionExpanded("dependents") ? 7 : -1);
365
+ } }
300
366
  function QueryInfoPanelComponent_Conditional_1_Conditional_11_Template(rf, ctx) { if (rf & 1) {
301
367
  const _r4 = i0.ɵɵgetCurrentView();
302
368
  i0.ɵɵelementStart(0, "div", 13)(1, "div", 18)(2, "div", 19);
@@ -337,7 +403,9 @@ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Template(rf, ctx)
337
403
  i0.ɵɵtext(28, "SQL Query");
338
404
  i0.ɵɵelementEnd()();
339
405
  i0.ɵɵconditionalCreate(29, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_29_Template, 3, 1, "div", 22);
340
- i0.ɵɵelementEnd()();
406
+ i0.ɵɵelementEnd();
407
+ i0.ɵɵconditionalCreate(30, QueryInfoPanelComponent_Conditional_1_Conditional_11_Conditional_30_Template, 8, 8, "div", 23);
408
+ i0.ɵɵelementEnd();
341
409
  } if (rf & 2) {
342
410
  const ctx_r1 = i0.ɵɵnextContext(2);
343
411
  i0.ɵɵadvance();
@@ -370,6 +438,8 @@ function QueryInfoPanelComponent_Conditional_1_Conditional_11_Template(rf, ctx)
370
438
  i0.ɵɵclassProp("fa-chevron-down", ctx_r1.IsSectionExpanded("sql"))("fa-chevron-right", !ctx_r1.IsSectionExpanded("sql"));
371
439
  i0.ɵɵadvance(3);
372
440
  i0.ɵɵconditional(ctx_r1.IsSectionExpanded("sql") ? 29 : -1);
441
+ i0.ɵɵadvance();
442
+ i0.ɵɵconditional(ctx_r1.QueryInfo.Dependents.length > 0 ? 30 : -1);
373
443
  } }
374
444
  function QueryInfoPanelComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
375
445
  const _r3 = i0.ɵɵgetCurrentView();
@@ -387,7 +457,7 @@ function QueryInfoPanelComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
387
457
  i0.ɵɵlistener("click", function QueryInfoPanelComponent_Conditional_1_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnClose()); });
388
458
  i0.ɵɵelement(10, "i", 12);
389
459
  i0.ɵɵelementEnd()();
390
- i0.ɵɵconditionalCreate(11, QueryInfoPanelComponent_Conditional_1_Conditional_11_Template, 30, 31, "div", 13);
460
+ i0.ɵɵconditionalCreate(11, QueryInfoPanelComponent_Conditional_1_Conditional_11_Template, 31, 32, "div", 13);
391
461
  i0.ɵɵelementStart(12, "div", 14)(13, "button", 15);
392
462
  i0.ɵɵlistener("click", function QueryInfoPanelComponent_Conditional_1_Template_button_click_13_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnOpenRecord()); });
393
463
  i0.ɵɵelement(14, "i", 16);
@@ -430,6 +500,7 @@ export class QueryInfoPanelComponent {
430
500
  // ========================================
431
501
  Close = new EventEmitter();
432
502
  OpenRecord = new EventEmitter();
503
+ CompositionTokenClick = new EventEmitter();
433
504
  // ========================================
434
505
  // Internal State
435
506
  // ========================================
@@ -473,6 +544,22 @@ export class QueryInfoPanelComponent {
473
544
  OnClose() {
474
545
  this.Close.emit();
475
546
  }
547
+ OnCompositionTokenClick(event) {
548
+ this.CompositionTokenClick.emit(event);
549
+ }
550
+ OnDependentQueryClick(dep) {
551
+ // Navigate to the dependent (referencing) query
552
+ const depQuery = dep.QueryInfo;
553
+ const categoryPath = depQuery?.CategoryPath?.replace(/^\/|\/$/g, '') || '';
554
+ const fullPath = categoryPath ? `${categoryPath}/${dep.Query}` : dep.Query;
555
+ this.CompositionTokenClick.emit({
556
+ FullToken: `{{query:"${fullPath}"}}`,
557
+ QueryName: dep.Query,
558
+ CategorySegments: categoryPath ? categoryPath.split('/') : [],
559
+ FullPath: fullPath,
560
+ MouseEvent: new MouseEvent('click')
561
+ });
562
+ }
476
563
  OnOpenRecord() {
477
564
  if (this.QueryInfo) {
478
565
  this.OpenRecord.emit({
@@ -539,14 +626,14 @@ export class QueryInfoPanelComponent {
539
626
  static ɵfac = function QueryInfoPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || QueryInfoPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
540
627
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: QueryInfoPanelComponent, selectors: [["mj-query-info-panel"]], hostBindings: function QueryInfoPanelComponent_HostBindings(rf, ctx) { if (rf & 1) {
541
628
  i0.ɵɵlistener("mousemove", function QueryInfoPanelComponent_mousemove_HostBindingHandler($event) { return ctx.OnMouseMove($event); }, i0.ɵɵresolveDocument)("mouseup", function QueryInfoPanelComponent_mouseup_HostBindingHandler() { return ctx.OnMouseUp(); }, i0.ɵɵresolveDocument);
542
- } }, inputs: { QueryInfo: "QueryInfo", Visible: "Visible", ShowOverlay: "ShowOverlay" }, outputs: { Close: "Close", OpenRecord: "OpenRecord" }, standalone: false, decls: 2, vars: 2, consts: [[1, "info-panel-overlay"], [1, "info-panel", 3, "width"], [1, "info-panel-overlay", 3, "click"], [1, "info-panel"], [1, "resize-handle", 3, "mousedown"], [1, "panel-header"], [1, "header-content"], [1, "fa-solid", "fa-circle-info", "header-icon"], [1, "header-text"], [1, "header-title"], [1, "header-subtitle"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "panel-footer"], [1, "btn", "btn-primary", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "btn", "btn-secondary", 3, "click"], [1, "info-section"], [1, "section-header", 3, "click"], [1, "fa-solid", "section-icon"], [1, "section-title"], [1, "section-content"], [1, "info-section", 3, "expanded"], [1, "section-count"], [1, "info-row"], [1, "info-label"], [1, "info-value"], [1, "status-badge"], [1, "info-value", "description"], [1, "fa-solid", "fa-folder", "category-icon"], [1, "fa-solid", "fa-check", "text-success"], [1, "section-content", "technical-description-content"], [3, "data", "enableMermaid", "enableHighlight", "enableCollapsibleHeadings", "enableSmartypants"], [1, "fields-list"], [1, "empty-section"], [1, "field-item"], [1, "field-header"], [1, "field-name"], [1, "field-type"], [1, "field-details"], [1, "field-description"], [1, "field-source"], [1, "fa-solid", "fa-link"], [1, "fa-solid", "fa-table-columns"], [1, "params-list"], [1, "param-item"], [1, "param-header"], [1, "param-name"], [1, "required-badge"], [1, "param-type"], [1, "param-details"], [1, "param-description"], [1, "param-default"], [1, "fa-solid", "fa-sliders"], [1, "sql-container"], [1, "sql-code"], [1, "fa-solid", "fa-code"]], template: function QueryInfoPanelComponent_Template(rf, ctx) { if (rf & 1) {
629
+ } }, inputs: { QueryInfo: "QueryInfo", Visible: "Visible", ShowOverlay: "ShowOverlay" }, outputs: { Close: "Close", OpenRecord: "OpenRecord", CompositionTokenClick: "CompositionTokenClick" }, standalone: false, decls: 2, vars: 2, consts: [[1, "info-panel-overlay"], [1, "info-panel", 3, "width"], [1, "info-panel-overlay", 3, "click"], [1, "info-panel"], [1, "resize-handle", 3, "mousedown"], [1, "panel-header"], [1, "header-content"], [1, "fa-solid", "fa-circle-info", "header-icon"], [1, "header-text"], [1, "header-title"], [1, "header-subtitle"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "panel-footer"], [1, "btn", "btn-primary", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "btn", "btn-secondary", 3, "click"], [1, "info-section"], [1, "section-header", 3, "click"], [1, "fa-solid", "section-icon"], [1, "section-title"], [1, "section-content"], [1, "info-section", 3, "expanded"], [1, "section-count"], [1, "info-row"], [1, "info-label"], [1, "info-value"], [1, "status-badge"], [1, "info-value", "description"], [1, "fa-solid", "fa-folder", "category-icon"], [1, "fa-solid", "fa-check", "text-success"], [1, "section-content", "technical-description-content"], [3, "data", "enableMermaid", "enableHighlight", "enableCollapsibleHeadings", "enableSmartypants"], [1, "fields-list"], [1, "empty-section"], [1, "field-item"], [1, "field-header"], [1, "field-name"], [1, "field-type"], [1, "field-details"], [1, "field-description"], [1, "field-source"], [1, "fa-solid", "fa-link"], [1, "fa-solid", "fa-table-columns"], [1, "params-list"], [1, "param-item"], [1, "param-header"], [1, "param-name"], [1, "required-badge"], [1, "param-type"], [1, "param-details"], [1, "param-description"], [1, "param-default"], [1, "fa-solid", "fa-sliders"], [1, "sql-container"], [3, "CompositionTokenClick", "value", "readonly", "language"], [1, "fa-solid", "fa-code"], [1, "dependents-list"], [1, "dependent-item"], [1, "dependents-hint"], [1, "fa-solid", "fa-info-circle"], [1, "dependent-item", 3, "click"], [1, "dependent-header"], [1, "fa-solid", "fa-arrow-left", "dependent-icon"], [1, "dependent-name"], [1, "dependent-ref-path"]], template: function QueryInfoPanelComponent_Template(rf, ctx) { if (rf & 1) {
543
630
  i0.ɵɵconditionalCreate(0, QueryInfoPanelComponent_Conditional_0_Template, 1, 1, "div", 0);
544
631
  i0.ɵɵconditionalCreate(1, QueryInfoPanelComponent_Conditional_1_Template, 18, 5, "div", 1);
545
632
  } if (rf & 2) {
546
633
  i0.ɵɵconditional(ctx.Visible && ctx.ShowOverlay ? 0 : -1);
547
634
  i0.ɵɵadvance();
548
635
  i0.ɵɵconditional(ctx.Visible ? 1 : -1);
549
- } }, dependencies: [i1.MarkdownComponent], styles: ["\n\n\n\n\n.info-panel-overlay[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n}\n\n\n\n.info-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n height: 100%;\n background: #fff;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n min-width: 350px;\n max-width: 800px;\n}\n\n\n\n.resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n background: transparent;\n transition: background 0.15s ease;\n z-index: 10;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover {\n background: rgba(92, 107, 192, 0.3);\n}\n\n.resize-handle[_ngcontent-%COMP%]:active {\n background: rgba(92, 107, 192, 0.5);\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n flex-shrink: 0;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.header-icon[_ngcontent-%COMP%] {\n font-size: 24px;\n opacity: 0.9;\n}\n\n.header-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.header-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n}\n\n.header-subtitle[_ngcontent-%COMP%] {\n font-size: 13px;\n opacity: 0.85;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n\n\n.info-section[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.info-section.expanded[_ngcontent-%COMP%] {\n border-color: #c5cae9;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #fafafa;\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n}\n\n.section-header[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n}\n\n.info-section.expanded[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] {\n background: #e8eaf6;\n border-bottom: 1px solid #c5cae9;\n}\n\n.section-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #666;\n width: 12px;\n text-align: center;\n}\n\n.section-title[_ngcontent-%COMP%] {\n flex: 1;\n font-weight: 600;\n font-size: 14px;\n color: #333;\n}\n\n.section-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n font-weight: 400;\n}\n\n.section-content[_ngcontent-%COMP%] {\n padding: 16px;\n background: #fff;\n}\n\n\n\n.technical-description-content[_ngcontent-%COMP%] {\n max-height: 400px;\n overflow-y: auto;\n}\n\n.technical-description-content [_nghost-%COMP%] .mj-markdown-container {\n font-size: 13px;\n line-height: 1.5;\n}\n\n\n\n.info-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.info-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: #888;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n line-height: 1.4;\n}\n\n.info-value.description[_ngcontent-%COMP%] {\n color: #555;\n font-style: italic;\n}\n\n.category-icon[_ngcontent-%COMP%] {\n color: #f9a825;\n margin-right: 4px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n background: #f5f5f5;\n color: #666;\n}\n\n.status-badge.approved[_ngcontent-%COMP%] {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.text-success[_ngcontent-%COMP%] {\n color: #2e7d32;\n}\n\n\n\n.fields-list[_ngcontent-%COMP%], \n.params-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.field-item[_ngcontent-%COMP%], \n.param-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 3px solid #5c6bc0;\n}\n\n.field-header[_ngcontent-%COMP%], \n.param-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 4px;\n}\n\n.field-name[_ngcontent-%COMP%], \n.param-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 13px;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.field-type[_ngcontent-%COMP%], \n.param-type[_ngcontent-%COMP%] {\n font-size: 11px;\n font-family: 'Consolas', 'Monaco', monospace;\n color: #666;\n background: #e8eaf6;\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.field-details[_ngcontent-%COMP%], \n.param-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 6px;\n}\n\n.field-description[_ngcontent-%COMP%], \n.param-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n font-style: italic;\n}\n\n.field-source[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #5c6bc0;\n}\n\n.field-source[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 4px;\n}\n\n.required-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n background: #ffebee;\n color: #c62828;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.param-default[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #888;\n}\n\n\n\n.sql-container[_ngcontent-%COMP%] {\n background: #1e1e1e;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.sql-code[_ngcontent-%COMP%] {\n margin: 0;\n padding: 16px;\n font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #d4d4d4;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-x: auto;\n}\n\n\n\n.empty-section[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: #888;\n font-style: italic;\n}\n\n.empty-section[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n opacity: 0.6;\n}\n\n\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 12px;\n padding: 16px 20px;\n background: #f5f5f5;\n border-top: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n background: linear-gradient(135deg, #7986cb 0%, #5c6bc0 100%);\n box-shadow: 0 2px 8px rgba(92, 107, 192, 0.4);\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: #fff;\n color: #333;\n border: 1px solid #ddd;\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n border-color: #ccc;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 6px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: #f5f5f5;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: #ccc;\n border-radius: 3px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n}"], data: { animation: [
636
+ } }, dependencies: [i1.MarkdownComponent, i2.CodeEditorComponent], styles: ["\n\n\n\n\n.info-panel-overlay[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n}\n\n\n\n.info-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n right: 0;\n height: 100%;\n background: #fff;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n min-width: 350px;\n max-width: 800px;\n}\n\n\n\n.resize-handle[_ngcontent-%COMP%] {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n background: transparent;\n transition: background 0.15s ease;\n z-index: 10;\n}\n\n.resize-handle[_ngcontent-%COMP%]:hover {\n background: rgba(92, 107, 192, 0.3);\n}\n\n.resize-handle[_ngcontent-%COMP%]:active {\n background: rgba(92, 107, 192, 0.5);\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n flex-shrink: 0;\n}\n\n.header-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.header-icon[_ngcontent-%COMP%] {\n font-size: 24px;\n opacity: 0.9;\n}\n\n.header-text[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.header-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n}\n\n.header-subtitle[_ngcontent-%COMP%] {\n font-size: 13px;\n opacity: 0.85;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n\n\n.info-section[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.info-section.expanded[_ngcontent-%COMP%] {\n border-color: #c5cae9;\n}\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #fafafa;\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n}\n\n.section-header[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n}\n\n.info-section.expanded[_ngcontent-%COMP%] .section-header[_ngcontent-%COMP%] {\n background: #e8eaf6;\n border-bottom: 1px solid #c5cae9;\n}\n\n.section-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #666;\n width: 12px;\n text-align: center;\n}\n\n.section-title[_ngcontent-%COMP%] {\n flex: 1;\n font-weight: 600;\n font-size: 14px;\n color: #333;\n}\n\n.section-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #888;\n font-weight: 400;\n}\n\n.section-content[_ngcontent-%COMP%] {\n padding: 16px;\n background: #fff;\n}\n\n\n\n.technical-description-content[_ngcontent-%COMP%] {\n max-height: 400px;\n overflow-y: auto;\n}\n\n.technical-description-content [_nghost-%COMP%] .mj-markdown-container {\n font-size: 13px;\n line-height: 1.5;\n}\n\n\n\n.info-row[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.info-row[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.info-label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: #888;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-value[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n line-height: 1.4;\n}\n\n.info-value.description[_ngcontent-%COMP%] {\n color: #555;\n font-style: italic;\n}\n\n.category-icon[_ngcontent-%COMP%] {\n color: #f9a825;\n margin-right: 4px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n background: #f5f5f5;\n color: #666;\n}\n\n.status-badge.approved[_ngcontent-%COMP%] {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.text-success[_ngcontent-%COMP%] {\n color: #2e7d32;\n}\n\n\n\n.fields-list[_ngcontent-%COMP%], \n.params-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.field-item[_ngcontent-%COMP%], \n.param-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 3px solid #5c6bc0;\n}\n\n.field-header[_ngcontent-%COMP%], \n.param-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 4px;\n}\n\n.field-name[_ngcontent-%COMP%], \n.param-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 13px;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.field-type[_ngcontent-%COMP%], \n.param-type[_ngcontent-%COMP%] {\n font-size: 11px;\n font-family: 'Consolas', 'Monaco', monospace;\n color: #666;\n background: #e8eaf6;\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.field-details[_ngcontent-%COMP%], \n.param-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 6px;\n}\n\n.field-description[_ngcontent-%COMP%], \n.param-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n font-style: italic;\n}\n\n.field-source[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #5c6bc0;\n}\n\n.field-source[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 4px;\n}\n\n.required-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n background: #ffebee;\n color: #c62828;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.param-default[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #888;\n}\n\n\n\n.sql-container[_ngcontent-%COMP%] {\n border-radius: 6px;\n overflow: hidden;\n}\n\n.sql-container[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n max-height: 400px;\n overflow: auto;\n}\n\n\n\n.empty-section[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: #888;\n font-style: italic;\n}\n\n.empty-section[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n opacity: 0.6;\n}\n\n\n\n.panel-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n gap: 12px;\n padding: 16px 20px;\n background: #f5f5f5;\n border-top: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover {\n background: linear-gradient(135deg, #7986cb 0%, #5c6bc0 100%);\n box-shadow: 0 2px 8px rgba(92, 107, 192, 0.4);\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: #fff;\n color: #333;\n border: 1px solid #ddd;\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover {\n background: #f5f5f5;\n border-color: #ccc;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 6px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background: #f5f5f5;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background: #ccc;\n border-radius: 3px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n}\n\n\n\n.dependents-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.dependent-item[_ngcontent-%COMP%] {\n padding: 10px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 3px solid #ef6c00;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.dependent-item[_ngcontent-%COMP%]:hover {\n background: #fff3e0;\n border-left-color: #e65100;\n}\n\n.dependent-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dependent-icon[_ngcontent-%COMP%] {\n color: #ef6c00;\n font-size: 11px;\n}\n\n.dependent-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 500;\n color: #333;\n}\n\n.dependent-ref-path[_ngcontent-%COMP%] {\n display: block;\n margin-top: 4px;\n margin-left: 19px;\n font-size: 11px;\n color: #888;\n}\n\n.dependents-hint[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 0 0;\n font-size: 11px;\n color: #999;\n}\n\n.dependents-hint[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}"], data: { animation: [
550
637
  trigger('slideIn', [
551
638
  transition(':enter', [
552
639
  style({ transform: 'translateX(100%)' }),
@@ -588,7 +675,7 @@ export class QueryInfoPanelComponent {
588
675
  animate('150ms ease-in', style({ opacity: 0 }))
589
676
  ])
590
677
  ])
591
- ], template: "<!-- Query Info Panel - Slide-in Panel -->\n@if (Visible && ShowOverlay) {\n <div class=\"info-panel-overlay\"\n @fadeIn\n (click)=\"OnClose()\">\n </div>\n}\n\n@if (Visible) {\n <div class=\"info-panel\"\n @slideIn\n [style.width.px]=\"PanelWidth\">\n <!-- Resize handle -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\"></div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <i class=\"fa-solid fa-circle-info header-icon\"></i>\n <div class=\"header-text\">\n <h3 class=\"header-title\">Query Information</h3>\n @if (QueryInfo) {\n <span class=\"header-subtitle\">{{ QueryInfo.Name }}</span>\n }\n </div>\n </div>\n <button class=\"close-btn\" (click)=\"OnClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Content -->\n @if (QueryInfo) {\n <div class=\"panel-content\">\n <!-- Overview Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('overview')\">\n <div class=\"section-header\" (click)=\"ToggleSection('overview')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('overview')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('overview')\"></i>\n <span class=\"section-title\">Overview</span>\n </div>\n @if (IsSectionExpanded('overview')) {\n <div class=\"section-content\">\n <div class=\"info-row\">\n <span class=\"info-label\">Name</span>\n <span class=\"info-value\">{{ QueryInfo.Name }}</span>\n </div>\n @if (QueryInfo.Description) {\n <div class=\"info-row\">\n <span class=\"info-label\">Description</span>\n <span class=\"info-value description\">{{ QueryInfo.Description }}</span>\n </div>\n }\n @if (QueryInfo.Category) {\n <div class=\"info-row\">\n <span class=\"info-label\">Category</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-folder category-icon\"></i>\n {{ QueryInfo.Category }}\n </span>\n </div>\n }\n <div class=\"info-row\">\n <span class=\"info-label\">Status</span>\n <span class=\"info-value\">\n <span class=\"status-badge\" [class.approved]=\"QueryInfo.Status === 'Approved'\">\n {{ QueryInfo.Status }}\n </span>\n </span>\n </div>\n @if (QueryInfo.OriginalSQL) {\n <div class=\"info-row\">\n <span class=\"info-label\">Has SQL</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-check text-success\"></i> Yes\n </span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Technical Description Section -->\n @if (QueryInfo.TechnicalDescription) {\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('technical')\">\n <div class=\"section-header\" (click)=\"ToggleSection('technical')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('technical')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('technical')\"></i>\n <span class=\"section-title\">Technical Description</span>\n </div>\n @if (IsSectionExpanded('technical')) {\n <div class=\"section-content technical-description-content\">\n <mj-markdown\n [data]=\"QueryInfo.TechnicalDescription || ''\"\n [enableMermaid]=\"true\"\n [enableHighlight]=\"true\"\n [enableCollapsibleHeadings]=\"false\"\n [enableSmartypants]=\"true\">\n </mj-markdown>\n </div>\n }\n </div>\n }\n <!-- Fields Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('fields')\">\n <div class=\"section-header\" (click)=\"ToggleSection('fields')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('fields')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('fields')\"></i>\n <span class=\"section-title\">Fields</span>\n <span class=\"section-count\">({{ QueryInfo.Fields.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('fields')) {\n <div class=\"section-content\">\n @if (QueryInfo.Fields.length) {\n <div class=\"fields-list\">\n @for (field of QueryInfo.Fields; track TrackByField($index, field)) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.Name }}</span>\n <span class=\"field-type\">{{ GetFieldTypeDisplay(field) }}</span>\n </div>\n @if (field.Description || field.SourceEntity) {\n <div class=\"field-details\">\n @if (field.Description) {\n <span class=\"field-description\">\n {{ field.Description }}\n </span>\n }\n @if (field.SourceEntity) {\n <span class=\"field-source\">\n <i class=\"fa-solid fa-link\"></i>\n {{ field.SourceEntity }}.{{ field.SourceFieldName }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-table-columns\"></i>\n <span>No fields defined</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Parameters Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('parameters')\">\n <div class=\"section-header\" (click)=\"ToggleSection('parameters')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('parameters')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('parameters')\"></i>\n <span class=\"section-title\">Parameters</span>\n <span class=\"section-count\">({{ QueryInfo.Parameters.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('parameters')) {\n <div class=\"section-content\">\n @if (QueryInfo.Parameters.length) {\n <div class=\"params-list\">\n @for (param of QueryInfo.Parameters; track TrackByParam($index, param)) {\n <div class=\"param-item\">\n <div class=\"param-header\">\n <span class=\"param-name\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n </span>\n <span class=\"param-type\">{{ GetParamTypeDisplay(param) }}</span>\n </div>\n @if (param.Description || param.DefaultValue) {\n <div class=\"param-details\">\n @if (param.Description) {\n <span class=\"param-description\">\n {{ param.Description }}\n </span>\n }\n @if (param.DefaultValue) {\n <span class=\"param-default\">\n Default: {{ param.DefaultValue }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-sliders\"></i>\n <span>No parameters required</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- SQL Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('sql')\">\n <div class=\"section-header\" (click)=\"ToggleSection('sql')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('sql')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('sql')\"></i>\n <span class=\"section-title\">SQL Query</span>\n </div>\n @if (IsSectionExpanded('sql')) {\n <div class=\"section-content\">\n @if (QueryInfo.SQL) {\n <div class=\"sql-container\">\n <pre class=\"sql-code\">{{ QueryInfo.SQL }}</pre>\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-code\"></i>\n <span>SQL not available</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"btn btn-primary\" (click)=\"OnOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n <button class=\"btn btn-secondary\" (click)=\"OnClose()\">\n Close\n </button>\n </div>\n </div>\n}\n", styles: ["/* Query Info Panel Styles */\n\n/* Overlay */\n.info-panel-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n}\n\n/* Panel Container */\n.info-panel {\n position: absolute;\n top: 0;\n right: 0;\n height: 100%;\n background: #fff;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n min-width: 350px;\n max-width: 800px;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n background: transparent;\n transition: background 0.15s ease;\n z-index: 10;\n}\n\n.resize-handle:hover {\n background: rgba(92, 107, 192, 0.3);\n}\n\n.resize-handle:active {\n background: rgba(92, 107, 192, 0.5);\n}\n\n/* Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n flex-shrink: 0;\n}\n\n.header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.header-icon {\n font-size: 24px;\n opacity: 0.9;\n}\n\n.header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.header-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n}\n\n.header-subtitle {\n font-size: 13px;\n opacity: 0.85;\n}\n\n.close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.close-btn:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n/* Sections */\n.info-section {\n margin-bottom: 8px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.info-section.expanded {\n border-color: #c5cae9;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #fafafa;\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n}\n\n.section-header:hover {\n background: #f0f0f0;\n}\n\n.info-section.expanded .section-header {\n background: #e8eaf6;\n border-bottom: 1px solid #c5cae9;\n}\n\n.section-icon {\n font-size: 10px;\n color: #666;\n width: 12px;\n text-align: center;\n}\n\n.section-title {\n flex: 1;\n font-weight: 600;\n font-size: 14px;\n color: #333;\n}\n\n.section-count {\n font-size: 12px;\n color: #888;\n font-weight: 400;\n}\n\n.section-content {\n padding: 16px;\n background: #fff;\n}\n\n/* Technical Description Markdown */\n.technical-description-content {\n max-height: 400px;\n overflow-y: auto;\n}\n\n.technical-description-content :host ::ng-deep .mj-markdown-container {\n font-size: 13px;\n line-height: 1.5;\n}\n\n/* Info Rows */\n.info-row {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.info-row:last-child {\n border-bottom: none;\n}\n\n.info-label {\n font-size: 11px;\n font-weight: 600;\n color: #888;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-value {\n font-size: 14px;\n color: #333;\n line-height: 1.4;\n}\n\n.info-value.description {\n color: #555;\n font-style: italic;\n}\n\n.category-icon {\n color: #f9a825;\n margin-right: 4px;\n}\n\n.status-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n background: #f5f5f5;\n color: #666;\n}\n\n.status-badge.approved {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.text-success {\n color: #2e7d32;\n}\n\n/* Fields List */\n.fields-list,\n.params-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.field-item,\n.param-item {\n padding: 10px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 3px solid #5c6bc0;\n}\n\n.field-header,\n.param-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 4px;\n}\n\n.field-name,\n.param-name {\n font-weight: 600;\n font-size: 13px;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.field-type,\n.param-type {\n font-size: 11px;\n font-family: 'Consolas', 'Monaco', monospace;\n color: #666;\n background: #e8eaf6;\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.field-details,\n.param-details {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 6px;\n}\n\n.field-description,\n.param-description {\n font-size: 12px;\n color: #666;\n font-style: italic;\n}\n\n.field-source {\n font-size: 11px;\n color: #5c6bc0;\n}\n\n.field-source i {\n margin-right: 4px;\n}\n\n.required-badge {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n background: #ffebee;\n color: #c62828;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.param-default {\n font-size: 11px;\n color: #888;\n}\n\n/* SQL Section */\n.sql-container {\n background: #1e1e1e;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.sql-code {\n margin: 0;\n padding: 16px;\n font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #d4d4d4;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-x: auto;\n}\n\n/* Empty State */\n.empty-section {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: #888;\n font-style: italic;\n}\n\n.empty-section i {\n font-size: 16px;\n opacity: 0.6;\n}\n\n/* Footer */\n.panel-footer {\n display: flex;\n justify-content: flex-start;\n gap: 12px;\n padding: 16px 20px;\n background: #f5f5f5;\n border-top: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-primary {\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n}\n\n.btn-primary:hover {\n background: linear-gradient(135deg, #7986cb 0%, #5c6bc0 100%);\n box-shadow: 0 2px 8px rgba(92, 107, 192, 0.4);\n}\n\n.btn-secondary {\n background: #fff;\n color: #333;\n border: 1px solid #ddd;\n}\n\n.btn-secondary:hover {\n background: #f5f5f5;\n border-color: #ccc;\n}\n\n/* Scrollbar */\n.panel-content::-webkit-scrollbar {\n width: 6px;\n}\n\n.panel-content::-webkit-scrollbar-track {\n background: #f5f5f5;\n}\n\n.panel-content::-webkit-scrollbar-thumb {\n background: #ccc;\n border-radius: 3px;\n}\n\n.panel-content::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n}\n"] }]
678
+ ], template: "<!-- Query Info Panel - Slide-in Panel -->\n@if (Visible && ShowOverlay) {\n <div class=\"info-panel-overlay\"\n @fadeIn\n (click)=\"OnClose()\">\n </div>\n}\n\n@if (Visible) {\n <div class=\"info-panel\"\n @slideIn\n [style.width.px]=\"PanelWidth\">\n <!-- Resize handle -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\"></div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <i class=\"fa-solid fa-circle-info header-icon\"></i>\n <div class=\"header-text\">\n <h3 class=\"header-title\">Query Information</h3>\n @if (QueryInfo) {\n <span class=\"header-subtitle\">{{ QueryInfo.Name }}</span>\n }\n </div>\n </div>\n <button class=\"close-btn\" (click)=\"OnClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Content -->\n @if (QueryInfo) {\n <div class=\"panel-content\">\n <!-- Overview Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('overview')\">\n <div class=\"section-header\" (click)=\"ToggleSection('overview')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('overview')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('overview')\"></i>\n <span class=\"section-title\">Overview</span>\n </div>\n @if (IsSectionExpanded('overview')) {\n <div class=\"section-content\">\n <div class=\"info-row\">\n <span class=\"info-label\">Name</span>\n <span class=\"info-value\">{{ QueryInfo.Name }}</span>\n </div>\n @if (QueryInfo.Description) {\n <div class=\"info-row\">\n <span class=\"info-label\">Description</span>\n <span class=\"info-value description\">{{ QueryInfo.Description }}</span>\n </div>\n }\n @if (QueryInfo.Category) {\n <div class=\"info-row\">\n <span class=\"info-label\">Category</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-folder category-icon\"></i>\n {{ QueryInfo.Category }}\n </span>\n </div>\n }\n <div class=\"info-row\">\n <span class=\"info-label\">Status</span>\n <span class=\"info-value\">\n <span class=\"status-badge\" [class.approved]=\"QueryInfo.Status === 'Approved'\">\n {{ QueryInfo.Status }}\n </span>\n </span>\n </div>\n @if (QueryInfo.OriginalSQL) {\n <div class=\"info-row\">\n <span class=\"info-label\">Has SQL</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-check text-success\"></i> Yes\n </span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Technical Description Section -->\n @if (QueryInfo.TechnicalDescription) {\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('technical')\">\n <div class=\"section-header\" (click)=\"ToggleSection('technical')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('technical')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('technical')\"></i>\n <span class=\"section-title\">Technical Description</span>\n </div>\n @if (IsSectionExpanded('technical')) {\n <div class=\"section-content technical-description-content\">\n <mj-markdown\n [data]=\"QueryInfo.TechnicalDescription || ''\"\n [enableMermaid]=\"true\"\n [enableHighlight]=\"true\"\n [enableCollapsibleHeadings]=\"false\"\n [enableSmartypants]=\"true\">\n </mj-markdown>\n </div>\n }\n </div>\n }\n <!-- Fields Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('fields')\">\n <div class=\"section-header\" (click)=\"ToggleSection('fields')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('fields')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('fields')\"></i>\n <span class=\"section-title\">Fields</span>\n <span class=\"section-count\">({{ QueryInfo.Fields.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('fields')) {\n <div class=\"section-content\">\n @if (QueryInfo.Fields.length) {\n <div class=\"fields-list\">\n @for (field of QueryInfo.Fields; track TrackByField($index, field)) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.Name }}</span>\n <span class=\"field-type\">{{ GetFieldTypeDisplay(field) }}</span>\n </div>\n @if (field.Description || field.SourceEntity) {\n <div class=\"field-details\">\n @if (field.Description) {\n <span class=\"field-description\">\n {{ field.Description }}\n </span>\n }\n @if (field.SourceEntity) {\n <span class=\"field-source\">\n <i class=\"fa-solid fa-link\"></i>\n {{ field.SourceEntity }}.{{ field.SourceFieldName }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-table-columns\"></i>\n <span>No fields defined</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Parameters Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('parameters')\">\n <div class=\"section-header\" (click)=\"ToggleSection('parameters')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('parameters')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('parameters')\"></i>\n <span class=\"section-title\">Parameters</span>\n <span class=\"section-count\">({{ QueryInfo.Parameters.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('parameters')) {\n <div class=\"section-content\">\n @if (QueryInfo.Parameters.length) {\n <div class=\"params-list\">\n @for (param of QueryInfo.Parameters; track TrackByParam($index, param)) {\n <div class=\"param-item\">\n <div class=\"param-header\">\n <span class=\"param-name\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n </span>\n <span class=\"param-type\">{{ GetParamTypeDisplay(param) }}</span>\n </div>\n @if (param.Description || param.DefaultValue) {\n <div class=\"param-details\">\n @if (param.Description) {\n <span class=\"param-description\">\n {{ param.Description }}\n </span>\n }\n @if (param.DefaultValue) {\n <span class=\"param-default\">\n Default: {{ param.DefaultValue }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-sliders\"></i>\n <span>No parameters required</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- SQL Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('sql')\">\n <div class=\"section-header\" (click)=\"ToggleSection('sql')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('sql')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('sql')\"></i>\n <span class=\"section-title\">SQL Query</span>\n </div>\n @if (IsSectionExpanded('sql')) {\n <div class=\"section-content\">\n @if (QueryInfo.SQL) {\n <div class=\"sql-container\">\n <mj-code-editor\n [value]=\"QueryInfo.SQL\"\n [readonly]=\"true\"\n [language]=\"'sql'\"\n (CompositionTokenClick)=\"OnCompositionTokenClick($event)\">\n </mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-code\"></i>\n <span>SQL not available</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Dependent Queries Section -->\n @if (QueryInfo.Dependents.length > 0) {\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('dependents')\">\n <div class=\"section-header\" (click)=\"ToggleSection('dependents')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('dependents')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('dependents')\"></i>\n <span class=\"section-title\">Dependent Queries</span>\n <span class=\"section-count\">({{ QueryInfo.Dependents.length }})</span>\n </div>\n @if (IsSectionExpanded('dependents')) {\n <div class=\"section-content\">\n <div class=\"dependents-list\">\n @for (dep of QueryInfo.Dependents; track dep.ID) {\n <div class=\"dependent-item\" (click)=\"OnDependentQueryClick(dep)\">\n <div class=\"dependent-header\">\n <i class=\"fa-solid fa-arrow-left dependent-icon\"></i>\n <span class=\"dependent-name\">{{ dep.Query }}</span>\n </div>\n @if (dep.ReferencePath) {\n <span class=\"dependent-ref-path\">\n via {{ dep.ReferencePath }}\n </span>\n }\n </div>\n }\n </div>\n <div class=\"dependents-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n These queries reference this query via composition\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"btn btn-primary\" (click)=\"OnOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n <button class=\"btn btn-secondary\" (click)=\"OnClose()\">\n Close\n </button>\n </div>\n </div>\n}\n", styles: ["/* Query Info Panel Styles */\n\n/* Overlay */\n.info-panel-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 999;\n}\n\n/* Panel Container */\n.info-panel {\n position: absolute;\n top: 0;\n right: 0;\n height: 100%;\n background: #fff;\n box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n min-width: 350px;\n max-width: 800px;\n}\n\n/* Resize Handle */\n.resize-handle {\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 6px;\n cursor: ew-resize;\n background: transparent;\n transition: background 0.15s ease;\n z-index: 10;\n}\n\n.resize-handle:hover {\n background: rgba(92, 107, 192, 0.3);\n}\n\n.resize-handle:active {\n background: rgba(92, 107, 192, 0.5);\n}\n\n/* Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n flex-shrink: 0;\n}\n\n.header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.header-icon {\n font-size: 24px;\n opacity: 0.9;\n}\n\n.header-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.header-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n}\n\n.header-subtitle {\n font-size: 13px;\n opacity: 0.85;\n}\n\n.close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: rgba(255, 255, 255, 0.15);\n color: #fff;\n border-radius: 6px;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.close-btn:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n/* Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n}\n\n/* Sections */\n.info-section {\n margin-bottom: 8px;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.info-section.expanded {\n border-color: #c5cae9;\n}\n\n.section-header {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px 16px;\n background: #fafafa;\n cursor: pointer;\n transition: background 0.15s ease;\n user-select: none;\n}\n\n.section-header:hover {\n background: #f0f0f0;\n}\n\n.info-section.expanded .section-header {\n background: #e8eaf6;\n border-bottom: 1px solid #c5cae9;\n}\n\n.section-icon {\n font-size: 10px;\n color: #666;\n width: 12px;\n text-align: center;\n}\n\n.section-title {\n flex: 1;\n font-weight: 600;\n font-size: 14px;\n color: #333;\n}\n\n.section-count {\n font-size: 12px;\n color: #888;\n font-weight: 400;\n}\n\n.section-content {\n padding: 16px;\n background: #fff;\n}\n\n/* Technical Description Markdown */\n.technical-description-content {\n max-height: 400px;\n overflow-y: auto;\n}\n\n.technical-description-content :host ::ng-deep .mj-markdown-container {\n font-size: 13px;\n line-height: 1.5;\n}\n\n/* Info Rows */\n.info-row {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.info-row:last-child {\n border-bottom: none;\n}\n\n.info-label {\n font-size: 11px;\n font-weight: 600;\n color: #888;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.info-value {\n font-size: 14px;\n color: #333;\n line-height: 1.4;\n}\n\n.info-value.description {\n color: #555;\n font-style: italic;\n}\n\n.category-icon {\n color: #f9a825;\n margin-right: 4px;\n}\n\n.status-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n background: #f5f5f5;\n color: #666;\n}\n\n.status-badge.approved {\n background: #e8f5e9;\n color: #2e7d32;\n}\n\n.text-success {\n color: #2e7d32;\n}\n\n/* Fields List */\n.fields-list,\n.params-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.field-item,\n.param-item {\n padding: 10px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 3px solid #5c6bc0;\n}\n\n.field-header,\n.param-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 4px;\n}\n\n.field-name,\n.param-name {\n font-weight: 600;\n font-size: 13px;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.field-type,\n.param-type {\n font-size: 11px;\n font-family: 'Consolas', 'Monaco', monospace;\n color: #666;\n background: #e8eaf6;\n padding: 2px 6px;\n border-radius: 4px;\n}\n\n.field-details,\n.param-details {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 6px;\n}\n\n.field-description,\n.param-description {\n font-size: 12px;\n color: #666;\n font-style: italic;\n}\n\n.field-source {\n font-size: 11px;\n color: #5c6bc0;\n}\n\n.field-source i {\n margin-right: 4px;\n}\n\n.required-badge {\n font-size: 10px;\n font-weight: 500;\n padding: 2px 6px;\n background: #ffebee;\n color: #c62828;\n border-radius: 4px;\n text-transform: uppercase;\n}\n\n.param-default {\n font-size: 11px;\n color: #888;\n}\n\n/* SQL Section */\n.sql-container {\n border-radius: 6px;\n overflow: hidden;\n}\n\n.sql-container mj-code-editor {\n display: block;\n max-height: 400px;\n overflow: auto;\n}\n\n/* Empty State */\n.empty-section {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 16px;\n color: #888;\n font-style: italic;\n}\n\n.empty-section i {\n font-size: 16px;\n opacity: 0.6;\n}\n\n/* Footer */\n.panel-footer {\n display: flex;\n justify-content: flex-start;\n gap: 12px;\n padding: 16px 20px;\n background: #f5f5f5;\n border-top: 1px solid #e0e0e0;\n flex-shrink: 0;\n}\n\n.btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.btn-primary {\n background: linear-gradient(135deg, #5c6bc0 0%, #3949ab 100%);\n color: #fff;\n}\n\n.btn-primary:hover {\n background: linear-gradient(135deg, #7986cb 0%, #5c6bc0 100%);\n box-shadow: 0 2px 8px rgba(92, 107, 192, 0.4);\n}\n\n.btn-secondary {\n background: #fff;\n color: #333;\n border: 1px solid #ddd;\n}\n\n.btn-secondary:hover {\n background: #f5f5f5;\n border-color: #ccc;\n}\n\n/* Scrollbar */\n.panel-content::-webkit-scrollbar {\n width: 6px;\n}\n\n.panel-content::-webkit-scrollbar-track {\n background: #f5f5f5;\n}\n\n.panel-content::-webkit-scrollbar-thumb {\n background: #ccc;\n border-radius: 3px;\n}\n\n.panel-content::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n}\n\n/* Dependent Queries */\n.dependents-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.dependent-item {\n padding: 10px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border-left: 3px solid #ef6c00;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.dependent-item:hover {\n background: #fff3e0;\n border-left-color: #e65100;\n}\n\n.dependent-header {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dependent-icon {\n color: #ef6c00;\n font-size: 11px;\n}\n\n.dependent-name {\n font-size: 13px;\n font-weight: 500;\n color: #333;\n}\n\n.dependent-ref-path {\n display: block;\n margin-top: 4px;\n margin-left: 19px;\n font-size: 11px;\n color: #888;\n}\n\n.dependents-hint {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 0 0;\n font-size: 11px;\n color: #999;\n}\n\n.dependents-hint i {\n font-size: 10px;\n}\n"] }]
592
679
  }], () => [{ type: i0.ChangeDetectorRef }], { QueryInfo: [{
593
680
  type: Input
594
681
  }], Visible: [{
@@ -599,6 +686,8 @@ export class QueryInfoPanelComponent {
599
686
  type: Output
600
687
  }], OpenRecord: [{
601
688
  type: Output
689
+ }], CompositionTokenClick: [{
690
+ type: Output
602
691
  }], OnMouseMove: [{
603
692
  type: HostListener,
604
693
  args: ['document:mousemove', ['$event']]
@@ -606,5 +695,5 @@ export class QueryInfoPanelComponent {
606
695
  type: HostListener,
607
696
  args: ['document:mouseup']
608
697
  }] }); })();
609
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryInfoPanelComponent, { className: "QueryInfoPanelComponent", filePath: "src/lib/query-info-panel/query-info-panel.component.ts", lineNumber: 65 }); })();
698
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryInfoPanelComponent, { className: "QueryInfoPanelComponent", filePath: "src/lib/query-info-panel/query-info-panel.component.ts", lineNumber: 66 }); })();
610
699
  //# sourceMappingURL=query-info-panel.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-info-panel.component.js","sourceRoot":"","sources":["../../../src/lib/query-info-panel/query-info-panel.component.ts","../../../src/lib/query-info-panel/query-info-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n OnInit,\n OnDestroy,\n HostListener\n} from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { QueryInfo, QueryFieldInfo, QueryParameterInfo } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\n\n/**\n * User Settings key for info panel width\n */\nconst INFO_PANEL_WIDTH_KEY = 'QueryViewer_InfoPanelWidth';\n\n/**\n * Event emitted when opening the full query record\n */\nexport interface OpenQueryRecordEvent {\n queryId: string;\n queryName: string;\n}\n\n/**\n * A slide-in panel that displays detailed query information.\n * Features:\n * - Expandable sections for fields, parameters, and SQL\n * - Resizable width with persistence\n * - Open button to navigate to full record\n */\n@Component({\n standalone: false,\n selector: 'mj-query-info-panel',\n templateUrl: './query-info-panel.component.html',\n styleUrls: ['./query-info-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [\n trigger('slideIn', [\n transition(':enter', [\n style({ transform: 'translateX(100%)' }),\n animate('250ms ease-out', style({ transform: 'translateX(0)' }))\n ]),\n transition(':leave', [\n animate('200ms ease-in', style({ transform: 'translateX(100%)' }))\n ])\n ]),\n trigger('fadeIn', [\n transition(':enter', [\n style({ opacity: 0 }),\n animate('200ms ease-out', style({ opacity: 1 }))\n ]),\n transition(':leave', [\n animate('150ms ease-in', style({ opacity: 0 }))\n ])\n ])\n ]\n})\nexport class QueryInfoPanelComponent implements OnInit, OnDestroy {\n // ========================================\n // Inputs\n // ========================================\n\n @Input() QueryInfo: QueryInfo | null = null;\n @Input() Visible: boolean = false;\n @Input() ShowOverlay: boolean = true;\n\n // ========================================\n // Outputs\n // ========================================\n\n @Output() Close = new EventEmitter<void>();\n @Output() OpenRecord = new EventEmitter<OpenQueryRecordEvent>();\n\n // ========================================\n // Internal State\n // ========================================\n\n public PanelWidth: number = 450;\n public ExpandedSections: Set<string> = new Set(['overview', 'fields']);\n\n private isResizing: boolean = false;\n private destroy$ = new Subject<void>();\n private widthPersistSubject = new Subject<number>();\n\n constructor(private cdr: ChangeDetectorRef) {\n // Debounce width persistence\n this.widthPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(width => {\n this.persistPanelWidth(width);\n });\n }\n\n ngOnInit(): void {\n this.loadPanelWidth();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ========================================\n // Section Toggle\n // ========================================\n\n public ToggleSection(section: string): void {\n if (this.ExpandedSections.has(section)) {\n this.ExpandedSections.delete(section);\n } else {\n this.ExpandedSections.add(section);\n }\n this.cdr.markForCheck();\n }\n\n public IsSectionExpanded(section: string): boolean {\n return this.ExpandedSections.has(section);\n }\n\n // ========================================\n // Panel Actions\n // ========================================\n\n public OnClose(): void {\n this.Close.emit();\n }\n\n public OnOpenRecord(): void {\n if (this.QueryInfo) {\n this.OpenRecord.emit({\n queryId: this.QueryInfo.ID,\n queryName: this.QueryInfo.Name\n });\n }\n }\n\n // ========================================\n // Resize Handling\n // ========================================\n\n public OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.isResizing = true;\n }\n\n @HostListener('document:mousemove', ['$event'])\n OnMouseMove(event: MouseEvent): void {\n if (!this.isResizing) return;\n\n const newWidth = window.innerWidth - event.clientX;\n this.PanelWidth = Math.min(Math.max(newWidth, 350), 800);\n this.widthPersistSubject.next(this.PanelWidth);\n this.cdr.markForCheck();\n }\n\n @HostListener('document:mouseup')\n OnMouseUp(): void {\n this.isResizing = false;\n }\n\n // ========================================\n // Width Persistence\n // ========================================\n\n private loadPanelWidth(): void {\n try {\n const saved = UserInfoEngine.Instance.GetSetting(INFO_PANEL_WIDTH_KEY);\n if (saved) {\n this.PanelWidth = parseInt(saved, 10) || 450;\n }\n } catch (error) {\n console.warn('[query-info-panel] Failed to load panel width:', error);\n }\n }\n\n private async persistPanelWidth(width: number): Promise<void> {\n try {\n await UserInfoEngine.Instance.SetSetting(INFO_PANEL_WIDTH_KEY, String(width));\n } catch (error) {\n console.warn('[query-info-panel] Failed to persist panel width:', error);\n }\n }\n\n // ========================================\n // Helpers\n // ========================================\n\n public GetFieldTypeDisplay(field: QueryFieldInfo): string {\n return field.SQLFullType || field.SQLBaseType || 'unknown';\n }\n\n public GetParamTypeDisplay(param: QueryParameterInfo): string {\n return param.Type || 'string';\n }\n\n public TrackByField(index: number, field: QueryFieldInfo): string {\n return field.Name;\n }\n\n public TrackByParam(index: number, param: QueryParameterInfo): string {\n return param.Name;\n }\n}\n","<!-- Query Info Panel - Slide-in Panel -->\n@if (Visible && ShowOverlay) {\n <div class=\"info-panel-overlay\"\n @fadeIn\n (click)=\"OnClose()\">\n </div>\n}\n\n@if (Visible) {\n <div class=\"info-panel\"\n @slideIn\n [style.width.px]=\"PanelWidth\">\n <!-- Resize handle -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\"></div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <i class=\"fa-solid fa-circle-info header-icon\"></i>\n <div class=\"header-text\">\n <h3 class=\"header-title\">Query Information</h3>\n @if (QueryInfo) {\n <span class=\"header-subtitle\">{{ QueryInfo.Name }}</span>\n }\n </div>\n </div>\n <button class=\"close-btn\" (click)=\"OnClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Content -->\n @if (QueryInfo) {\n <div class=\"panel-content\">\n <!-- Overview Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('overview')\">\n <div class=\"section-header\" (click)=\"ToggleSection('overview')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('overview')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('overview')\"></i>\n <span class=\"section-title\">Overview</span>\n </div>\n @if (IsSectionExpanded('overview')) {\n <div class=\"section-content\">\n <div class=\"info-row\">\n <span class=\"info-label\">Name</span>\n <span class=\"info-value\">{{ QueryInfo.Name }}</span>\n </div>\n @if (QueryInfo.Description) {\n <div class=\"info-row\">\n <span class=\"info-label\">Description</span>\n <span class=\"info-value description\">{{ QueryInfo.Description }}</span>\n </div>\n }\n @if (QueryInfo.Category) {\n <div class=\"info-row\">\n <span class=\"info-label\">Category</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-folder category-icon\"></i>\n {{ QueryInfo.Category }}\n </span>\n </div>\n }\n <div class=\"info-row\">\n <span class=\"info-label\">Status</span>\n <span class=\"info-value\">\n <span class=\"status-badge\" [class.approved]=\"QueryInfo.Status === 'Approved'\">\n {{ QueryInfo.Status }}\n </span>\n </span>\n </div>\n @if (QueryInfo.OriginalSQL) {\n <div class=\"info-row\">\n <span class=\"info-label\">Has SQL</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-check text-success\"></i> Yes\n </span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Technical Description Section -->\n @if (QueryInfo.TechnicalDescription) {\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('technical')\">\n <div class=\"section-header\" (click)=\"ToggleSection('technical')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('technical')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('technical')\"></i>\n <span class=\"section-title\">Technical Description</span>\n </div>\n @if (IsSectionExpanded('technical')) {\n <div class=\"section-content technical-description-content\">\n <mj-markdown\n [data]=\"QueryInfo.TechnicalDescription || ''\"\n [enableMermaid]=\"true\"\n [enableHighlight]=\"true\"\n [enableCollapsibleHeadings]=\"false\"\n [enableSmartypants]=\"true\">\n </mj-markdown>\n </div>\n }\n </div>\n }\n <!-- Fields Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('fields')\">\n <div class=\"section-header\" (click)=\"ToggleSection('fields')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('fields')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('fields')\"></i>\n <span class=\"section-title\">Fields</span>\n <span class=\"section-count\">({{ QueryInfo.Fields.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('fields')) {\n <div class=\"section-content\">\n @if (QueryInfo.Fields.length) {\n <div class=\"fields-list\">\n @for (field of QueryInfo.Fields; track TrackByField($index, field)) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.Name }}</span>\n <span class=\"field-type\">{{ GetFieldTypeDisplay(field) }}</span>\n </div>\n @if (field.Description || field.SourceEntity) {\n <div class=\"field-details\">\n @if (field.Description) {\n <span class=\"field-description\">\n {{ field.Description }}\n </span>\n }\n @if (field.SourceEntity) {\n <span class=\"field-source\">\n <i class=\"fa-solid fa-link\"></i>\n {{ field.SourceEntity }}.{{ field.SourceFieldName }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-table-columns\"></i>\n <span>No fields defined</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Parameters Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('parameters')\">\n <div class=\"section-header\" (click)=\"ToggleSection('parameters')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('parameters')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('parameters')\"></i>\n <span class=\"section-title\">Parameters</span>\n <span class=\"section-count\">({{ QueryInfo.Parameters.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('parameters')) {\n <div class=\"section-content\">\n @if (QueryInfo.Parameters.length) {\n <div class=\"params-list\">\n @for (param of QueryInfo.Parameters; track TrackByParam($index, param)) {\n <div class=\"param-item\">\n <div class=\"param-header\">\n <span class=\"param-name\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n </span>\n <span class=\"param-type\">{{ GetParamTypeDisplay(param) }}</span>\n </div>\n @if (param.Description || param.DefaultValue) {\n <div class=\"param-details\">\n @if (param.Description) {\n <span class=\"param-description\">\n {{ param.Description }}\n </span>\n }\n @if (param.DefaultValue) {\n <span class=\"param-default\">\n Default: {{ param.DefaultValue }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-sliders\"></i>\n <span>No parameters required</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- SQL Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('sql')\">\n <div class=\"section-header\" (click)=\"ToggleSection('sql')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('sql')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('sql')\"></i>\n <span class=\"section-title\">SQL Query</span>\n </div>\n @if (IsSectionExpanded('sql')) {\n <div class=\"section-content\">\n @if (QueryInfo.SQL) {\n <div class=\"sql-container\">\n <pre class=\"sql-code\">{{ QueryInfo.SQL }}</pre>\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-code\"></i>\n <span>SQL not available</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"btn btn-primary\" (click)=\"OnOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n <button class=\"btn btn-secondary\" (click)=\"OnClose()\">\n Close\n </button>\n </div>\n </div>\n}\n"]}
1
+ {"version":3,"file":"query-info-panel.component.js","sourceRoot":"","sources":["../../../src/lib/query-info-panel/query-info-panel.component.ts","../../../src/lib/query-info-panel/query-info-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n OnInit,\n OnDestroy,\n HostListener\n} from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { QueryInfo, QueryFieldInfo, QueryParameterInfo, QueryDependencyInfo } from '@memberjunction/core';\nimport { CompositionTokenClickEvent } from '@memberjunction/ng-code-editor';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\n\n/**\n * User Settings key for info panel width\n */\nconst INFO_PANEL_WIDTH_KEY = 'QueryViewer_InfoPanelWidth';\n\n/**\n * Event emitted when opening the full query record\n */\nexport interface OpenQueryRecordEvent {\n queryId: string;\n queryName: string;\n}\n\n/**\n * A slide-in panel that displays detailed query information.\n * Features:\n * - Expandable sections for fields, parameters, and SQL\n * - Resizable width with persistence\n * - Open button to navigate to full record\n */\n@Component({\n standalone: false,\n selector: 'mj-query-info-panel',\n templateUrl: './query-info-panel.component.html',\n styleUrls: ['./query-info-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [\n trigger('slideIn', [\n transition(':enter', [\n style({ transform: 'translateX(100%)' }),\n animate('250ms ease-out', style({ transform: 'translateX(0)' }))\n ]),\n transition(':leave', [\n animate('200ms ease-in', style({ transform: 'translateX(100%)' }))\n ])\n ]),\n trigger('fadeIn', [\n transition(':enter', [\n style({ opacity: 0 }),\n animate('200ms ease-out', style({ opacity: 1 }))\n ]),\n transition(':leave', [\n animate('150ms ease-in', style({ opacity: 0 }))\n ])\n ])\n ]\n})\nexport class QueryInfoPanelComponent implements OnInit, OnDestroy {\n // ========================================\n // Inputs\n // ========================================\n\n @Input() QueryInfo: QueryInfo | null = null;\n @Input() Visible: boolean = false;\n @Input() ShowOverlay: boolean = true;\n\n // ========================================\n // Outputs\n // ========================================\n\n @Output() Close = new EventEmitter<void>();\n @Output() OpenRecord = new EventEmitter<OpenQueryRecordEvent>();\n @Output() CompositionTokenClick = new EventEmitter<CompositionTokenClickEvent>();\n\n // ========================================\n // Internal State\n // ========================================\n\n public PanelWidth: number = 450;\n public ExpandedSections: Set<string> = new Set(['overview', 'fields']);\n\n private isResizing: boolean = false;\n private destroy$ = new Subject<void>();\n private widthPersistSubject = new Subject<number>();\n\n constructor(private cdr: ChangeDetectorRef) {\n // Debounce width persistence\n this.widthPersistSubject.pipe(\n debounceTime(500),\n takeUntil(this.destroy$)\n ).subscribe(width => {\n this.persistPanelWidth(width);\n });\n }\n\n ngOnInit(): void {\n this.loadPanelWidth();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ========================================\n // Section Toggle\n // ========================================\n\n public ToggleSection(section: string): void {\n if (this.ExpandedSections.has(section)) {\n this.ExpandedSections.delete(section);\n } else {\n this.ExpandedSections.add(section);\n }\n this.cdr.markForCheck();\n }\n\n public IsSectionExpanded(section: string): boolean {\n return this.ExpandedSections.has(section);\n }\n\n // ========================================\n // Panel Actions\n // ========================================\n\n public OnClose(): void {\n this.Close.emit();\n }\n\n public OnCompositionTokenClick(event: CompositionTokenClickEvent): void {\n this.CompositionTokenClick.emit(event);\n }\n\n public OnDependentQueryClick(dep: QueryDependencyInfo): void {\n // Navigate to the dependent (referencing) query\n const depQuery = dep.QueryInfo;\n const categoryPath = depQuery?.CategoryPath?.replace(/^\\/|\\/$/g, '') || '';\n const fullPath = categoryPath ? `${categoryPath}/${dep.Query}` : dep.Query;\n this.CompositionTokenClick.emit({\n FullToken: `{{query:\"${fullPath}\"}}`,\n QueryName: dep.Query,\n CategorySegments: categoryPath ? categoryPath.split('/') : [],\n FullPath: fullPath,\n MouseEvent: new MouseEvent('click')\n });\n }\n\n public OnOpenRecord(): void {\n if (this.QueryInfo) {\n this.OpenRecord.emit({\n queryId: this.QueryInfo.ID,\n queryName: this.QueryInfo.Name\n });\n }\n }\n\n // ========================================\n // Resize Handling\n // ========================================\n\n public OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.isResizing = true;\n }\n\n @HostListener('document:mousemove', ['$event'])\n OnMouseMove(event: MouseEvent): void {\n if (!this.isResizing) return;\n\n const newWidth = window.innerWidth - event.clientX;\n this.PanelWidth = Math.min(Math.max(newWidth, 350), 800);\n this.widthPersistSubject.next(this.PanelWidth);\n this.cdr.markForCheck();\n }\n\n @HostListener('document:mouseup')\n OnMouseUp(): void {\n this.isResizing = false;\n }\n\n // ========================================\n // Width Persistence\n // ========================================\n\n private loadPanelWidth(): void {\n try {\n const saved = UserInfoEngine.Instance.GetSetting(INFO_PANEL_WIDTH_KEY);\n if (saved) {\n this.PanelWidth = parseInt(saved, 10) || 450;\n }\n } catch (error) {\n console.warn('[query-info-panel] Failed to load panel width:', error);\n }\n }\n\n private async persistPanelWidth(width: number): Promise<void> {\n try {\n await UserInfoEngine.Instance.SetSetting(INFO_PANEL_WIDTH_KEY, String(width));\n } catch (error) {\n console.warn('[query-info-panel] Failed to persist panel width:', error);\n }\n }\n\n // ========================================\n // Helpers\n // ========================================\n\n public GetFieldTypeDisplay(field: QueryFieldInfo): string {\n return field.SQLFullType || field.SQLBaseType || 'unknown';\n }\n\n public GetParamTypeDisplay(param: QueryParameterInfo): string {\n return param.Type || 'string';\n }\n\n public TrackByField(index: number, field: QueryFieldInfo): string {\n return field.Name;\n }\n\n public TrackByParam(index: number, param: QueryParameterInfo): string {\n return param.Name;\n }\n}\n","<!-- Query Info Panel - Slide-in Panel -->\n@if (Visible && ShowOverlay) {\n <div class=\"info-panel-overlay\"\n @fadeIn\n (click)=\"OnClose()\">\n </div>\n}\n\n@if (Visible) {\n <div class=\"info-panel\"\n @slideIn\n [style.width.px]=\"PanelWidth\">\n <!-- Resize handle -->\n <div class=\"resize-handle\" (mousedown)=\"OnResizeStart($event)\"></div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-content\">\n <i class=\"fa-solid fa-circle-info header-icon\"></i>\n <div class=\"header-text\">\n <h3 class=\"header-title\">Query Information</h3>\n @if (QueryInfo) {\n <span class=\"header-subtitle\">{{ QueryInfo.Name }}</span>\n }\n </div>\n </div>\n <button class=\"close-btn\" (click)=\"OnClose()\" title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <!-- Content -->\n @if (QueryInfo) {\n <div class=\"panel-content\">\n <!-- Overview Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('overview')\">\n <div class=\"section-header\" (click)=\"ToggleSection('overview')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('overview')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('overview')\"></i>\n <span class=\"section-title\">Overview</span>\n </div>\n @if (IsSectionExpanded('overview')) {\n <div class=\"section-content\">\n <div class=\"info-row\">\n <span class=\"info-label\">Name</span>\n <span class=\"info-value\">{{ QueryInfo.Name }}</span>\n </div>\n @if (QueryInfo.Description) {\n <div class=\"info-row\">\n <span class=\"info-label\">Description</span>\n <span class=\"info-value description\">{{ QueryInfo.Description }}</span>\n </div>\n }\n @if (QueryInfo.Category) {\n <div class=\"info-row\">\n <span class=\"info-label\">Category</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-folder category-icon\"></i>\n {{ QueryInfo.Category }}\n </span>\n </div>\n }\n <div class=\"info-row\">\n <span class=\"info-label\">Status</span>\n <span class=\"info-value\">\n <span class=\"status-badge\" [class.approved]=\"QueryInfo.Status === 'Approved'\">\n {{ QueryInfo.Status }}\n </span>\n </span>\n </div>\n @if (QueryInfo.OriginalSQL) {\n <div class=\"info-row\">\n <span class=\"info-label\">Has SQL</span>\n <span class=\"info-value\">\n <i class=\"fa-solid fa-check text-success\"></i> Yes\n </span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Technical Description Section -->\n @if (QueryInfo.TechnicalDescription) {\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('technical')\">\n <div class=\"section-header\" (click)=\"ToggleSection('technical')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('technical')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('technical')\"></i>\n <span class=\"section-title\">Technical Description</span>\n </div>\n @if (IsSectionExpanded('technical')) {\n <div class=\"section-content technical-description-content\">\n <mj-markdown\n [data]=\"QueryInfo.TechnicalDescription || ''\"\n [enableMermaid]=\"true\"\n [enableHighlight]=\"true\"\n [enableCollapsibleHeadings]=\"false\"\n [enableSmartypants]=\"true\">\n </mj-markdown>\n </div>\n }\n </div>\n }\n <!-- Fields Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('fields')\">\n <div class=\"section-header\" (click)=\"ToggleSection('fields')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('fields')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('fields')\"></i>\n <span class=\"section-title\">Fields</span>\n <span class=\"section-count\">({{ QueryInfo.Fields.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('fields')) {\n <div class=\"section-content\">\n @if (QueryInfo.Fields.length) {\n <div class=\"fields-list\">\n @for (field of QueryInfo.Fields; track TrackByField($index, field)) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.Name }}</span>\n <span class=\"field-type\">{{ GetFieldTypeDisplay(field) }}</span>\n </div>\n @if (field.Description || field.SourceEntity) {\n <div class=\"field-details\">\n @if (field.Description) {\n <span class=\"field-description\">\n {{ field.Description }}\n </span>\n }\n @if (field.SourceEntity) {\n <span class=\"field-source\">\n <i class=\"fa-solid fa-link\"></i>\n {{ field.SourceEntity }}.{{ field.SourceFieldName }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-table-columns\"></i>\n <span>No fields defined</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Parameters Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('parameters')\">\n <div class=\"section-header\" (click)=\"ToggleSection('parameters')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('parameters')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('parameters')\"></i>\n <span class=\"section-title\">Parameters</span>\n <span class=\"section-count\">({{ QueryInfo.Parameters.length || 0 }})</span>\n </div>\n @if (IsSectionExpanded('parameters')) {\n <div class=\"section-content\">\n @if (QueryInfo.Parameters.length) {\n <div class=\"params-list\">\n @for (param of QueryInfo.Parameters; track TrackByParam($index, param)) {\n <div class=\"param-item\">\n <div class=\"param-header\">\n <span class=\"param-name\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span class=\"required-badge\">Required</span>\n }\n </span>\n <span class=\"param-type\">{{ GetParamTypeDisplay(param) }}</span>\n </div>\n @if (param.Description || param.DefaultValue) {\n <div class=\"param-details\">\n @if (param.Description) {\n <span class=\"param-description\">\n {{ param.Description }}\n </span>\n }\n @if (param.DefaultValue) {\n <span class=\"param-default\">\n Default: {{ param.DefaultValue }}\n </span>\n }\n </div>\n }\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-sliders\"></i>\n <span>No parameters required</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- SQL Section -->\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('sql')\">\n <div class=\"section-header\" (click)=\"ToggleSection('sql')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('sql')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('sql')\"></i>\n <span class=\"section-title\">SQL Query</span>\n </div>\n @if (IsSectionExpanded('sql')) {\n <div class=\"section-content\">\n @if (QueryInfo.SQL) {\n <div class=\"sql-container\">\n <mj-code-editor\n [value]=\"QueryInfo.SQL\"\n [readonly]=\"true\"\n [language]=\"'sql'\"\n (CompositionTokenClick)=\"OnCompositionTokenClick($event)\">\n </mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-section\">\n <i class=\"fa-solid fa-code\"></i>\n <span>SQL not available</span>\n </div>\n }\n </div>\n }\n </div>\n <!-- Dependent Queries Section -->\n @if (QueryInfo.Dependents.length > 0) {\n <div class=\"info-section\" [class.expanded]=\"IsSectionExpanded('dependents')\">\n <div class=\"section-header\" (click)=\"ToggleSection('dependents')\">\n <i class=\"fa-solid section-icon\"\n [class.fa-chevron-down]=\"IsSectionExpanded('dependents')\"\n [class.fa-chevron-right]=\"!IsSectionExpanded('dependents')\"></i>\n <span class=\"section-title\">Dependent Queries</span>\n <span class=\"section-count\">({{ QueryInfo.Dependents.length }})</span>\n </div>\n @if (IsSectionExpanded('dependents')) {\n <div class=\"section-content\">\n <div class=\"dependents-list\">\n @for (dep of QueryInfo.Dependents; track dep.ID) {\n <div class=\"dependent-item\" (click)=\"OnDependentQueryClick(dep)\">\n <div class=\"dependent-header\">\n <i class=\"fa-solid fa-arrow-left dependent-icon\"></i>\n <span class=\"dependent-name\">{{ dep.Query }}</span>\n </div>\n @if (dep.ReferencePath) {\n <span class=\"dependent-ref-path\">\n via {{ dep.ReferencePath }}\n </span>\n }\n </div>\n }\n </div>\n <div class=\"dependents-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n These queries reference this query via composition\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Footer -->\n <div class=\"panel-footer\">\n <button class=\"btn btn-primary\" (click)=\"OnOpenRecord()\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n Open Full Record\n </button>\n <button class=\"btn btn-secondary\" (click)=\"OnClose()\">\n Close\n </button>\n </div>\n </div>\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { EventEmitter, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
2
2
  import { QueryInfo } from '@memberjunction/core';
3
3
  import { RunQueryResult } from '@memberjunction/core';
4
+ import { CompositionTokenClickEvent } from '@memberjunction/ng-code-editor';
4
5
  import { QueryDataGridComponent } from '../query-data-grid/query-data-grid.component';
5
6
  import { QueryGridSelectionMode, QueryGridState, QueryGridVisualConfig, QueryParameterValues, QueryEntityLinkClickEvent, QueryGridStateChangedEvent, QuerySelectionChangedEvent, QueryRowClickEvent } from '../query-data-grid/models/query-grid-types';
6
7
  import * as i0 from "@angular/core";
@@ -85,6 +86,10 @@ export declare class QueryViewerComponent implements OnInit, OnDestroy {
85
86
  queryId: string;
86
87
  queryName: string;
87
88
  }>;
89
+ /**
90
+ * Fired when a composition token ({{query:"..."}}) is clicked in the SQL info panel
91
+ */
92
+ CompositionTokenClick: EventEmitter<CompositionTokenClickEvent>;
88
93
  DataGrid: QueryDataGridComponent;
89
94
  QueryInfo: QueryInfo | null;
90
95
  QueryData: Record<string, unknown>[];
@@ -124,9 +129,10 @@ export declare class QueryViewerComponent implements OnInit, OnDestroy {
124
129
  queryId: string;
125
130
  queryName: string;
126
131
  }): void;
132
+ OnCompositionTokenClick(event: CompositionTokenClickEvent): void;
127
133
  Refresh(): void;
128
134
  get HasParameters(): boolean;
129
135
  static ɵfac: i0.ɵɵFactoryDeclaration<QueryViewerComponent, never>;
130
- static ɵcmp: i0.ɵɵComponentDeclaration<QueryViewerComponent, "mj-query-viewer", never, { "QueryId": { "alias": "QueryId"; "required": false; }; "AutoRun": { "alias": "AutoRun"; "required": false; }; "SelectionMode": { "alias": "SelectionMode"; "required": false; }; "ShowToolbar": { "alias": "ShowToolbar"; "required": false; }; "VisualConfig": { "alias": "VisualConfig"; "required": false; }; "PersistState": { "alias": "PersistState"; "required": false; }; "PersistParameters": { "alias": "PersistParameters"; "required": false; }; }, { "EntityLinkClick": "EntityLinkClick"; "RowDoubleClick": "RowDoubleClick"; "SelectionChange": "SelectionChange"; "QueryStart": "QueryStart"; "QueryComplete": "QueryComplete"; "QueryError": "QueryError"; "OpenQueryRecord": "OpenQueryRecord"; }, never, never, false, never>;
136
+ static ɵcmp: i0.ɵɵComponentDeclaration<QueryViewerComponent, "mj-query-viewer", never, { "QueryId": { "alias": "QueryId"; "required": false; }; "AutoRun": { "alias": "AutoRun"; "required": false; }; "SelectionMode": { "alias": "SelectionMode"; "required": false; }; "ShowToolbar": { "alias": "ShowToolbar"; "required": false; }; "VisualConfig": { "alias": "VisualConfig"; "required": false; }; "PersistState": { "alias": "PersistState"; "required": false; }; "PersistParameters": { "alias": "PersistParameters"; "required": false; }; }, { "EntityLinkClick": "EntityLinkClick"; "RowDoubleClick": "RowDoubleClick"; "SelectionChange": "SelectionChange"; "QueryStart": "QueryStart"; "QueryComplete": "QueryComplete"; "QueryError": "QueryError"; "OpenQueryRecord": "OpenQueryRecord"; "CompositionTokenClick": "CompositionTokenClick"; }, never, never, false, never>;
131
137
  }
132
138
  //# sourceMappingURL=query-viewer.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-viewer.component.d.ts","sourceRoot":"","sources":["../../../src/lib/query-viewer/query-viewer.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-viewer.component.d.ts","sourceRoot":"","sources":["../../../src/lib/query-viewer/query-viewer.component.ts"],"names":[],"mappings":"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"}