@memberjunction/ng-query-viewer 6.2.0-edge.0 → 6.2.0-edge.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/query-data-grid/models/query-grid-types.d.ts +10 -0
- package/dist/lib/query-data-grid/models/query-grid-types.d.ts.map +1 -1
- package/dist/lib/query-data-grid/models/query-grid-types.js +26 -6
- package/dist/lib/query-data-grid/models/query-grid-types.js.map +1 -1
- package/dist/lib/query-data-grid/query-data-grid.component.d.ts.map +1 -1
- package/dist/lib/query-data-grid/query-data-grid.component.js +19 -11
- package/dist/lib/query-data-grid/query-data-grid.component.js.map +1 -1
- package/dist/lib/query-pivot/query-pivot.component.d.ts +144 -0
- package/dist/lib/query-pivot/query-pivot.component.d.ts.map +1 -0
- package/dist/lib/query-pivot/query-pivot.component.js +434 -0
- package/dist/lib/query-pivot/query-pivot.component.js.map +1 -0
- package/dist/lib/query-pivot/query-pivot.compute.d.ts +36 -0
- package/dist/lib/query-pivot/query-pivot.compute.d.ts.map +1 -0
- package/dist/lib/query-pivot/query-pivot.compute.js +324 -0
- package/dist/lib/query-pivot/query-pivot.compute.js.map +1 -0
- package/dist/lib/query-pivot/query-pivot.types.d.ts +74 -0
- package/dist/lib/query-pivot/query-pivot.types.d.ts.map +1 -0
- package/dist/lib/query-pivot/query-pivot.types.js +2 -0
- package/dist/lib/query-pivot/query-pivot.types.js.map +1 -0
- package/dist/lib/query-row-detail/query-row-detail.component.d.ts +26 -0
- package/dist/lib/query-row-detail/query-row-detail.component.d.ts.map +1 -1
- package/dist/lib/query-row-detail/query-row-detail.component.js +79 -23
- package/dist/lib/query-row-detail/query-row-detail.component.js.map +1 -1
- package/dist/lib/query-viewer/query-viewer.component.js +5 -5
- package/dist/lib/query-viewer/query-viewer.component.js.map +1 -1
- package/dist/lib/query-viewer.module.d.ts +11 -10
- package/dist/lib/query-viewer.module.d.ts.map +1 -1
- package/dist/lib/query-viewer.module.js +9 -4
- package/dist/lib/query-viewer.module.js.map +1 -1
- package/dist/public-api.d.ts +3 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +4 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +14 -14
|
@@ -2,6 +2,7 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, HostLi
|
|
|
2
2
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
3
3
|
import { Subject } from 'rxjs';
|
|
4
4
|
import { takeUntil, debounceTime } from 'rxjs/operators';
|
|
5
|
+
import { FormatDateOnly, IsDateOnlySQLType } from '@memberjunction/core';
|
|
5
6
|
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
6
7
|
import * as i0 from "@angular/core";
|
|
7
8
|
function QueryRowDetailComponent_Conditional_0_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -473,6 +474,11 @@ export class QueryRowDetailComponent {
|
|
|
473
474
|
const date = new Date(value);
|
|
474
475
|
if (isNaN(date.getTime()))
|
|
475
476
|
return String(value);
|
|
477
|
+
// A SQL `date` is a calendar day delivered as UTC midnight. Format it in UTC, and give it
|
|
478
|
+
// no "hours ago": measured from UTC midnight, a day has no time of its own to be ago from.
|
|
479
|
+
if (IsDateOnlySQLType(baseType)) {
|
|
480
|
+
return FormatDateOnly(date, { year: 'numeric', month: 'short', day: 'numeric' }, 'en-US');
|
|
481
|
+
}
|
|
476
482
|
const now = new Date();
|
|
477
483
|
const diffMs = now.getTime() - date.getTime();
|
|
478
484
|
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
@@ -487,12 +493,10 @@ export class QueryRowDetailComponent {
|
|
|
487
493
|
else if (diffDays < 7) {
|
|
488
494
|
relativeTime = `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;
|
|
489
495
|
}
|
|
490
|
-
const formatted =
|
|
491
|
-
|
|
492
|
-
:
|
|
493
|
-
|
|
494
|
-
hour: 'numeric', minute: '2-digit'
|
|
495
|
-
});
|
|
496
|
+
const formatted = date.toLocaleString('en-US', {
|
|
497
|
+
year: 'numeric', month: 'short', day: 'numeric',
|
|
498
|
+
hour: 'numeric', minute: '2-digit'
|
|
499
|
+
});
|
|
496
500
|
return relativeTime ? `${formatted} • ${relativeTime}` : formatted;
|
|
497
501
|
}
|
|
498
502
|
// Numbers
|
|
@@ -530,10 +534,14 @@ export class QueryRowDetailComponent {
|
|
|
530
534
|
// ========================================
|
|
531
535
|
// User Actions
|
|
532
536
|
// ========================================
|
|
533
|
-
|
|
537
|
+
OnClose() {
|
|
534
538
|
this.Close.emit();
|
|
535
539
|
}
|
|
536
|
-
|
|
540
|
+
/** @deprecated Use {@link OnClose}. */
|
|
541
|
+
onClose() {
|
|
542
|
+
return this.OnClose();
|
|
543
|
+
}
|
|
544
|
+
OnEntityLinkClick(field) {
|
|
537
545
|
if (field.targetEntityName && field.value != null) {
|
|
538
546
|
this.EntityLinkClick.emit({
|
|
539
547
|
entityName: field.targetEntityName,
|
|
@@ -542,34 +550,62 @@ export class QueryRowDetailComponent {
|
|
|
542
550
|
});
|
|
543
551
|
}
|
|
544
552
|
}
|
|
545
|
-
|
|
553
|
+
/** @deprecated Use {@link OnEntityLinkClick}. */
|
|
554
|
+
onEntityLinkClick(field) {
|
|
555
|
+
return this.OnEntityLinkClick(field);
|
|
556
|
+
}
|
|
557
|
+
OnNavigatePrev() {
|
|
546
558
|
this.NavigateRow.emit('prev');
|
|
547
559
|
}
|
|
548
|
-
|
|
560
|
+
/** @deprecated Use {@link OnNavigatePrev}. */
|
|
561
|
+
onNavigatePrev() {
|
|
562
|
+
return this.OnNavigatePrev();
|
|
563
|
+
}
|
|
564
|
+
OnNavigateNext() {
|
|
549
565
|
this.NavigateRow.emit('next');
|
|
550
566
|
}
|
|
551
|
-
|
|
567
|
+
/** @deprecated Use {@link OnNavigateNext}. */
|
|
568
|
+
onNavigateNext() {
|
|
569
|
+
return this.OnNavigateNext();
|
|
570
|
+
}
|
|
571
|
+
ToggleFieldExpand(field) {
|
|
552
572
|
field.isExpanded = !field.isExpanded;
|
|
553
573
|
this.cdr.markForCheck();
|
|
554
574
|
}
|
|
555
|
-
|
|
575
|
+
/** @deprecated Use {@link ToggleFieldExpand}. */
|
|
576
|
+
toggleFieldExpand(field) {
|
|
577
|
+
return this.ToggleFieldExpand(field);
|
|
578
|
+
}
|
|
579
|
+
CopyValue(field) {
|
|
556
580
|
const textToCopy = field.value != null ? String(field.value) : '';
|
|
557
581
|
navigator.clipboard.writeText(textToCopy);
|
|
558
582
|
}
|
|
559
|
-
|
|
583
|
+
/** @deprecated Use {@link CopyValue}. */
|
|
584
|
+
copyValue(field) {
|
|
585
|
+
return this.CopyValue(field);
|
|
586
|
+
}
|
|
587
|
+
CopyRowAsJson() {
|
|
560
588
|
if (this._rowData) {
|
|
561
589
|
const json = JSON.stringify(this._rowData, null, 2);
|
|
562
590
|
navigator.clipboard.writeText(json);
|
|
563
591
|
}
|
|
564
592
|
}
|
|
565
|
-
|
|
593
|
+
/** @deprecated Use {@link CopyRowAsJson}. */
|
|
594
|
+
copyRowAsJson() {
|
|
595
|
+
return this.CopyRowAsJson();
|
|
596
|
+
}
|
|
597
|
+
IsJson(value) {
|
|
566
598
|
if (!value || typeof value !== 'string')
|
|
567
599
|
return false;
|
|
568
600
|
const trimmed = value.trim();
|
|
569
601
|
return (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
570
602
|
(trimmed.startsWith('[') && trimmed.endsWith(']'));
|
|
571
603
|
}
|
|
572
|
-
|
|
604
|
+
/** @deprecated Use {@link IsJson}. */
|
|
605
|
+
isJson(value) {
|
|
606
|
+
return this.IsJson(value);
|
|
607
|
+
}
|
|
608
|
+
FormatJson(value) {
|
|
573
609
|
try {
|
|
574
610
|
return JSON.stringify(JSON.parse(value), null, 2);
|
|
575
611
|
}
|
|
@@ -577,15 +613,23 @@ export class QueryRowDetailComponent {
|
|
|
577
613
|
return value;
|
|
578
614
|
}
|
|
579
615
|
}
|
|
616
|
+
/** @deprecated Use {@link FormatJson}. */
|
|
617
|
+
formatJson(value) {
|
|
618
|
+
return this.FormatJson(value);
|
|
619
|
+
}
|
|
580
620
|
// ========================================
|
|
581
621
|
// Resize Handling
|
|
582
622
|
// ========================================
|
|
583
|
-
|
|
623
|
+
OnResizeStart(event) {
|
|
584
624
|
event.preventDefault();
|
|
585
625
|
this.IsResizing = true;
|
|
586
626
|
document.body.style.cursor = 'ew-resize';
|
|
587
627
|
document.body.style.userSelect = 'none';
|
|
588
628
|
}
|
|
629
|
+
/** @deprecated Use {@link OnResizeStart}. */
|
|
630
|
+
onResizeStart(event) {
|
|
631
|
+
return this.OnResizeStart(event);
|
|
632
|
+
}
|
|
589
633
|
onMouseMove(event) {
|
|
590
634
|
if (!this.IsResizing)
|
|
591
635
|
return;
|
|
@@ -648,26 +692,38 @@ export class QueryRowDetailComponent {
|
|
|
648
692
|
console.error('[query-row-detail] Failed to persist hide empty fields preference:', error);
|
|
649
693
|
}
|
|
650
694
|
}
|
|
651
|
-
|
|
695
|
+
ToggleHideEmptyFields() {
|
|
652
696
|
this.HideEmptyFields = !this.HideEmptyFields;
|
|
653
697
|
this.persistHideEmptyFieldsPreference();
|
|
654
698
|
this.cdr.markForCheck();
|
|
655
699
|
}
|
|
700
|
+
/** @deprecated Use {@link ToggleHideEmptyFields}. */
|
|
701
|
+
toggleHideEmptyFields() {
|
|
702
|
+
return this.ToggleHideEmptyFields();
|
|
703
|
+
}
|
|
656
704
|
/**
|
|
657
705
|
* Returns visible fields based on HideEmptyFields setting
|
|
658
706
|
*/
|
|
659
|
-
|
|
707
|
+
GetVisibleFields(fields) {
|
|
660
708
|
if (!this.HideEmptyFields) {
|
|
661
709
|
return fields;
|
|
662
710
|
}
|
|
663
711
|
return fields.filter(f => f.value !== null && f.value !== undefined && f.value !== '');
|
|
664
712
|
}
|
|
713
|
+
/** @deprecated Use {@link GetVisibleFields}. */
|
|
714
|
+
getVisibleFields(fields) {
|
|
715
|
+
return this.GetVisibleFields(fields);
|
|
716
|
+
}
|
|
665
717
|
/**
|
|
666
718
|
* Returns count of empty fields for display
|
|
667
719
|
*/
|
|
668
|
-
|
|
720
|
+
GetEmptyFieldCount(fields) {
|
|
669
721
|
return fields.filter(f => f.value === null || f.value === undefined || f.value === '').length;
|
|
670
722
|
}
|
|
723
|
+
/** @deprecated Use {@link GetEmptyFieldCount}. */
|
|
724
|
+
getEmptyFieldCount(fields) {
|
|
725
|
+
return this.GetEmptyFieldCount(fields);
|
|
726
|
+
}
|
|
671
727
|
// ========================================
|
|
672
728
|
// Keyboard Navigation
|
|
673
729
|
// ========================================
|
|
@@ -675,16 +731,16 @@ export class QueryRowDetailComponent {
|
|
|
675
731
|
if (!this.Visible)
|
|
676
732
|
return;
|
|
677
733
|
if (event.key === 'Escape') {
|
|
678
|
-
this.
|
|
734
|
+
this.OnClose();
|
|
679
735
|
}
|
|
680
736
|
else if (event.key === 'ArrowUp' || event.key === 'k') {
|
|
681
737
|
if (this.RowIndex > 0) {
|
|
682
|
-
this.
|
|
738
|
+
this.OnNavigatePrev();
|
|
683
739
|
}
|
|
684
740
|
}
|
|
685
741
|
else if (event.key === 'ArrowDown' || event.key === 'j') {
|
|
686
742
|
if (this.RowIndex < this.TotalRows - 1) {
|
|
687
|
-
this.
|
|
743
|
+
this.OnNavigateNext();
|
|
688
744
|
}
|
|
689
745
|
}
|
|
690
746
|
}
|
|
@@ -751,5 +807,5 @@ export class QueryRowDetailComponent {
|
|
|
751
807
|
type: HostListener,
|
|
752
808
|
args: ['document:keydown', ['$event']]
|
|
753
809
|
}] }); })();
|
|
754
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryRowDetailComponent, { className: "QueryRowDetailComponent", filePath: "src/lib/query-row-detail/query-row-detail.component.ts", lineNumber:
|
|
810
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryRowDetailComponent, { className: "QueryRowDetailComponent", filePath: "src/lib/query-row-detail/query-row-detail.component.ts", lineNumber: 80 }); })();
|
|
755
811
|
//# sourceMappingURL=query-row-detail.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-row-detail.component.js","sourceRoot":"","sources":["../../../src/lib/query-row-detail/query-row-detail.component.ts","../../../src/lib/query-row-detail/query-row-detail.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ElementRef,\n HostListener\n} from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\nimport { Subject } from 'rxjs';\nimport { takeUntil, debounceTime } from 'rxjs/operators';\nimport { MJQueryEntityExtended } from '@memberjunction/core-entities';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { QueryGridColumnConfig } from '../query-data-grid/models/query-grid-types';\n\n/**\n * Event emitted when navigating to a linked entity record\n */\nexport interface RowDetailEntityLinkEvent {\n entityName: string;\n recordId: string;\n fieldName: string;\n}\n\n/**\n * Field display configuration for the detail panel\n */\ninterface DetailField {\n name: string;\n displayName: string;\n value: unknown;\n formattedValue: string;\n sqlType: string;\n isPrimaryKey: boolean;\n isForeignKey: boolean;\n targetEntityName?: string;\n targetEntityIcon?: string;\n sourceEntityName?: string;\n isLongText: boolean;\n isExpanded: boolean;\n}\n\n/**\n * Settings key for panel width persistence\n */\nconst PANEL_WIDTH_SETTING_KEY = 'QueryViewer_RowDetailPanel_Width';\n\n/**\n * Settings key for hide empty fields preference\n */\nconst HIDE_EMPTY_FIELDS_KEY = 'QueryViewer_RowDetailPanel_HideEmptyFields';\n\n/**\n * Row detail slide-in panel component.\n * Displays a single row's data in a formatted, grouped view with entity links.\n */\n@Component({\n standalone: false,\n selector: 'mj-query-row-detail',\n templateUrl: './query-row-detail.component.html',\n styleUrls: ['./query-row-detail.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [\n trigger('slideIn', [\n transition(':enter', [\n style({ transform: 'translateX(100%)', opacity: 0 }),\n animate('200ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))\n ]),\n transition(':leave', [\n animate('150ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))\n ])\n ])\n ]\n})\nexport class QueryRowDetailComponent implements OnInit, OnDestroy {\n // ========================================\n // Inputs\n // ========================================\n\n private _rowData: Record<string, unknown> | null = null;\n @Input()\n set RowData(value: Record<string, unknown> | null) {\n this._rowData = value;\n if (value) {\n this.buildDetailFields();\n }\n }\n get RowData(): Record<string, unknown> | null {\n return this._rowData;\n }\n\n private _columns: QueryGridColumnConfig[] = [];\n @Input()\n set Columns(value: QueryGridColumnConfig[]) {\n this._columns = value || [];\n if (this._rowData) {\n this.buildDetailFields();\n }\n }\n get Columns(): QueryGridColumnConfig[] {\n return this._columns;\n }\n\n @Input() QueryInfo: MJQueryEntityExtended | null = null;\n @Input() Visible: boolean = false;\n @Input() RowIndex: number = 0;\n @Input() TotalRows: number = 0;\n\n // ========================================\n // Outputs\n // ========================================\n\n @Output() Close = new EventEmitter<void>();\n @Output() EntityLinkClick = new EventEmitter<RowDetailEntityLinkEvent>();\n @Output() NavigateRow = new EventEmitter<'prev' | 'next'>();\n\n // ========================================\n // Internal State\n // ========================================\n\n public PrimaryKeyFields: DetailField[] = [];\n public ForeignKeyFields: DetailField[] = [];\n public RegularFields: DetailField[] = [];\n public PanelWidth: number = 400;\n public IsResizing: boolean = false;\n public HideEmptyFields: boolean = true;\n\n private destroy$ = new Subject<void>();\n private widthPersistSubject = new Subject<number>();\n private minWidth = 300;\n private maxWidth = 800;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private elementRef: ElementRef\n ) {\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.loadPersistedWidth();\n this.loadHideEmptyFieldsPreference();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ========================================\n // Field Building\n // ========================================\n\n private buildDetailFields(): void {\n if (!this._rowData || !this._columns.length) {\n this.PrimaryKeyFields = [];\n this.ForeignKeyFields = [];\n this.RegularFields = [];\n return;\n }\n\n const primaryKeys: DetailField[] = [];\n const foreignKeys: DetailField[] = [];\n const regular: DetailField[] = [];\n\n for (const col of this._columns) {\n const value = this._rowData[col.field];\n const field = this.buildDetailField(col, value);\n\n if (field.isPrimaryKey) {\n primaryKeys.push(field);\n } else if (field.isForeignKey) {\n foreignKeys.push(field);\n } else {\n regular.push(field);\n }\n }\n\n this.PrimaryKeyFields = primaryKeys;\n this.ForeignKeyFields = foreignKeys;\n this.RegularFields = regular;\n this.cdr.markForCheck();\n }\n\n private buildDetailField(col: QueryGridColumnConfig, value: unknown): DetailField {\n const formattedValue = this.formatValue(value, col);\n const isLongText = typeof value === 'string' && value.length > 200;\n\n return {\n name: col.field,\n displayName: col.title,\n value,\n formattedValue,\n sqlType: col.sqlBaseType,\n isPrimaryKey: col.isPrimaryKey || false,\n isForeignKey: col.isForeignKey || false,\n targetEntityName: col.targetEntityName,\n targetEntityIcon: col.targetEntityIcon,\n sourceEntityName: col.sourceEntityName,\n isLongText,\n isExpanded: false\n };\n }\n\n private formatValue(value: unknown, col: QueryGridColumnConfig): string {\n if (value === null || value === undefined) {\n return '(empty)';\n }\n\n const baseType = col.sqlBaseType.toLowerCase();\n\n // Boolean\n if (baseType === 'bit') {\n return value ? 'Yes' : 'No';\n }\n\n // Date/Time\n if (['date', 'datetime', 'datetime2', 'smalldatetime', 'datetimeoffset'].includes(baseType)) {\n const date = new Date(value as string);\n if (isNaN(date.getTime())) return String(value);\n\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffHours = Math.floor(diffMs / (1000 * 60 * 60));\n const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n let relativeTime = '';\n if (diffHours < 1) {\n relativeTime = 'just now';\n } else if (diffHours < 24) {\n relativeTime = `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;\n } else if (diffDays < 7) {\n relativeTime = `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;\n }\n\n const formatted = baseType === 'date'\n ? date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })\n : date.toLocaleString('en-US', {\n year: 'numeric', month: 'short', day: 'numeric',\n hour: 'numeric', minute: '2-digit'\n });\n\n return relativeTime ? `${formatted} • ${relativeTime}` : formatted;\n }\n\n // Numbers\n if (['int', 'bigint', 'smallint', 'tinyint'].includes(baseType)) {\n const num = Number(value);\n if (isNaN(num)) return String(value);\n return num.toLocaleString();\n }\n\n if (['decimal', 'numeric', 'float', 'real'].includes(baseType)) {\n const num = Number(value);\n if (isNaN(num)) return String(value);\n return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 4 });\n }\n\n if (['money', 'smallmoney'].includes(baseType)) {\n const num = Number(value);\n if (isNaN(num)) return String(value);\n return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(num);\n }\n\n // JSON detection\n const strValue = String(value);\n if (strValue.startsWith('{') || strValue.startsWith('[')) {\n try {\n JSON.parse(strValue);\n return strValue; // Will be formatted as JSON in template\n } catch {\n // Not valid JSON, continue\n }\n }\n\n return strValue;\n }\n\n // ========================================\n // User Actions\n // ========================================\n\n public onClose(): void {\n this.Close.emit();\n }\n\n public onEntityLinkClick(field: DetailField): void {\n if (field.targetEntityName && field.value != null) {\n this.EntityLinkClick.emit({\n entityName: field.targetEntityName,\n recordId: String(field.value),\n fieldName: field.name\n });\n }\n }\n\n public onNavigatePrev(): void {\n this.NavigateRow.emit('prev');\n }\n\n public onNavigateNext(): void {\n this.NavigateRow.emit('next');\n }\n\n public toggleFieldExpand(field: DetailField): void {\n field.isExpanded = !field.isExpanded;\n this.cdr.markForCheck();\n }\n\n public copyValue(field: DetailField): void {\n const textToCopy = field.value != null ? String(field.value) : '';\n navigator.clipboard.writeText(textToCopy);\n }\n\n public copyRowAsJson(): void {\n if (this._rowData) {\n const json = JSON.stringify(this._rowData, null, 2);\n navigator.clipboard.writeText(json);\n }\n }\n\n public isJson(value: string): boolean {\n if (!value || typeof value !== 'string') return false;\n const trimmed = value.trim();\n return (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'));\n }\n\n public formatJson(value: string): string {\n try {\n return JSON.stringify(JSON.parse(value), null, 2);\n } catch {\n return value;\n }\n }\n\n // ========================================\n // Resize Handling\n // ========================================\n\n public onResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.IsResizing = true;\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n }\n\n @HostListener('document:mousemove', ['$event'])\n onMouseMove(event: MouseEvent): void {\n if (!this.IsResizing) return;\n\n const containerRect = this.elementRef.nativeElement.parentElement?.getBoundingClientRect();\n if (!containerRect) return;\n\n const newWidth = containerRect.right - event.clientX;\n this.PanelWidth = Math.min(Math.max(newWidth, this.minWidth), this.maxWidth);\n this.cdr.markForCheck();\n }\n\n @HostListener('document:mouseup')\n onMouseUp(): void {\n if (this.IsResizing) {\n this.IsResizing = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n this.widthPersistSubject.next(this.PanelWidth);\n }\n }\n\n // ========================================\n // Persistence\n // ========================================\n\n private loadPersistedWidth(): void {\n try {\n const savedWidth = UserInfoEngine.Instance.GetSetting(PANEL_WIDTH_SETTING_KEY);\n if (savedWidth) {\n const width = parseInt(savedWidth, 10);\n if (!isNaN(width) && width >= this.minWidth && width <= this.maxWidth) {\n this.PanelWidth = width;\n }\n }\n } catch (error) {\n console.error('[query-row-detail] Failed to load persisted width:', error);\n }\n }\n\n private async persistPanelWidth(width: number): Promise<void> {\n try {\n await UserInfoEngine.Instance.SetSetting(PANEL_WIDTH_SETTING_KEY, String(width));\n } catch (error) {\n console.error('[query-row-detail] Failed to persist panel width:', error);\n }\n }\n\n private loadHideEmptyFieldsPreference(): void {\n try {\n const saved = UserInfoEngine.Instance.GetSetting(HIDE_EMPTY_FIELDS_KEY);\n if (saved !== undefined) {\n this.HideEmptyFields = saved === 'true';\n }\n } catch (error) {\n console.error('[query-row-detail] Failed to load hide empty fields preference:', error);\n }\n }\n\n private async persistHideEmptyFieldsPreference(): Promise<void> {\n try {\n await UserInfoEngine.Instance.SetSetting(HIDE_EMPTY_FIELDS_KEY, String(this.HideEmptyFields));\n } catch (error) {\n console.error('[query-row-detail] Failed to persist hide empty fields preference:', error);\n }\n }\n\n public toggleHideEmptyFields(): void {\n this.HideEmptyFields = !this.HideEmptyFields;\n this.persistHideEmptyFieldsPreference();\n this.cdr.markForCheck();\n }\n\n /**\n * Returns visible fields based on HideEmptyFields setting\n */\n public getVisibleFields(fields: DetailField[]): DetailField[] {\n if (!this.HideEmptyFields) {\n return fields;\n }\n return fields.filter(f => f.value !== null && f.value !== undefined && f.value !== '');\n }\n\n /**\n * Returns count of empty fields for display\n */\n public getEmptyFieldCount(fields: DetailField[]): number {\n return fields.filter(f => f.value === null || f.value === undefined || f.value === '').length;\n }\n\n // ========================================\n // Keyboard Navigation\n // ========================================\n\n @HostListener('document:keydown', ['$event'])\n onKeyDown(event: KeyboardEvent): void {\n if (!this.Visible) return;\n\n if (event.key === 'Escape') {\n this.onClose();\n } else if (event.key === 'ArrowUp' || event.key === 'k') {\n if (this.RowIndex > 0) {\n this.onNavigatePrev();\n }\n } else if (event.key === 'ArrowDown' || event.key === 'j') {\n if (this.RowIndex < this.TotalRows - 1) {\n this.onNavigateNext();\n }\n }\n }\n}\n","<!-- Row Detail Slide-in Panel -->\n@if (Visible) {\n <div class=\"row-detail-panel\"\n @slideIn\n [style.width.px]=\"PanelWidth\">\n <!-- Resize handle -->\n <div class=\"resize-handle\"\n (mousedown)=\"onResizeStart($event)\"\n [class.resizing]=\"IsResizing\">\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <i class=\"fa-solid fa-table-cells-large header-icon\"></i>\n <h3 class=\"panel-title\">Row Details</h3>\n </div>\n <div class=\"header-right\">\n <!-- Row navigation -->\n @if (TotalRows > 1) {\n <div class=\"row-nav\">\n <button class=\"nav-btn\"\n [disabled]=\"RowIndex === 0\"\n (click)=\"onNavigatePrev()\"\n title=\"Previous row (↑ or K)\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <span class=\"row-indicator\">{{ RowIndex + 1 }} / {{ TotalRows }}</span>\n <button class=\"nav-btn\"\n [disabled]=\"RowIndex >= TotalRows - 1\"\n (click)=\"onNavigateNext()\"\n title=\"Next row (↓ or J)\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n }\n <!-- Toggle empty fields -->\n <button class=\"action-btn\"\n (click)=\"toggleHideEmptyFields()\"\n [class.active]=\"HideEmptyFields\"\n [title]=\"HideEmptyFields ? 'Show empty fields' : 'Hide empty fields'\">\n <i class=\"fa-solid\" [class.fa-eye]=\"!HideEmptyFields\" [class.fa-eye-slash]=\"HideEmptyFields\"></i>\n </button>\n <!-- Copy JSON button -->\n <button class=\"action-btn\" (click)=\"copyRowAsJson()\" title=\"Copy row as JSON\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <!-- Close button -->\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Primary Keys Section -->\n @if (getVisibleFields(PrimaryKeyFields).length > 0) {\n <div class=\"field-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-key section-icon pk-icon\"></i>\n Primary Key\n </h4>\n <div class=\"field-list\">\n @for (field of getVisibleFields(PrimaryKeyFields); track field) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n <button class=\"copy-btn\" (click)=\"copyValue(field)\" title=\"Copy value\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n <div class=\"field-value\"\n [class.clickable]=\"field.targetEntityName\"\n (click)=\"field.targetEntityName && onEntityLinkClick(field)\">\n @if (field.targetEntityIcon) {\n <i\n [class]=\"field.targetEntityIcon\"\n class=\"entity-icon\"></i>\n }\n <span class=\"value-text monospace\">{{ field.formattedValue }}</span>\n @if (field.targetEntityName) {\n <i\n class=\"fa-solid fa-arrow-up-right-from-square link-icon\"></i>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Foreign Keys Section -->\n @if (getVisibleFields(ForeignKeyFields).length > 0) {\n <div class=\"field-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-link section-icon fk-icon\"></i>\n Related Records\n </h4>\n <div class=\"field-list\">\n @for (field of getVisibleFields(ForeignKeyFields); track field) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n @if (field.targetEntityName) {\n <span class=\"target-entity\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n {{ field.targetEntityName }}\n </span>\n }\n <button class=\"copy-btn\" (click)=\"copyValue(field)\" title=\"Copy value\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n @if (field.value != null) {\n <div class=\"field-value clickable\"\n (click)=\"onEntityLinkClick(field)\">\n @if (field.targetEntityIcon) {\n <i\n [class]=\"field.targetEntityIcon\"\n class=\"entity-icon\"></i>\n }\n <span class=\"value-text monospace\">{{ field.formattedValue }}</span>\n <i class=\"fa-solid fa-arrow-up-right-from-square link-icon\"></i>\n </div>\n }\n @if (field.value == null) {\n <div class=\"field-value empty\">\n <span class=\"value-text\">(empty)</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n <!-- Regular Fields Section -->\n @if (getVisibleFields(RegularFields).length > 0) {\n <div class=\"field-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-list section-icon\"></i>\n Fields\n @if (HideEmptyFields && getEmptyFieldCount(RegularFields) > 0) {\n <span class=\"hidden-count\">\n ({{ getEmptyFieldCount(RegularFields) }} empty hidden)\n </span>\n }\n </h4>\n <div class=\"field-list\">\n @for (field of getVisibleFields(RegularFields); track field) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n <span class=\"field-type\">{{ field.sqlType }}</span>\n <button class=\"copy-btn\" (click)=\"copyValue(field)\" title=\"Copy value\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n <!-- JSON value -->\n @if (isJson(field.formattedValue)) {\n <div class=\"field-value json-value\"\n [class.expanded]=\"field.isExpanded\">\n <pre class=\"json-content\">{{ formatJson(field.formattedValue) }}</pre>\n <button class=\"expand-btn\" (click)=\"toggleFieldExpand(field)\">\n {{ field.isExpanded ? 'Collapse' : 'Expand' }}\n </button>\n </div>\n }\n <!-- Long text value -->\n @if (!isJson(field.formattedValue) && field.isLongText) {\n <div class=\"field-value long-text\"\n [class.expanded]=\"field.isExpanded\">\n <span class=\"value-text\">{{ field.formattedValue }}</span>\n <button class=\"expand-btn\" (click)=\"toggleFieldExpand(field)\">\n {{ field.isExpanded ? 'Show less' : 'Show more' }}\n </button>\n </div>\n }\n <!-- Boolean value -->\n @if (field.sqlType.toLowerCase() === 'bit' && !isJson(field.formattedValue)) {\n <div class=\"field-value boolean-value\"\n >\n <i [class]=\"field.value ? 'fa-solid fa-check-circle bool-true' : 'fa-solid fa-times-circle bool-false'\"></i>\n <span class=\"value-text\">{{ field.formattedValue }}</span>\n </div>\n }\n <!-- Empty value -->\n @if (field.value == null && !isJson(field.formattedValue)) {\n <div class=\"field-value empty\"\n >\n <span class=\"value-text\">(empty)</span>\n </div>\n }\n <!-- Regular value -->\n @if (field.value != null && !isJson(field.formattedValue) && !field.isLongText && field.sqlType.toLowerCase() !== 'bit') {\n <div class=\"field-value\"\n >\n <span class=\"value-text\"\n [class.monospace]=\"field.sqlType.toLowerCase().includes('uniqueidentifier') || field.name.toLowerCase().includes('id')\">\n {{ field.formattedValue }}\n </span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n<!-- Backdrop -->\n@if (Visible) {\n <div class=\"panel-backdrop\"\n (click)=\"onClose()\">\n </div>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"query-row-detail.component.js","sourceRoot":"","sources":["../../../src/lib/query-row-detail/query-row-detail.component.ts","../../../src/lib/query-row-detail/query-row-detail.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ElementRef,\n HostListener\n} from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\nimport { Subject } from 'rxjs';\nimport { takeUntil, debounceTime } from 'rxjs/operators';\nimport { MJQueryEntityExtended } from '@memberjunction/core-entities';\nimport { FormatDateOnly, IsDateOnlySQLType } from '@memberjunction/core';\nimport { UserInfoEngine } from '@memberjunction/core-entities';\nimport { QueryGridColumnConfig } from '../query-data-grid/models/query-grid-types';\n\n/**\n * Event emitted when navigating to a linked entity record\n */\nexport interface RowDetailEntityLinkEvent {\n entityName: string;\n recordId: string;\n fieldName: string;\n}\n\n/**\n * Field display configuration for the detail panel\n */\ninterface DetailField {\n name: string;\n displayName: string;\n value: unknown;\n formattedValue: string;\n sqlType: string;\n isPrimaryKey: boolean;\n isForeignKey: boolean;\n targetEntityName?: string;\n targetEntityIcon?: string;\n sourceEntityName?: string;\n isLongText: boolean;\n isExpanded: boolean;\n}\n\n/**\n * Settings key for panel width persistence\n */\nconst PANEL_WIDTH_SETTING_KEY = 'QueryViewer_RowDetailPanel_Width';\n\n/**\n * Settings key for hide empty fields preference\n */\nconst HIDE_EMPTY_FIELDS_KEY = 'QueryViewer_RowDetailPanel_HideEmptyFields';\n\n/**\n * Row detail slide-in panel component.\n * Displays a single row's data in a formatted, grouped view with entity links.\n */\n@Component({\n standalone: false,\n selector: 'mj-query-row-detail',\n templateUrl: './query-row-detail.component.html',\n styleUrls: ['./query-row-detail.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n animations: [\n trigger('slideIn', [\n transition(':enter', [\n style({ transform: 'translateX(100%)', opacity: 0 }),\n animate('200ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))\n ]),\n transition(':leave', [\n animate('150ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))\n ])\n ])\n ]\n})\nexport class QueryRowDetailComponent implements OnInit, OnDestroy {\n // ========================================\n // Inputs\n // ========================================\n\n private _rowData: Record<string, unknown> | null = null;\n @Input()\n set RowData(value: Record<string, unknown> | null) {\n this._rowData = value;\n if (value) {\n this.buildDetailFields();\n }\n }\n get RowData(): Record<string, unknown> | null {\n return this._rowData;\n }\n\n private _columns: QueryGridColumnConfig[] = [];\n @Input()\n set Columns(value: QueryGridColumnConfig[]) {\n this._columns = value || [];\n if (this._rowData) {\n this.buildDetailFields();\n }\n }\n get Columns(): QueryGridColumnConfig[] {\n return this._columns;\n }\n\n @Input() QueryInfo: MJQueryEntityExtended | null = null;\n @Input() Visible: boolean = false;\n @Input() RowIndex: number = 0;\n @Input() TotalRows: number = 0;\n\n // ========================================\n // Outputs\n // ========================================\n\n @Output() Close = new EventEmitter<void>();\n @Output() EntityLinkClick = new EventEmitter<RowDetailEntityLinkEvent>();\n @Output() NavigateRow = new EventEmitter<'prev' | 'next'>();\n\n // ========================================\n // Internal State\n // ========================================\n\n public PrimaryKeyFields: DetailField[] = [];\n public ForeignKeyFields: DetailField[] = [];\n public RegularFields: DetailField[] = [];\n public PanelWidth: number = 400;\n public IsResizing: boolean = false;\n public HideEmptyFields: boolean = true;\n\n private destroy$ = new Subject<void>();\n private widthPersistSubject = new Subject<number>();\n private minWidth = 300;\n private maxWidth = 800;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private elementRef: ElementRef\n ) {\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.loadPersistedWidth();\n this.loadHideEmptyFieldsPreference();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ========================================\n // Field Building\n // ========================================\n\n private buildDetailFields(): void {\n if (!this._rowData || !this._columns.length) {\n this.PrimaryKeyFields = [];\n this.ForeignKeyFields = [];\n this.RegularFields = [];\n return;\n }\n\n const primaryKeys: DetailField[] = [];\n const foreignKeys: DetailField[] = [];\n const regular: DetailField[] = [];\n\n for (const col of this._columns) {\n const value = this._rowData[col.field];\n const field = this.buildDetailField(col, value);\n\n if (field.isPrimaryKey) {\n primaryKeys.push(field);\n } else if (field.isForeignKey) {\n foreignKeys.push(field);\n } else {\n regular.push(field);\n }\n }\n\n this.PrimaryKeyFields = primaryKeys;\n this.ForeignKeyFields = foreignKeys;\n this.RegularFields = regular;\n this.cdr.markForCheck();\n }\n\n private buildDetailField(col: QueryGridColumnConfig, value: unknown): DetailField {\n const formattedValue = this.formatValue(value, col);\n const isLongText = typeof value === 'string' && value.length > 200;\n\n return {\n name: col.field,\n displayName: col.title,\n value,\n formattedValue,\n sqlType: col.sqlBaseType,\n isPrimaryKey: col.isPrimaryKey || false,\n isForeignKey: col.isForeignKey || false,\n targetEntityName: col.targetEntityName,\n targetEntityIcon: col.targetEntityIcon,\n sourceEntityName: col.sourceEntityName,\n isLongText,\n isExpanded: false\n };\n }\n\n private formatValue(value: unknown, col: QueryGridColumnConfig): string {\n if (value === null || value === undefined) {\n return '(empty)';\n }\n\n const baseType = col.sqlBaseType.toLowerCase();\n\n // Boolean\n if (baseType === 'bit') {\n return value ? 'Yes' : 'No';\n }\n\n // Date/Time\n if (['date', 'datetime', 'datetime2', 'smalldatetime', 'datetimeoffset'].includes(baseType)) {\n const date = new Date(value as string);\n if (isNaN(date.getTime())) return String(value);\n\n // A SQL `date` is a calendar day delivered as UTC midnight. Format it in UTC, and give it\n // no \"hours ago\": measured from UTC midnight, a day has no time of its own to be ago from.\n if (IsDateOnlySQLType(baseType)) {\n return FormatDateOnly(date, { year: 'numeric', month: 'short', day: 'numeric' }, 'en-US');\n }\n\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffHours = Math.floor(diffMs / (1000 * 60 * 60));\n const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n let relativeTime = '';\n if (diffHours < 1) {\n relativeTime = 'just now';\n } else if (diffHours < 24) {\n relativeTime = `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;\n } else if (diffDays < 7) {\n relativeTime = `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;\n }\n\n const formatted = date.toLocaleString('en-US', {\n year: 'numeric', month: 'short', day: 'numeric',\n hour: 'numeric', minute: '2-digit'\n });\n\n return relativeTime ? `${formatted} • ${relativeTime}` : formatted;\n }\n\n // Numbers\n if (['int', 'bigint', 'smallint', 'tinyint'].includes(baseType)) {\n const num = Number(value);\n if (isNaN(num)) return String(value);\n return num.toLocaleString();\n }\n\n if (['decimal', 'numeric', 'float', 'real'].includes(baseType)) {\n const num = Number(value);\n if (isNaN(num)) return String(value);\n return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 4 });\n }\n\n if (['money', 'smallmoney'].includes(baseType)) {\n const num = Number(value);\n if (isNaN(num)) return String(value);\n return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(num);\n }\n\n // JSON detection\n const strValue = String(value);\n if (strValue.startsWith('{') || strValue.startsWith('[')) {\n try {\n JSON.parse(strValue);\n return strValue; // Will be formatted as JSON in template\n } catch {\n // Not valid JSON, continue\n }\n }\n\n return strValue;\n }\n\n // ========================================\n // User Actions\n // ========================================\n\n public OnClose(): void {\n this.Close.emit();\n }\n\n /** @deprecated Use {@link OnClose}. */\n public onClose(): void {\n return this.OnClose();\n }\n\n public OnEntityLinkClick(field: DetailField): void {\n if (field.targetEntityName && field.value != null) {\n this.EntityLinkClick.emit({\n entityName: field.targetEntityName,\n recordId: String(field.value),\n fieldName: field.name\n });\n }\n }\n\n /** @deprecated Use {@link OnEntityLinkClick}. */\n public onEntityLinkClick(field: DetailField): void {\n return this.OnEntityLinkClick(field);\n }\n\n public OnNavigatePrev(): void {\n this.NavigateRow.emit('prev');\n }\n\n /** @deprecated Use {@link OnNavigatePrev}. */\n public onNavigatePrev(): void {\n return this.OnNavigatePrev();\n }\n\n public OnNavigateNext(): void {\n this.NavigateRow.emit('next');\n }\n\n /** @deprecated Use {@link OnNavigateNext}. */\n public onNavigateNext(): void {\n return this.OnNavigateNext();\n }\n\n public ToggleFieldExpand(field: DetailField): void {\n field.isExpanded = !field.isExpanded;\n this.cdr.markForCheck();\n }\n\n /** @deprecated Use {@link ToggleFieldExpand}. */\n public toggleFieldExpand(field: DetailField): void {\n return this.ToggleFieldExpand(field);\n }\n\n public CopyValue(field: DetailField): void {\n const textToCopy = field.value != null ? String(field.value) : '';\n navigator.clipboard.writeText(textToCopy);\n }\n\n /** @deprecated Use {@link CopyValue}. */\n public copyValue(field: DetailField): void {\n return this.CopyValue(field);\n }\n\n public CopyRowAsJson(): void {\n if (this._rowData) {\n const json = JSON.stringify(this._rowData, null, 2);\n navigator.clipboard.writeText(json);\n }\n }\n\n /** @deprecated Use {@link CopyRowAsJson}. */\n public copyRowAsJson(): void {\n return this.CopyRowAsJson();\n }\n\n public IsJson(value: string): boolean {\n if (!value || typeof value !== 'string') return false;\n const trimmed = value.trim();\n return (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'));\n }\n\n /** @deprecated Use {@link IsJson}. */\n public isJson(value: string): boolean {\n return this.IsJson(value);\n }\n\n public FormatJson(value: string): string {\n try {\n return JSON.stringify(JSON.parse(value), null, 2);\n } catch {\n return value;\n }\n }\n\n /** @deprecated Use {@link FormatJson}. */\n public formatJson(value: string): string {\n return this.FormatJson(value);\n }\n\n // ========================================\n // Resize Handling\n // ========================================\n\n public OnResizeStart(event: MouseEvent): void {\n event.preventDefault();\n this.IsResizing = true;\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n }\n\n /** @deprecated Use {@link OnResizeStart}. */\n public onResizeStart(event: MouseEvent): void {\n return this.OnResizeStart(event);\n }\n\n @HostListener('document:mousemove', ['$event'])\n onMouseMove(event: MouseEvent): void {\n if (!this.IsResizing) return;\n\n const containerRect = this.elementRef.nativeElement.parentElement?.getBoundingClientRect();\n if (!containerRect) return;\n\n const newWidth = containerRect.right - event.clientX;\n this.PanelWidth = Math.min(Math.max(newWidth, this.minWidth), this.maxWidth);\n this.cdr.markForCheck();\n }\n\n @HostListener('document:mouseup')\n onMouseUp(): void {\n if (this.IsResizing) {\n this.IsResizing = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n this.widthPersistSubject.next(this.PanelWidth);\n }\n }\n\n // ========================================\n // Persistence\n // ========================================\n\n private loadPersistedWidth(): void {\n try {\n const savedWidth = UserInfoEngine.Instance.GetSetting(PANEL_WIDTH_SETTING_KEY);\n if (savedWidth) {\n const width = parseInt(savedWidth, 10);\n if (!isNaN(width) && width >= this.minWidth && width <= this.maxWidth) {\n this.PanelWidth = width;\n }\n }\n } catch (error) {\n console.error('[query-row-detail] Failed to load persisted width:', error);\n }\n }\n\n private async persistPanelWidth(width: number): Promise<void> {\n try {\n await UserInfoEngine.Instance.SetSetting(PANEL_WIDTH_SETTING_KEY, String(width));\n } catch (error) {\n console.error('[query-row-detail] Failed to persist panel width:', error);\n }\n }\n\n private loadHideEmptyFieldsPreference(): void {\n try {\n const saved = UserInfoEngine.Instance.GetSetting(HIDE_EMPTY_FIELDS_KEY);\n if (saved !== undefined) {\n this.HideEmptyFields = saved === 'true';\n }\n } catch (error) {\n console.error('[query-row-detail] Failed to load hide empty fields preference:', error);\n }\n }\n\n private async persistHideEmptyFieldsPreference(): Promise<void> {\n try {\n await UserInfoEngine.Instance.SetSetting(HIDE_EMPTY_FIELDS_KEY, String(this.HideEmptyFields));\n } catch (error) {\n console.error('[query-row-detail] Failed to persist hide empty fields preference:', error);\n }\n }\n\n public ToggleHideEmptyFields(): void {\n this.HideEmptyFields = !this.HideEmptyFields;\n this.persistHideEmptyFieldsPreference();\n this.cdr.markForCheck();\n }\n\n /** @deprecated Use {@link ToggleHideEmptyFields}. */\n public toggleHideEmptyFields(): void {\n return this.ToggleHideEmptyFields();\n }\n\n /**\n * Returns visible fields based on HideEmptyFields setting\n */\n public GetVisibleFields(fields: DetailField[]): DetailField[] {\n if (!this.HideEmptyFields) {\n return fields;\n }\n return fields.filter(f => f.value !== null && f.value !== undefined && f.value !== '');\n }\n\n /** @deprecated Use {@link GetVisibleFields}. */\n public getVisibleFields(fields: DetailField[]): DetailField[] {\n return this.GetVisibleFields(fields);\n }\n\n /**\n * Returns count of empty fields for display\n */\n public GetEmptyFieldCount(fields: DetailField[]): number {\n return fields.filter(f => f.value === null || f.value === undefined || f.value === '').length;\n }\n\n /** @deprecated Use {@link GetEmptyFieldCount}. */\n public getEmptyFieldCount(fields: DetailField[]): number {\n return this.GetEmptyFieldCount(fields);\n }\n\n // ========================================\n // Keyboard Navigation\n // ========================================\n\n @HostListener('document:keydown', ['$event'])\n onKeyDown(event: KeyboardEvent): void {\n if (!this.Visible) return;\n\n if (event.key === 'Escape') {\n this.OnClose();\n } else if (event.key === 'ArrowUp' || event.key === 'k') {\n if (this.RowIndex > 0) {\n this.OnNavigatePrev();\n }\n } else if (event.key === 'ArrowDown' || event.key === 'j') {\n if (this.RowIndex < this.TotalRows - 1) {\n this.OnNavigateNext();\n }\n }\n }\n}\n","<!-- Row Detail Slide-in Panel -->\n@if (Visible) {\n <div class=\"row-detail-panel\"\n @slideIn\n [style.width.px]=\"PanelWidth\">\n <!-- Resize handle -->\n <div class=\"resize-handle\"\n (mousedown)=\"onResizeStart($event)\"\n [class.resizing]=\"IsResizing\">\n </div>\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"header-left\">\n <i class=\"fa-solid fa-table-cells-large header-icon\"></i>\n <h3 class=\"panel-title\">Row Details</h3>\n </div>\n <div class=\"header-right\">\n <!-- Row navigation -->\n @if (TotalRows > 1) {\n <div class=\"row-nav\">\n <button class=\"nav-btn\"\n [disabled]=\"RowIndex === 0\"\n (click)=\"onNavigatePrev()\"\n title=\"Previous row (↑ or K)\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <span class=\"row-indicator\">{{ RowIndex + 1 }} / {{ TotalRows }}</span>\n <button class=\"nav-btn\"\n [disabled]=\"RowIndex >= TotalRows - 1\"\n (click)=\"onNavigateNext()\"\n title=\"Next row (↓ or J)\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n }\n <!-- Toggle empty fields -->\n <button class=\"action-btn\"\n (click)=\"toggleHideEmptyFields()\"\n [class.active]=\"HideEmptyFields\"\n [title]=\"HideEmptyFields ? 'Show empty fields' : 'Hide empty fields'\">\n <i class=\"fa-solid\" [class.fa-eye]=\"!HideEmptyFields\" [class.fa-eye-slash]=\"HideEmptyFields\"></i>\n </button>\n <!-- Copy JSON button -->\n <button class=\"action-btn\" (click)=\"copyRowAsJson()\" title=\"Copy row as JSON\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <!-- Close button -->\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close (Esc)\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Primary Keys Section -->\n @if (getVisibleFields(PrimaryKeyFields).length > 0) {\n <div class=\"field-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-key section-icon pk-icon\"></i>\n Primary Key\n </h4>\n <div class=\"field-list\">\n @for (field of getVisibleFields(PrimaryKeyFields); track field) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n <button class=\"copy-btn\" (click)=\"copyValue(field)\" title=\"Copy value\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n <div class=\"field-value\"\n [class.clickable]=\"field.targetEntityName\"\n (click)=\"field.targetEntityName && onEntityLinkClick(field)\">\n @if (field.targetEntityIcon) {\n <i\n [class]=\"field.targetEntityIcon\"\n class=\"entity-icon\"></i>\n }\n <span class=\"value-text monospace\">{{ field.formattedValue }}</span>\n @if (field.targetEntityName) {\n <i\n class=\"fa-solid fa-arrow-up-right-from-square link-icon\"></i>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n <!-- Foreign Keys Section -->\n @if (getVisibleFields(ForeignKeyFields).length > 0) {\n <div class=\"field-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-link section-icon fk-icon\"></i>\n Related Records\n </h4>\n <div class=\"field-list\">\n @for (field of getVisibleFields(ForeignKeyFields); track field) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n @if (field.targetEntityName) {\n <span class=\"target-entity\">\n <i class=\"fa-solid fa-arrow-right\"></i>\n {{ field.targetEntityName }}\n </span>\n }\n <button class=\"copy-btn\" (click)=\"copyValue(field)\" title=\"Copy value\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n @if (field.value != null) {\n <div class=\"field-value clickable\"\n (click)=\"onEntityLinkClick(field)\">\n @if (field.targetEntityIcon) {\n <i\n [class]=\"field.targetEntityIcon\"\n class=\"entity-icon\"></i>\n }\n <span class=\"value-text monospace\">{{ field.formattedValue }}</span>\n <i class=\"fa-solid fa-arrow-up-right-from-square link-icon\"></i>\n </div>\n }\n @if (field.value == null) {\n <div class=\"field-value empty\">\n <span class=\"value-text\">(empty)</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n <!-- Regular Fields Section -->\n @if (getVisibleFields(RegularFields).length > 0) {\n <div class=\"field-section\">\n <h4 class=\"section-title\">\n <i class=\"fa-solid fa-list section-icon\"></i>\n Fields\n @if (HideEmptyFields && getEmptyFieldCount(RegularFields) > 0) {\n <span class=\"hidden-count\">\n ({{ getEmptyFieldCount(RegularFields) }} empty hidden)\n </span>\n }\n </h4>\n <div class=\"field-list\">\n @for (field of getVisibleFields(RegularFields); track field) {\n <div class=\"field-item\">\n <div class=\"field-header\">\n <span class=\"field-name\">{{ field.displayName }}</span>\n <span class=\"field-type\">{{ field.sqlType }}</span>\n <button class=\"copy-btn\" (click)=\"copyValue(field)\" title=\"Copy value\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n <!-- JSON value -->\n @if (isJson(field.formattedValue)) {\n <div class=\"field-value json-value\"\n [class.expanded]=\"field.isExpanded\">\n <pre class=\"json-content\">{{ formatJson(field.formattedValue) }}</pre>\n <button class=\"expand-btn\" (click)=\"toggleFieldExpand(field)\">\n {{ field.isExpanded ? 'Collapse' : 'Expand' }}\n </button>\n </div>\n }\n <!-- Long text value -->\n @if (!isJson(field.formattedValue) && field.isLongText) {\n <div class=\"field-value long-text\"\n [class.expanded]=\"field.isExpanded\">\n <span class=\"value-text\">{{ field.formattedValue }}</span>\n <button class=\"expand-btn\" (click)=\"toggleFieldExpand(field)\">\n {{ field.isExpanded ? 'Show less' : 'Show more' }}\n </button>\n </div>\n }\n <!-- Boolean value -->\n @if (field.sqlType.toLowerCase() === 'bit' && !isJson(field.formattedValue)) {\n <div class=\"field-value boolean-value\"\n >\n <i [class]=\"field.value ? 'fa-solid fa-check-circle bool-true' : 'fa-solid fa-times-circle bool-false'\"></i>\n <span class=\"value-text\">{{ field.formattedValue }}</span>\n </div>\n }\n <!-- Empty value -->\n @if (field.value == null && !isJson(field.formattedValue)) {\n <div class=\"field-value empty\"\n >\n <span class=\"value-text\">(empty)</span>\n </div>\n }\n <!-- Regular value -->\n @if (field.value != null && !isJson(field.formattedValue) && !field.isLongText && field.sqlType.toLowerCase() !== 'bit') {\n <div class=\"field-value\"\n >\n <span class=\"value-text\"\n [class.monospace]=\"field.sqlType.toLowerCase().includes('uniqueidentifier') || field.name.toLowerCase().includes('id')\">\n {{ field.formattedValue }}\n </span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n<!-- Backdrop -->\n@if (Visible) {\n <div class=\"panel-backdrop\"\n (click)=\"onClose()\">\n </div>\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import { QueryEngine } from '@memberjunction/core-entities';
|
|
|
6
6
|
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
7
7
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
8
8
|
import { QueryDataGridComponent } from '../query-data-grid/query-data-grid.component';
|
|
9
|
-
import {
|
|
9
|
+
import { GetQueryGridStateKey, GetQueryParamsKey } from '../query-data-grid/models/query-grid-types';
|
|
10
10
|
import * as i0 from "@angular/core";
|
|
11
11
|
import * as i1 from "../query-data-grid/query-data-grid.component";
|
|
12
12
|
import * as i2 from "../query-parameter-form/query-parameter-form.component";
|
|
@@ -334,7 +334,7 @@ export class QueryViewerComponent extends BaseAngularComponent {
|
|
|
334
334
|
try {
|
|
335
335
|
// Load grid state
|
|
336
336
|
if (this.PersistState) {
|
|
337
|
-
const gridStateKey =
|
|
337
|
+
const gridStateKey = GetQueryGridStateKey(this._queryId);
|
|
338
338
|
const gridStateSetting = await this.getUserSetting(gridStateKey);
|
|
339
339
|
if (gridStateSetting) {
|
|
340
340
|
this.SavedGridState = JSON.parse(gridStateSetting);
|
|
@@ -342,7 +342,7 @@ export class QueryViewerComponent extends BaseAngularComponent {
|
|
|
342
342
|
}
|
|
343
343
|
// Load saved parameters
|
|
344
344
|
if (this.PersistParameters) {
|
|
345
|
-
const paramsKey =
|
|
345
|
+
const paramsKey = GetQueryParamsKey(this._queryId);
|
|
346
346
|
const paramsSetting = await this.getUserSetting(paramsKey);
|
|
347
347
|
if (paramsSetting) {
|
|
348
348
|
this.SavedParams = JSON.parse(paramsSetting);
|
|
@@ -357,7 +357,7 @@ export class QueryViewerComponent extends BaseAngularComponent {
|
|
|
357
357
|
if (!this._queryId || !this.PersistState)
|
|
358
358
|
return;
|
|
359
359
|
try {
|
|
360
|
-
const key =
|
|
360
|
+
const key = GetQueryGridStateKey(this._queryId);
|
|
361
361
|
await this.setUserSetting(key, JSON.stringify(state));
|
|
362
362
|
}
|
|
363
363
|
catch (error) {
|
|
@@ -368,7 +368,7 @@ export class QueryViewerComponent extends BaseAngularComponent {
|
|
|
368
368
|
if (!this._queryId || !this.PersistParameters)
|
|
369
369
|
return;
|
|
370
370
|
try {
|
|
371
|
-
const key =
|
|
371
|
+
const key = GetQueryParamsKey(this._queryId);
|
|
372
372
|
await this.setUserSetting(key, JSON.stringify(params));
|
|
373
373
|
}
|
|
374
374
|
catch (error) {
|