@memberjunction/ng-artifacts 5.10.1 → 5.12.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.
Files changed (28) hide show
  1. package/dist/lib/artifacts.module.d.ts +2 -1
  2. package/dist/lib/artifacts.module.d.ts.map +1 -1
  3. package/dist/lib/artifacts.module.js +7 -3
  4. package/dist/lib/artifacts.module.js.map +1 -1
  5. package/dist/lib/components/artifact-message-card.component.js +2 -2
  6. package/dist/lib/components/artifact-message-card.component.js.map +1 -1
  7. package/dist/lib/components/artifact-viewer-panel.component.js +2 -2
  8. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +2 -0
  9. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
  10. package/dist/lib/components/plugins/component-artifact-viewer.component.js +43 -14
  11. package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
  12. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts +75 -0
  13. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts.map +1 -0
  14. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +569 -0
  15. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -0
  16. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts +10 -0
  17. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
  18. package/dist/lib/components/plugins/data-artifact-viewer.component.js +44 -11
  19. package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
  20. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js +2 -2
  21. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts.map +1 -1
  22. package/dist/lib/components/plugins/json-artifact-viewer.component.js +3 -3
  23. package/dist/lib/components/plugins/json-artifact-viewer.component.js.map +1 -1
  24. package/dist/public-api.d.ts +1 -0
  25. package/dist/public-api.d.ts.map +1 -1
  26. package/dist/public-api.js +1 -0
  27. package/dist/public-api.js.map +1 -1
  28. package/package.json +15 -14
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-feedback-panel.component.js","sourceRoot":"","sources":["../../../../../src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.ts","../../../../../src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnDestroy, ChangeDetectorRef, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { Metadata } from '@memberjunction/core';\nimport { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n/**\n * Flattened tree item for rendering the component hierarchy\n */\ninterface TreeItem {\n spec: ComponentSpec;\n depth: number;\n hasChildren: boolean;\n}\n\n/**\n * Component feedback panel that displays component hierarchy tree\n * and allows users to select components and provide star ratings with comments.\n * Registry-agnostic: works with any component registry (Skip, MJ Central, etc.)\n */\n@Component({\n selector: 'mj-component-feedback-panel',\n standalone: true,\n imports: [CommonModule, FormsModule],\n templateUrl: './component-feedback-panel.component.html',\n styleUrls: ['./component-feedback-panel.component.css']\n})\nexport class ComponentFeedbackPanelComponent implements OnDestroy {\n @Input() ComponentSpec: ComponentSpec | null = null;\n @Input() ReactContainerElement: HTMLElement | null = null;\n @Input() ConversationId: string | null = null;\n @Input() ConversationDetailId: string | null = null;\n\n @Output() Closed = new EventEmitter<void>();\n\n // Feedback form state\n public SelectedSpec: ComponentSpec | null = null;\n public StarRating = 0;\n public HoverRating = 0;\n public FeedbackComments = '';\n public IsSubmitting = false;\n public SubmitSuccess = false;\n public SubmitError = '';\n\n // Tree state\n public ExpandedNodes = new Set<string>();\n\n // Highlight overlays\n private highlightOverlay: HTMLElement | null = null;\n private hoverOverlay: HTMLElement | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private containerClickHandler: ((e: MouseEvent) => void) | null = null;\n\n private cdr = inject(ChangeDetectorRef);\n\n // --- Tree Methods ---\n\n GetTreeItems(): TreeItem[] {\n if (!this.ComponentSpec) return [];\n if (!this.ExpandedNodes.has(this.ComponentSpec.name)) {\n this.ExpandedNodes.add(this.ComponentSpec.name);\n }\n return this.buildTree(this.ComponentSpec, 0);\n }\n\n private buildTree(spec: ComponentSpec, depth: number): TreeItem[] {\n const items: TreeItem[] = [{\n spec,\n depth,\n hasChildren: !!(spec.dependencies && spec.dependencies.length > 0)\n }];\n if (this.ExpandedNodes.has(spec.name) && spec.dependencies) {\n for (const child of spec.dependencies) {\n items.push(...this.buildTree(child, depth + 1));\n }\n }\n return items;\n }\n\n ToggleNode(spec: ComponentSpec, event: MouseEvent): void {\n event.stopPropagation();\n if (this.ExpandedNodes.has(spec.name)) {\n this.ExpandedNodes.delete(spec.name);\n } else {\n this.ExpandedNodes.add(spec.name);\n }\n }\n\n IsNodeExpanded(spec: ComponentSpec): boolean {\n return this.ExpandedNodes.has(spec.name);\n }\n\n SelectComponent(spec: ComponentSpec): void {\n this.SelectedSpec = spec;\n this.ResetForm();\n this.HighlightComponent(spec.name);\n }\n\n IsSelected(spec: ComponentSpec): boolean {\n return this.SelectedSpec?.name === spec.name;\n }\n\n GetIndentation(depth: number): string {\n return `${depth * 20}px`;\n }\n\n // --- Star Rating ---\n\n SetRating(stars: number): void {\n this.StarRating = stars;\n }\n\n SetHoverRating(stars: number): void {\n this.HoverRating = stars;\n }\n\n ClearHoverRating(): void {\n this.HoverRating = 0;\n }\n\n GetDisplayRating(): number {\n return this.HoverRating || this.StarRating;\n }\n\n IsStarFilled(index: number): boolean {\n return index <= this.GetDisplayRating();\n }\n\n // --- Form ---\n\n ResetForm(): void {\n this.StarRating = 0;\n this.HoverRating = 0;\n this.FeedbackComments = '';\n this.SubmitSuccess = false;\n this.SubmitError = '';\n }\n\n CanSubmit(): boolean {\n return !!this.SelectedSpec && this.StarRating > 0 && !this.IsSubmitting;\n }\n\n async SubmitFeedback(): Promise<void> {\n if (!this.CanSubmit() || !this.SelectedSpec) return;\n\n this.IsSubmitting = true;\n this.SubmitError = '';\n this.SubmitSuccess = false;\n this.cdr.detectChanges();\n\n try {\n // Dynamic import to avoid adding graphql-dataprovider as a package dependency.\n // At runtime in the browser, Metadata.Provider is always a GraphQLDataProvider.\n const { GraphQLComponentRegistryClient } = await import('@memberjunction/graphql-dataprovider');\n const provider = Metadata.Provider;\n const client = new GraphQLComponentRegistryClient(provider as ConstructorParameters<typeof GraphQLComponentRegistryClient>[0]);\n\n const response = await client.SendComponentFeedback({\n componentName: this.SelectedSpec.name,\n componentNamespace: this.SelectedSpec.namespace || this.SelectedSpec.registry || '',\n componentVersion: this.SelectedSpec.version,\n registryName: this.SelectedSpec.registry,\n rating: this.StarRating * 20, // 0-5 -> 0-100\n comments: this.FeedbackComments.trim() || undefined,\n conversationID: this.ConversationId || undefined,\n conversationDetailID: this.ConversationDetailId || undefined\n });\n\n if (response.success) {\n this.SubmitSuccess = true;\n setTimeout(() => {\n this.ResetForm();\n this.cdr.detectChanges();\n }, 2000);\n } else {\n this.SubmitError = response.error || 'Failed to submit feedback.';\n }\n } catch (error) {\n this.SubmitError = 'Failed to submit feedback. Please try again.';\n console.error('Error submitting component feedback:', error);\n } finally {\n this.IsSubmitting = false;\n this.cdr.detectChanges();\n }\n }\n\n // --- Hover Highlight (light preview on tree hover) ---\n\n HoverTreeItem(spec: ComponentSpec): void {\n if (!this.ReactContainerElement || this.IsSelected(spec)) return;\n this.showHoverOverlay(spec.name);\n }\n\n ClearTreeItemHover(): void {\n this.removeHoverOverlay();\n }\n\n private showHoverOverlay(componentName: string): void {\n if (!this.ReactContainerElement) return;\n\n const targetEl = this.ReactContainerElement.querySelector(\n `[data-mj-component=\"${componentName}\"]`\n );\n if (!targetEl) {\n this.removeHoverOverlay();\n return;\n }\n\n this.ensureContainerPositioned();\n\n if (!this.hoverOverlay) {\n this.hoverOverlay = document.createElement('div');\n this.ReactContainerElement.appendChild(this.hoverOverlay);\n }\n\n this.positionOverlay(this.hoverOverlay, targetEl);\n this.hoverOverlay.style.border = '2px dashed var(--mj-brand-primary, #3B82F6)';\n this.hoverOverlay.style.background = 'color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 5%, transparent)';\n }\n\n private removeHoverOverlay(): void {\n if (this.hoverOverlay?.parentNode) {\n this.hoverOverlay.parentNode.removeChild(this.hoverOverlay);\n }\n this.hoverOverlay = null;\n }\n\n // --- Region Highlighting (solid selection) ---\n\n private HighlightComponent(componentName: string): void {\n if (!this.ReactContainerElement) {\n this.ClearHighlight();\n return;\n }\n\n const targetEl = this.ReactContainerElement.querySelector(\n `[data-mj-component=\"${componentName}\"]`\n );\n if (!targetEl) {\n this.ClearHighlight();\n return;\n }\n\n this.ensureContainerPositioned();\n\n if (!this.highlightOverlay) {\n this.highlightOverlay = document.createElement('div');\n this.ReactContainerElement.appendChild(this.highlightOverlay);\n }\n\n this.positionOverlay(this.highlightOverlay, targetEl);\n this.highlightOverlay.style.border = '2px solid var(--mj-brand-primary, #3B82F6)';\n this.highlightOverlay.style.background = 'color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 10%, transparent)';\n\n // Watch for resize/layout changes\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => {\n if (this.highlightOverlay) {\n this.positionOverlay(this.highlightOverlay, targetEl);\n }\n });\n this.resizeObserver.observe(targetEl);\n this.resizeObserver.observe(this.ReactContainerElement);\n\n // Set up bidirectional click selection on container\n this.installContainerClickListener();\n }\n\n private ensureContainerPositioned(): void {\n if (!this.ReactContainerElement) return;\n const containerStyle = getComputedStyle(this.ReactContainerElement);\n if (containerStyle.position === 'static') {\n this.ReactContainerElement.style.position = 'relative';\n }\n }\n\n /**\n * Gets the effective bounding rect for a component marker element.\n * display:contents elements return zero-size rects, so we compute\n * the union bounding box of their children instead.\n */\n private getEffectiveRect(el: Element): DOMRect {\n const rect = el.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) return rect;\n\n // display:contents wrapper — union the bounding rects of all children\n const children = el.children;\n if (children.length === 0) return rect;\n\n let top = Infinity, left = Infinity, bottom = -Infinity, right = -Infinity;\n for (let i = 0; i < children.length; i++) {\n const childRect = children[i].getBoundingClientRect();\n if (childRect.width === 0 && childRect.height === 0) continue;\n top = Math.min(top, childRect.top);\n left = Math.min(left, childRect.left);\n bottom = Math.max(bottom, childRect.bottom);\n right = Math.max(right, childRect.right);\n }\n\n if (top === Infinity) return rect; // no visible children\n return new DOMRect(left, top, right - left, bottom - top);\n }\n\n private positionOverlay(overlay: HTMLElement, targetEl: Element): void {\n if (!this.ReactContainerElement) return;\n\n const targetRect = this.getEffectiveRect(targetEl);\n const containerRect = this.ReactContainerElement.getBoundingClientRect();\n\n overlay.style.position = 'absolute';\n overlay.style.top = `${targetRect.top - containerRect.top + this.ReactContainerElement.scrollTop}px`;\n overlay.style.left = `${targetRect.left - containerRect.left + this.ReactContainerElement.scrollLeft}px`;\n overlay.style.width = `${targetRect.width}px`;\n overlay.style.height = `${targetRect.height}px`;\n overlay.style.pointerEvents = 'none';\n overlay.style.zIndex = '10';\n overlay.style.borderRadius = '4px';\n overlay.style.transition = 'all 0.2s ease';\n }\n\n // --- Bidirectional click: clicking a component region selects it in the tree ---\n\n private installContainerClickListener(): void {\n if (this.containerClickHandler || !this.ReactContainerElement) return;\n\n this.containerClickHandler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n\n // Walk up from click target to find nearest [data-mj-component]\n const componentEl = target.closest('[data-mj-component]');\n if (!componentEl) return;\n\n const componentName = componentEl.getAttribute('data-mj-component');\n if (!componentName) return;\n\n // Find matching spec in the tree\n const matchingSpec = this.findSpecByName(componentName);\n if (matchingSpec && matchingSpec.name !== this.SelectedSpec?.name) {\n this.SelectComponent(matchingSpec);\n this.cdr.detectChanges();\n }\n };\n\n // Use capture phase so we observe the click without interfering with component handlers\n this.ReactContainerElement.addEventListener('click', this.containerClickHandler, true);\n }\n\n private removeContainerClickListener(): void {\n if (this.containerClickHandler && this.ReactContainerElement) {\n this.ReactContainerElement.removeEventListener('click', this.containerClickHandler, true);\n }\n this.containerClickHandler = null;\n }\n\n private findSpecByName(name: string): ComponentSpec | null {\n if (!this.ComponentSpec) return null;\n return this.walkSpecTree(this.ComponentSpec, name);\n }\n\n private walkSpecTree(spec: ComponentSpec, name: string): ComponentSpec | null {\n if (spec.name === name) return spec;\n if (spec.dependencies) {\n for (const child of spec.dependencies) {\n const found = this.walkSpecTree(child, name);\n if (found) return found;\n }\n }\n return null;\n }\n\n private ClearHighlight(): void {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n if (this.highlightOverlay?.parentNode) {\n this.highlightOverlay.parentNode.removeChild(this.highlightOverlay);\n }\n this.highlightOverlay = null;\n this.removeHoverOverlay();\n this.removeContainerClickListener();\n }\n\n ClosePanel(): void {\n this.ClearHighlight();\n this.Closed.emit();\n }\n\n ngOnDestroy(): void {\n this.ClearHighlight();\n }\n}\n","<div class=\"feedback-panel-overlay\" (click)=\"ClosePanel()\">\n <div class=\"feedback-panel\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n <span>Component Feedback</span>\n </div>\n <button class=\"close-button\" (click)=\"ClosePanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Component Tree Section -->\n <div class=\"tree-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <span>Select Component</span>\n </div>\n\n @if (ComponentSpec) {\n <div class=\"component-tree\">\n @for (item of GetTreeItems(); track item.spec.name) {\n <div\n class=\"tree-item\"\n [class.selected]=\"IsSelected(item.spec)\"\n [style.padding-left]=\"GetIndentation(item.depth)\"\n (click)=\"SelectComponent(item.spec)\"\n (mouseenter)=\"HoverTreeItem(item.spec)\"\n (mouseleave)=\"ClearTreeItemHover()\">\n\n @if (item.hasChildren) {\n <i\n class=\"tree-toggle fa-solid\"\n [class.fa-chevron-right]=\"!IsNodeExpanded(item.spec)\"\n [class.fa-chevron-down]=\"IsNodeExpanded(item.spec)\"\n (click)=\"ToggleNode(item.spec, $event)\">\n </i>\n } @else {\n <span class=\"tree-spacer\"></span>\n }\n\n <i class=\"fa-solid fa-cube component-icon\"></i>\n\n <div class=\"component-info\">\n <span class=\"component-name\">{{ item.spec.title || item.spec.name }}</span>\n @if (item.spec.location === 'registry') {\n <span class=\"component-badge registry\">Registry</span>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No component hierarchy available</span>\n </div>\n }\n </div>\n\n <!-- Feedback Form Section -->\n <div class=\"feedback-section\">\n @if (SelectedSpec) {\n <div class=\"selected-component-info\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star\"></i>\n <span>Rate: {{ SelectedSpec.title || SelectedSpec.name }}</span>\n </div>\n\n @if (SelectedSpec.description) {\n <p class=\"component-description\">{{ SelectedSpec.description }}</p>\n }\n\n <!-- Star Rating -->\n <div class=\"star-rating-container\">\n <label class=\"rating-label\">Your Rating</label>\n <div class=\"star-rating\">\n @for (star of [1, 2, 3, 4, 5]; track star) {\n <i\n class=\"star\"\n [class.fa-solid]=\"IsStarFilled(star)\"\n [class.fa-regular]=\"!IsStarFilled(star)\"\n [class.fa-star]=\"true\"\n (click)=\"SetRating(star)\"\n (mouseenter)=\"SetHoverRating(star)\"\n (mouseleave)=\"ClearHoverRating()\">\n </i>\n }\n </div>\n @if (StarRating > 0) {\n <span class=\"rating-text\">{{ StarRating }} out of 5 stars</span>\n } @else {\n <span class=\"rating-text placeholder\">Click to rate</span>\n }\n </div>\n\n <!-- Comment Input -->\n <div class=\"comment-container\">\n <label class=\"comment-label\">\n Comments\n <span class=\"optional-label\">(optional)</span>\n </label>\n <textarea\n class=\"comment-input\"\n [(ngModel)]=\"FeedbackComments\"\n placeholder=\"Share your thoughts about this component...\"\n rows=\"4\"\n maxlength=\"1000\">\n </textarea>\n @if (FeedbackComments.length > 0) {\n <span class=\"char-count\">{{ FeedbackComments.length }}/1000</span>\n }\n </div>\n\n <!-- Submit Button -->\n <div class=\"submit-container\">\n <button\n class=\"submit-button\"\n [disabled]=\"!CanSubmit()\"\n (click)=\"SubmitFeedback()\">\n @if (IsSubmitting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Submitting...</span>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n <span>Submit Feedback</span>\n }\n </button>\n </div>\n\n <!-- Success/Error Messages -->\n @if (SubmitSuccess) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>Feedback submitted successfully!</span>\n </div>\n }\n @if (SubmitError) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n <span>{{ SubmitError }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"no-selection-message\">\n <i class=\"fa-solid fa-hand-pointer\"></i>\n <p>Select a component from the tree to provide feedback</p>\n </div>\n }\n </div>\n </div>\n </div>\n</div>\n"]}
@@ -1,6 +1,7 @@
1
1
  import { OnInit, ChangeDetectorRef, EventEmitter } from '@angular/core';
2
2
  import { CompositeKey } from '@memberjunction/core';
3
3
  import { QueryGridColumnConfig, QueryEntityLinkClickEvent } from '@memberjunction/ng-query-viewer';
4
+ import { PageChangeEvent } from '@memberjunction/ng-pagination';
4
5
  import { BaseArtifactViewerPluginComponent, ArtifactViewerTab, NavigationRequest } from '../base-artifact-viewer.component';
5
6
  import { SaveQueryResult } from './save-query-dialog.component';
6
7
  import * as i0 from "@angular/core";
@@ -89,6 +90,10 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
89
90
  ShowUpdateDropdown: boolean;
90
91
  IsSaving: boolean;
91
92
  SavingMessage: string;
93
+ /** Paging state — passed through to mj-query-data-grid's embedded pager */
94
+ PagerTotalRowCount: number;
95
+ PagerPageNumber: number;
96
+ PagerPageSize: number;
92
97
  /** Query sync state — drives the toolbar UI for saved query actions */
93
98
  QuerySyncState: QuerySyncState;
94
99
  /** Latest version number for this artifact (from cache) */
@@ -131,6 +136,11 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
131
136
  * Converts the grid's recordId string into a CompositeKey for the artifact viewer pipeline.
132
137
  */
133
138
  OnEntityLinkClick(event: QueryEntityLinkClickEvent): void;
139
+ /**
140
+ * Handle page change from the data grid's embedded pager.
141
+ * Re-executes the live SQL with the new page parameters.
142
+ */
143
+ OnPageChange(event: PageChangeEvent): Promise<void>;
134
144
  /**
135
145
  * Execute the SQL query via RunQuery and populate the grid.
136
146
  * Falls back to inline data on error.
@@ -1 +1 @@
1
- {"version":3,"file":"data-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/data-artifact-viewer.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/data-artifact-viewer.component.ts"],"names":[],"mappings":"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"}
@@ -191,14 +191,14 @@ function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_19_
191
191
  i0.ɵɵtext(5, "(Showing cached data)");
192
192
  i0.ɵɵelementEnd()();
193
193
  i0.ɵɵelementStart(6, "mj-query-data-grid", 45);
194
- i0.ɵɵlistener("EntityLinkClick", function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_19_Template_mj_query_data_grid_EntityLinkClick_6_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnEntityLinkClick($event)); });
194
+ i0.ɵɵlistener("EntityLinkClick", function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_19_Template_mj_query_data_grid_EntityLinkClick_6_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnEntityLinkClick($event)); })("PageChange", function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_19_Template_mj_query_data_grid_PageChange_6_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnPageChange($event)); });
195
195
  i0.ɵɵelementEnd();
196
196
  } if (rf & 2) {
197
197
  const ctx_r0 = i0.ɵɵnextContext(3);
198
198
  i0.ɵɵadvance(3);
199
199
  i0.ɵɵtextInterpolate(ctx_r0.ErrorMessage);
200
200
  i0.ɵɵadvance(3);
201
- i0.ɵɵproperty("ColumnConfigs", ctx_r0.GridColumnConfigs)("Data", ctx_r0.GridData)("ShowToolbar", false)("ShowRefresh", false)("PersistState", false)("SelectionMode", "none");
201
+ i0.ɵɵproperty("ColumnConfigs", ctx_r0.GridColumnConfigs)("Data", ctx_r0.GridData)("TotalRowCount", ctx_r0.PagerTotalRowCount)("PageNumber", ctx_r0.PagerPageNumber)("PageSize", ctx_r0.PagerPageSize)("ShowToolbar", false)("ShowRefresh", false)("PersistState", false)("SelectionMode", "none");
202
202
  } }
203
203
  function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_20_Template(rf, ctx) { if (rf & 1) {
204
204
  i0.ɵɵelementStart(0, "div", 1);
@@ -214,11 +214,11 @@ function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_20_
214
214
  function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_21_Template(rf, ctx) { if (rf & 1) {
215
215
  const _r10 = i0.ɵɵgetCurrentView();
216
216
  i0.ɵɵelementStart(0, "mj-query-data-grid", 45);
217
- i0.ɵɵlistener("EntityLinkClick", function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_21_Template_mj_query_data_grid_EntityLinkClick_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnEntityLinkClick($event)); });
217
+ i0.ɵɵlistener("EntityLinkClick", function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_21_Template_mj_query_data_grid_EntityLinkClick_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnEntityLinkClick($event)); })("PageChange", function DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_21_Template_mj_query_data_grid_PageChange_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnPageChange($event)); });
218
218
  i0.ɵɵelementEnd();
219
219
  } if (rf & 2) {
220
220
  const ctx_r0 = i0.ɵɵnextContext(3);
221
- i0.ɵɵproperty("ColumnConfigs", ctx_r0.GridColumnConfigs)("Data", ctx_r0.GridData)("ShowToolbar", false)("ShowRefresh", false)("PersistState", false)("SelectionMode", "none");
221
+ i0.ɵɵproperty("ColumnConfigs", ctx_r0.GridColumnConfigs)("Data", ctx_r0.GridData)("TotalRowCount", ctx_r0.PagerTotalRowCount)("PageNumber", ctx_r0.PagerPageNumber)("PageSize", ctx_r0.PagerPageSize)("ShowToolbar", false)("ShowRefresh", false)("PersistState", false)("SelectionMode", "none");
222
222
  } }
223
223
  function DataArtifactViewerComponent_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
224
224
  i0.ɵɵelementStart(0, "div", 4)(1, "div", 5);
@@ -236,7 +236,7 @@ function DataArtifactViewerComponent_Conditional_1_Conditional_0_Template(rf, ct
236
236
  i0.ɵɵelementEnd()();
237
237
  i0.ɵɵelementStart(16, "div", 13);
238
238
  i0.ɵɵconditionalCreate(17, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_17_Template, 2, 1, "div", 14);
239
- i0.ɵɵconditionalCreate(18, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_18_Template, 1, 0, "mj-loading", 15)(19, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_19_Template, 7, 7)(20, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_20_Template, 4, 1, "div", 1)(21, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_21_Template, 1, 6, "mj-query-data-grid", 16);
239
+ i0.ɵɵconditionalCreate(18, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_18_Template, 1, 0, "mj-loading", 15)(19, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_19_Template, 7, 10)(20, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_20_Template, 4, 1, "div", 1)(21, DataArtifactViewerComponent_Conditional_1_Conditional_0_Conditional_21_Template, 1, 9, "mj-query-data-grid", 16);
240
240
  i0.ɵɵelementEnd();
241
241
  } if (rf & 2) {
242
242
  let tmp_7_0;
@@ -340,6 +340,10 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
340
340
  ShowUpdateDropdown = false;
341
341
  IsSaving = false;
342
342
  SavingMessage = '';
343
+ /** Paging state — passed through to mj-query-data-grid's embedded pager */
344
+ PagerTotalRowCount = 0;
345
+ PagerPageNumber = 1;
346
+ PagerPageSize = 100;
343
347
  /** Query sync state — drives the toolbar UI for saved query actions */
344
348
  QuerySyncState = 'no-query-latest';
345
349
  /** Latest version number for this artifact (from cache) */
@@ -443,14 +447,28 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
443
447
  * Converts the grid's recordId string into a CompositeKey for the artifact viewer pipeline.
444
448
  */
445
449
  OnEntityLinkClick(event) {
450
+ const md = new Metadata();
451
+ const entity = md.Entities.find(e => e.Name === event.entityName);
452
+ const pkFieldName = entity?.FirstPrimaryKey?.Name ?? 'ID';
446
453
  const compositeKey = new CompositeKey([
447
- new KeyValuePair('ID', event.recordId)
454
+ new KeyValuePair(pkFieldName, event.recordId)
448
455
  ]);
449
456
  this.openEntityRecord.emit({
450
457
  entityName: event.entityName,
451
458
  compositeKey
452
459
  });
453
460
  }
461
+ /**
462
+ * Handle page change from the data grid's embedded pager.
463
+ * Re-executes the live SQL with the new page parameters.
464
+ */
465
+ async OnPageChange(event) {
466
+ if (!this.spec?.metadata?.sql)
467
+ return;
468
+ this.PagerPageNumber = event.PageNumber;
469
+ this.PagerPageSize = event.PageSize;
470
+ await this.LoadLiveData();
471
+ }
454
472
  /**
455
473
  * Execute the SQL query via RunQuery and populate the grid.
456
474
  * Falls back to inline data on error.
@@ -461,12 +479,27 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
461
479
  this.cdr.detectChanges();
462
480
  try {
463
481
  const rq = new RunQuery();
464
- const result = await rq.RunQuery({ SQL: this.spec.metadata.sql });
482
+ const startRow = (this.PagerPageNumber - 1) * this.PagerPageSize;
483
+ const result = await rq.RunQuery({
484
+ SQL: this.spec.metadata.sql,
485
+ StartRow: startRow,
486
+ MaxRows: this.PagerPageSize
487
+ });
465
488
  if (result.Success) {
466
489
  this.GridData = result.Results;
467
490
  this.liveRowCount = result.RowCount;
468
491
  this.liveExecutionTime = result.ExecutionTime;
469
492
  this.IsLive = true;
493
+ // Update pager state from result
494
+ if (result.TotalRowCount != null) {
495
+ this.PagerTotalRowCount = result.TotalRowCount;
496
+ }
497
+ if (result.PageNumber != null) {
498
+ this.PagerPageNumber = result.PageNumber;
499
+ }
500
+ if (result.PageSize != null) {
501
+ this.PagerPageSize = result.PageSize;
502
+ }
470
503
  }
471
504
  else {
472
505
  this.HandleQueryError(result.ErrorMessage || 'Query execution failed');
@@ -800,7 +833,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
800
833
  return tabs;
801
834
  }
802
835
  static ɵfac = function DataArtifactViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DataArtifactViewerComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
803
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DataArtifactViewerComponent, selectors: [["mj-data-artifact-viewer"]], outputs: { openEntityRecord: "openEntityRecord", navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 3, consts: [[1, "data-artifact-viewer", 3, "ngClass"], [1, "error-state"], [1, "empty-state"], [3, "QueryName", "QueryDescription", "SQL", "Plan"], [1, "data-toolbar"], [1, "data-title"], [1, "fas", "fa-table"], [1, "live-badge"], [1, "row-count"], [1, "exec-time"], [1, "data-actions"], ["title", "Refresh data", 1, "btn-icon", 3, "disabled"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save"], [1, "grid-container"], [1, "saving-overlay"], ["text", "Loading data..."], ["Height", "100%", 3, "ColumnConfigs", "Data", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], ["title", "Refresh data", 1, "btn-icon", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save", 3, "click"], [1, "fas", "fa-save"], [1, "query-badge", "query-badge-synced"], [1, "fas", "fa-check"], ["title", "Open saved query record", 1, "btn-icon", "btn-open", 3, "click"], [1, "fas", "fa-external-link-alt"], [1, "query-badge", "query-badge-outdated"], [1, "fas", "fa-circle-exclamation"], [1, "dropdown-wrapper"], ["title", "Update or save query", 1, "btn-icon", "btn-warning", 3, "click"], [1, "fas", "fa-caret-down"], [1, "query-dropdown"], [1, "query-dropdown", 3, "click"], [1, "query-dropdown-item", 3, "click"], [1, "fas", "fa-arrow-up-from-bracket", 2, "color", "#d97706"], [1, "dropdown-label"], [1, "dropdown-desc"], [1, "fas", "fa-plus", 2, "color", "#16a34a"], [1, "fas", "fa-external-link-alt", 2, "color", "#6c757d"], [1, "query-badge", "query-badge-muted"], [1, "fas", "fa-clock-rotate-left"], ["title", "Open saved query record", 1, "btn-icon", "btn-muted", 3, "click"], [3, "text"], [1, "error-banner"], [1, "fas", "fa-exclamation-triangle"], [1, "fallback-note"], ["Height", "100%", 3, "EntityLinkClick", "ColumnConfigs", "Data", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], [1, "fas", "fa-diagram-project"], [1, "plan-content"], [3, "data", "enableMermaid", "enableHighlight", "enableCollapsibleHeadings", "enableSmartypants"], [1, "fas", "fa-inbox"], [3, "Saved", "Cancelled", "QueryName", "QueryDescription", "SQL", "Plan"]], template: function DataArtifactViewerComponent_Template(rf, ctx) { if (rf & 1) {
836
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DataArtifactViewerComponent, selectors: [["mj-data-artifact-viewer"]], outputs: { openEntityRecord: "openEntityRecord", navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 3, consts: [[1, "data-artifact-viewer", 3, "ngClass"], [1, "error-state"], [1, "empty-state"], [3, "QueryName", "QueryDescription", "SQL", "Plan"], [1, "data-toolbar"], [1, "data-title"], [1, "fas", "fa-table"], [1, "live-badge"], [1, "row-count"], [1, "exec-time"], [1, "data-actions"], ["title", "Refresh data", 1, "btn-icon", 3, "disabled"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save"], [1, "grid-container"], [1, "saving-overlay"], ["text", "Loading data..."], ["Height", "100%", 3, "ColumnConfigs", "Data", "TotalRowCount", "PageNumber", "PageSize", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], ["title", "Refresh data", 1, "btn-icon", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save", 3, "click"], [1, "fas", "fa-save"], [1, "query-badge", "query-badge-synced"], [1, "fas", "fa-check"], ["title", "Open saved query record", 1, "btn-icon", "btn-open", 3, "click"], [1, "fas", "fa-external-link-alt"], [1, "query-badge", "query-badge-outdated"], [1, "fas", "fa-circle-exclamation"], [1, "dropdown-wrapper"], ["title", "Update or save query", 1, "btn-icon", "btn-warning", 3, "click"], [1, "fas", "fa-caret-down"], [1, "query-dropdown"], [1, "query-dropdown", 3, "click"], [1, "query-dropdown-item", 3, "click"], [1, "fas", "fa-arrow-up-from-bracket", 2, "color", "#d97706"], [1, "dropdown-label"], [1, "dropdown-desc"], [1, "fas", "fa-plus", 2, "color", "#16a34a"], [1, "fas", "fa-external-link-alt", 2, "color", "var(--mj-text-muted)"], [1, "query-badge", "query-badge-muted"], [1, "fas", "fa-clock-rotate-left"], ["title", "Open saved query record", 1, "btn-icon", "btn-muted", 3, "click"], [3, "text"], [1, "error-banner"], [1, "fas", "fa-exclamation-triangle"], [1, "fallback-note"], ["Height", "100%", 3, "EntityLinkClick", "PageChange", "ColumnConfigs", "Data", "TotalRowCount", "PageNumber", "PageSize", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], [1, "fas", "fa-diagram-project"], [1, "plan-content"], [3, "data", "enableMermaid", "enableHighlight", "enableCollapsibleHeadings", "enableSmartypants"], [1, "fas", "fa-inbox"], [3, "Saved", "Cancelled", "QueryName", "QueryDescription", "SQL", "Plan"]], template: function DataArtifactViewerComponent_Template(rf, ctx) { if (rf & 1) {
804
837
  i0.ɵɵelementStart(0, "div", 0);
805
838
  i0.ɵɵconditionalCreate(1, DataArtifactViewerComponent_Conditional_1_Template, 3, 1)(2, DataArtifactViewerComponent_Conditional_2_Template, 4, 1, "div", 1)(3, DataArtifactViewerComponent_Conditional_3_Template, 4, 0, "div", 2);
806
839
  i0.ɵɵconditionalCreate(4, DataArtifactViewerComponent_Conditional_4_Template, 1, 4, "mj-save-query-panel", 3);
@@ -811,7 +844,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
811
844
  i0.ɵɵconditional(ctx.spec ? 1 : ctx.HasError ? 2 : 3);
812
845
  i0.ɵɵadvance(3);
813
846
  i0.ɵɵconditional(ctx.ShowSaveDialog ? 4 : -1);
814
- } }, dependencies: [i1.NgClass, i2.MarkdownComponent, i3.QueryDataGridComponent, i4.LoadingComponent, i5.SaveQueryPanelComponent], styles: [".data-artifact-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.data-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n}\n\n.data-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: #333;\n}\n\n.data-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #6c757d;\n}\n\n.row-count[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: #e9ecef;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: #495057;\n}\n\n.exec-time[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: #d4edda;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: #155724;\n}\n\n.live-badge[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: #cce5ff;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n color: #004085;\n}\n\n.data-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n padding: 4px 10px;\n background: white;\n border: 1px solid #ced4da;\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: #495057;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: #e9ecef;\n border-color: #adb5bd;\n}\n\n.btn-icon[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-save[_ngcontent-%COMP%] {\n color: #16a34a;\n border-color: #86efac;\n}\n\n.btn-icon.btn-save[_ngcontent-%COMP%]:hover {\n background: #f0fdf4;\n border-color: #16a34a;\n}\n\n.btn-icon.btn-open[_ngcontent-%COMP%] {\n color: #2563eb;\n border-color: #93c5fd;\n}\n\n.btn-icon.btn-open[_ngcontent-%COMP%]:hover {\n background: #eff6ff;\n border-color: #2563eb;\n}\n\n.grid-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 200px;\n height: 500px;\n position: relative;\n}\n\n\n\n.saving-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n padding: 8px 12px;\n background: #fff3cd;\n border-bottom: 1px solid #ffc107;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #856404;\n}\n\n.fallback-note[_ngcontent-%COMP%] {\n font-style: italic;\n color: #6c757d;\n}\n\n.empty-state[_ngcontent-%COMP%], .error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #6c757d;\n text-align: center;\n gap: 12px;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], .error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: #dc3545;\n}\n\n.plan-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 16px;\n}\n\n\n\n.query-badge[_ngcontent-%COMP%] {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n\n.query-badge-synced[_ngcontent-%COMP%] {\n background: #d1fae5;\n color: #065f46;\n}\n\n.query-badge-outdated[_ngcontent-%COMP%] {\n background: #fff3cd;\n color: #856404;\n}\n\n.query-badge-muted[_ngcontent-%COMP%] {\n background: #f3f4f6;\n color: #9ca3af;\n}\n\n\n\n.dropdown-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.btn-icon.btn-warning[_ngcontent-%COMP%] {\n color: #d97706;\n border-color: #fcd34d;\n}\n\n.btn-icon.btn-warning[_ngcontent-%COMP%]:hover {\n background: #fffbeb;\n border-color: #d97706;\n}\n\n.btn-icon.btn-muted[_ngcontent-%COMP%] {\n color: #9ca3af;\n border-color: #e5e7eb;\n}\n\n\n\n.query-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n overflow: hidden;\n min-width: 280px;\n z-index: 100;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%] {\n padding: 10px 14px;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n cursor: pointer;\n border-bottom: 1px solid #f0f0f0;\n transition: background 0.1s;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%]:hover {\n background: #f8f9fa;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.dropdown-label[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.dropdown-desc[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #6c757d;\n margin-top: 2px;\n}"] });
847
+ } }, dependencies: [i1.NgClass, i2.MarkdownComponent, i3.QueryDataGridComponent, i4.LoadingComponent, i5.SaveQueryPanelComponent], styles: [".data-artifact-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.data-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.data-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.data-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.row-count[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.exec-time[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-status-success);\n}\n\n.live-badge[_ngcontent-%COMP%] {\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.data-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: var(--mj-text-secondary);\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-save[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-save[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-color: var(--mj-status-success);\n}\n\n.btn-icon.btn-open[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-open[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.grid-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 200px;\n height: 500px;\n position: relative;\n}\n\n\n\n.saving-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n}\n\n.error-banner[_ngcontent-%COMP%] {\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-bottom: 1px solid var(--mj-status-warning);\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-status-warning);\n}\n\n.fallback-note[_ngcontent-%COMP%] {\n font-style: italic;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%], .error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: var(--mj-text-muted);\n text-align: center;\n gap: 12px;\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], .error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.plan-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 16px;\n}\n\n\n\n.query-badge[_ngcontent-%COMP%] {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n\n.query-badge-synced[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.query-badge-outdated[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.query-badge-muted[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n\n\n.dropdown-wrapper[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.btn-icon.btn-warning[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-warning[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-color: var(--mj-status-warning);\n}\n\n.btn-icon.btn-muted[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled);\n border-color: var(--mj-border-default);\n}\n\n\n\n.query-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n min-width: 280px;\n z-index: 100;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%] {\n padding: 10px 14px;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n cursor: pointer;\n border-bottom: 1px solid var(--mj-border-default);\n transition: background 0.1s;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n}\n\n.query-dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.query-dropdown-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.dropdown-label[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.dropdown-desc[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}"] });
815
848
  };
816
849
  DataArtifactViewerComponent = __decorate([
817
850
  RegisterClass(BaseArtifactViewerPluginComponent, 'DataArtifactViewerPlugin')
@@ -819,11 +852,11 @@ DataArtifactViewerComponent = __decorate([
819
852
  export { DataArtifactViewerComponent };
820
853
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DataArtifactViewerComponent, [{
821
854
  type: Component,
822
- args: [{ standalone: false, selector: 'mj-data-artifact-viewer', template: "<div class=\"data-artifact-viewer\" [ngClass]=\"cssClass\">\n @if (spec) {\n @if (HasData || IsLoading) {\n <!-- Toolbar -->\n <div class=\"data-toolbar\">\n <div class=\"data-title\">\n <i class=\"fas fa-table\"></i>\n <span>{{ spec.title || 'Data Results' }}</span>\n @if (IsLive) {\n <span class=\"live-badge\">Live</span>\n }\n @if (DisplayRowCount != null) {\n <span class=\"row-count\">{{ DisplayRowCount }} rows</span>\n }\n @if (DisplayExecutionTime != null) {\n <span class=\"exec-time\">{{ DisplayExecutionTime }}ms</span>\n }\n </div>\n <div class=\"data-actions\">\n @if (IsLive) {\n <button class=\"btn-icon\" title=\"Refresh data\" (click)=\"OnRefresh()\" [disabled]=\"IsLoading\">\n <i class=\"fas fa-sync-alt\" [class.fa-spin]=\"IsLoading\"></i> Refresh\n </button>\n }\n\n @switch (QuerySyncState) {\n <!-- S1: No saved query, latest version \u2192 Save Query -->\n @case ('no-query-latest') {\n <button class=\"btn-icon btn-save\" title=\"Save as reusable query\"\n (click)=\"OnShowSaveDialog()\">\n <i class=\"fas fa-save\"></i> Save Query\n </button>\n }\n\n <!-- S2: SQL matches \u2192 green badge + Open -->\n @case ('synced') {\n <span class=\"query-badge query-badge-synced\">\n <i class=\"fas fa-check\"></i> Saved at v{{ SavedAtVersion }}\n </span>\n <button class=\"btn-icon btn-open\" title=\"Open saved query record\"\n (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S3: SQL differs, latest version \u2192 amber badge + dropdown -->\n @case ('outdated-latest') {\n <span class=\"query-badge query-badge-outdated\">\n <i class=\"fas fa-circle-exclamation\"></i> Saved at v{{ SavedAtVersion }}\n </span>\n <div class=\"dropdown-wrapper\">\n <button class=\"btn-icon btn-warning\" title=\"Update or save query\"\n (click)=\"OnToggleUpdateDropdown()\">\n <i class=\"fas fa-save\"></i> Update Query <i class=\"fas fa-caret-down\"></i>\n </button>\n @if (ShowUpdateDropdown) {\n <div class=\"query-dropdown\" (click)=\"$event.stopPropagation()\">\n <div class=\"query-dropdown-item\" (click)=\"OnUpdateExistingQuery()\">\n <i class=\"fas fa-arrow-up-from-bracket\" style=\"color:#d97706\"></i>\n <div>\n <div class=\"dropdown-label\">Update \"{{ SavedQueryDisplayName }}\"</div>\n <div class=\"dropdown-desc\">Replace saved query SQL with this version's SQL</div>\n </div>\n </div>\n <div class=\"query-dropdown-item\" (click)=\"OnSaveAsNewQuery()\">\n <i class=\"fas fa-plus\" style=\"color:#16a34a\"></i>\n <div>\n <div class=\"dropdown-label\">Save as New Query</div>\n <div class=\"dropdown-desc\">Create a new query, keep the original unchanged</div>\n </div>\n </div>\n <div class=\"query-dropdown-item\" (click)=\"OnOpenSavedQuery(); OnCloseDropdown()\">\n <i class=\"fas fa-external-link-alt\" style=\"color:#6c757d\"></i>\n <div>\n <div class=\"dropdown-label\">Open Saved Query</div>\n <div class=\"dropdown-desc\">View \"{{ SavedQueryDisplayName }}\" (saved at v{{ SavedAtVersion }})</div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- S4: Older version, query was updated ahead -->\n @case ('query-ahead') {\n <span class=\"query-badge query-badge-muted\">\n <i class=\"fas fa-clock-rotate-left\"></i> Query updated at v{{ SavedAtVersion }}\n </span>\n <button class=\"btn-icon btn-muted\" title=\"Open saved query record\"\n (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S5: Middle version, saved at older, not latest -->\n @case ('query-behind') {\n <span class=\"query-badge query-badge-muted\">\n <i class=\"fas fa-clock-rotate-left\"></i> Saved at v{{ SavedAtVersion }}\n </span>\n <button class=\"btn-icon btn-muted\" title=\"Open saved query record\"\n (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S6: No saved query, older version \u2192 no actions -->\n @case ('no-query-older') {\n <!-- No query actions available on older versions -->\n }\n }\n </div>\n </div>\n\n <!-- Grid -->\n <div class=\"grid-container\">\n <!-- Saving overlay -->\n @if (IsSaving) {\n <div class=\"saving-overlay\">\n <mj-loading [text]=\"SavingMessage\"></mj-loading>\n </div>\n }\n @if (IsLoading) {\n <mj-loading text=\"Loading data...\"></mj-loading>\n } @else if (HasError && HasData) {\n <div class=\"error-banner\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n <span class=\"fallback-note\">(Showing cached data)</span>\n </div>\n <mj-query-data-grid\n [ColumnConfigs]=\"GridColumnConfigs\"\n [Data]=\"GridData\"\n [ShowToolbar]=\"false\"\n [ShowRefresh]=\"false\"\n [PersistState]=\"false\"\n [SelectionMode]=\"'none'\"\n (EntityLinkClick)=\"OnEntityLinkClick($event)\"\n Height=\"100%\">\n </mj-query-data-grid>\n } @else if (HasError) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ ErrorMessage }}</p>\n </div>\n } @else {\n <mj-query-data-grid\n [ColumnConfigs]=\"GridColumnConfigs\"\n [Data]=\"GridData\"\n [ShowToolbar]=\"false\"\n [ShowRefresh]=\"false\"\n [PersistState]=\"false\"\n [SelectionMode]=\"'none'\"\n (EntityLinkClick)=\"OnEntityLinkClick($event)\"\n Height=\"100%\">\n </mj-query-data-grid>\n }\n </div>\n } @else if (spec.plan) {\n <!-- Plan-only view (no results yet) -->\n <div class=\"data-toolbar\">\n <div class=\"data-title\">\n <i class=\"fas fa-diagram-project\"></i>\n <span>{{ spec.title || 'Query Plan' }}</span>\n </div>\n </div>\n <div class=\"plan-content\">\n <mj-markdown\n [data]=\"spec.plan\"\n [enableMermaid]=\"true\"\n [enableHighlight]=\"true\"\n [enableCollapsibleHeadings]=\"false\"\n [enableSmartypants]=\"true\">\n </mj-markdown>\n </div>\n } @else {\n <!-- No data and no plan -->\n <div class=\"empty-state\">\n <i class=\"fas fa-inbox\"></i>\n <p>No data to display</p>\n </div>\n }\n } @else if (HasError) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ ErrorMessage }}</p>\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fas fa-inbox\"></i>\n <p>No data to display</p>\n </div>\n }\n\n <!-- Save Query Panel (slide-in) -->\n @if (ShowSaveDialog) {\n <mj-save-query-panel\n [QueryName]=\"spec?.title || 'Untitled Query'\"\n [QueryDescription]=\"''\"\n [SQL]=\"spec?.metadata?.sql || ''\"\n [Plan]=\"spec?.plan || ''\"\n (Saved)=\"OnQuerySaved($event)\"\n (Cancelled)=\"ShowSaveDialog = false\">\n </mj-save-query-panel>\n }\n</div>\n", styles: [".data-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.data-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n}\n\n.data-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: #333;\n}\n\n.data-title i {\n color: #6c757d;\n}\n\n.row-count {\n padding: 2px 8px;\n background: #e9ecef;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: #495057;\n}\n\n.exec-time {\n padding: 2px 8px;\n background: #d4edda;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: #155724;\n}\n\n.live-badge {\n padding: 2px 8px;\n background: #cce5ff;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n color: #004085;\n}\n\n.data-actions {\n display: flex;\n gap: 6px;\n}\n\n.btn-icon {\n padding: 4px 10px;\n background: white;\n border: 1px solid #ced4da;\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: #495057;\n}\n\n.btn-icon:hover {\n background: #e9ecef;\n border-color: #adb5bd;\n}\n\n.btn-icon:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-save {\n color: #16a34a;\n border-color: #86efac;\n}\n\n.btn-icon.btn-save:hover {\n background: #f0fdf4;\n border-color: #16a34a;\n}\n\n.btn-icon.btn-open {\n color: #2563eb;\n border-color: #93c5fd;\n}\n\n.btn-icon.btn-open:hover {\n background: #eff6ff;\n border-color: #2563eb;\n}\n\n.grid-container {\n flex: 1;\n overflow: hidden;\n min-height: 200px;\n height: 500px;\n position: relative;\n}\n\n/* Saving overlay \u2014 semi-transparent panel over the grid */\n.saving-overlay {\n position: absolute;\n inset: 0;\n background: rgba(255, 255, 255, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n}\n\n.error-banner {\n padding: 8px 12px;\n background: #fff3cd;\n border-bottom: 1px solid #ffc107;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #856404;\n}\n\n.fallback-note {\n font-style: italic;\n color: #6c757d;\n}\n\n.empty-state, .error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #6c757d;\n text-align: center;\n gap: 12px;\n}\n\n.empty-state i, .error-state i {\n font-size: 32px;\n}\n\n.error-state {\n color: #dc3545;\n}\n\n.plan-content {\n flex: 1;\n overflow: auto;\n padding: 16px;\n}\n\n/* Query sync badges */\n.query-badge {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n\n.query-badge-synced {\n background: #d1fae5;\n color: #065f46;\n}\n\n.query-badge-outdated {\n background: #fff3cd;\n color: #856404;\n}\n\n.query-badge-muted {\n background: #f3f4f6;\n color: #9ca3af;\n}\n\n/* Dropdown wrapper */\n.dropdown-wrapper {\n position: relative;\n}\n\n.btn-icon.btn-warning {\n color: #d97706;\n border-color: #fcd34d;\n}\n\n.btn-icon.btn-warning:hover {\n background: #fffbeb;\n border-color: #d97706;\n}\n\n.btn-icon.btn-muted {\n color: #9ca3af;\n border-color: #e5e7eb;\n}\n\n/* Query actions dropdown */\n.query-dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n overflow: hidden;\n min-width: 280px;\n z-index: 100;\n}\n\n.query-dropdown-item {\n padding: 10px 14px;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n cursor: pointer;\n border-bottom: 1px solid #f0f0f0;\n transition: background 0.1s;\n}\n\n.query-dropdown-item:last-child {\n border-bottom: none;\n}\n\n.query-dropdown-item:hover {\n background: #f8f9fa;\n}\n\n.query-dropdown-item i {\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.dropdown-label {\n font-weight: 500;\n}\n\n.dropdown-desc {\n font-size: 11px;\n color: #6c757d;\n margin-top: 2px;\n}\n"] }]
855
+ args: [{ standalone: false, selector: 'mj-data-artifact-viewer', template: "<div class=\"data-artifact-viewer\" [ngClass]=\"cssClass\">\n @if (spec) {\n @if (HasData || IsLoading) {\n <!-- Toolbar -->\n <div class=\"data-toolbar\">\n <div class=\"data-title\">\n <i class=\"fas fa-table\"></i>\n <span>{{ spec.title || 'Data Results' }}</span>\n @if (IsLive) {\n <span class=\"live-badge\">Live</span>\n }\n @if (DisplayRowCount != null) {\n <span class=\"row-count\">{{ DisplayRowCount }} rows</span>\n }\n @if (DisplayExecutionTime != null) {\n <span class=\"exec-time\">{{ DisplayExecutionTime }}ms</span>\n }\n </div>\n <div class=\"data-actions\">\n @if (IsLive) {\n <button class=\"btn-icon\" title=\"Refresh data\" (click)=\"OnRefresh()\" [disabled]=\"IsLoading\">\n <i class=\"fas fa-sync-alt\" [class.fa-spin]=\"IsLoading\"></i> Refresh\n </button>\n }\n\n @switch (QuerySyncState) {\n <!-- S1: No saved query, latest version \u2192 Save Query -->\n @case ('no-query-latest') {\n <button class=\"btn-icon btn-save\" title=\"Save as reusable query\"\n (click)=\"OnShowSaveDialog()\">\n <i class=\"fas fa-save\"></i> Save Query\n </button>\n }\n\n <!-- S2: SQL matches \u2192 green badge + Open -->\n @case ('synced') {\n <span class=\"query-badge query-badge-synced\">\n <i class=\"fas fa-check\"></i> Saved at v{{ SavedAtVersion }}\n </span>\n <button class=\"btn-icon btn-open\" title=\"Open saved query record\"\n (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S3: SQL differs, latest version \u2192 amber badge + dropdown -->\n @case ('outdated-latest') {\n <span class=\"query-badge query-badge-outdated\">\n <i class=\"fas fa-circle-exclamation\"></i> Saved at v{{ SavedAtVersion }}\n </span>\n <div class=\"dropdown-wrapper\">\n <button class=\"btn-icon btn-warning\" title=\"Update or save query\"\n (click)=\"OnToggleUpdateDropdown()\">\n <i class=\"fas fa-save\"></i> Update Query <i class=\"fas fa-caret-down\"></i>\n </button>\n @if (ShowUpdateDropdown) {\n <div class=\"query-dropdown\" (click)=\"$event.stopPropagation()\">\n <div class=\"query-dropdown-item\" (click)=\"OnUpdateExistingQuery()\">\n <i class=\"fas fa-arrow-up-from-bracket\" style=\"color:#d97706\"></i>\n <div>\n <div class=\"dropdown-label\">Update \"{{ SavedQueryDisplayName }}\"</div>\n <div class=\"dropdown-desc\">Replace saved query SQL with this version's SQL</div>\n </div>\n </div>\n <div class=\"query-dropdown-item\" (click)=\"OnSaveAsNewQuery()\">\n <i class=\"fas fa-plus\" style=\"color:#16a34a\"></i>\n <div>\n <div class=\"dropdown-label\">Save as New Query</div>\n <div class=\"dropdown-desc\">Create a new query, keep the original unchanged</div>\n </div>\n </div>\n <div class=\"query-dropdown-item\" (click)=\"OnOpenSavedQuery(); OnCloseDropdown()\">\n <i class=\"fas fa-external-link-alt\" style=\"color:var(--mj-text-muted)\"></i>\n <div>\n <div class=\"dropdown-label\">Open Saved Query</div>\n <div class=\"dropdown-desc\">View \"{{ SavedQueryDisplayName }}\" (saved at v{{ SavedAtVersion }})</div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- S4: Older version, query was updated ahead -->\n @case ('query-ahead') {\n <span class=\"query-badge query-badge-muted\">\n <i class=\"fas fa-clock-rotate-left\"></i> Query updated at v{{ SavedAtVersion }}\n </span>\n <button class=\"btn-icon btn-muted\" title=\"Open saved query record\"\n (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S5: Middle version, saved at older, not latest -->\n @case ('query-behind') {\n <span class=\"query-badge query-badge-muted\">\n <i class=\"fas fa-clock-rotate-left\"></i> Saved at v{{ SavedAtVersion }}\n </span>\n <button class=\"btn-icon btn-muted\" title=\"Open saved query record\"\n (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S6: No saved query, older version \u2192 no actions -->\n @case ('no-query-older') {\n <!-- No query actions available on older versions -->\n }\n }\n </div>\n </div>\n\n <!-- Grid -->\n <div class=\"grid-container\">\n <!-- Saving overlay -->\n @if (IsSaving) {\n <div class=\"saving-overlay\">\n <mj-loading [text]=\"SavingMessage\"></mj-loading>\n </div>\n }\n @if (IsLoading) {\n <mj-loading text=\"Loading data...\"></mj-loading>\n } @else if (HasError && HasData) {\n <div class=\"error-banner\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n <span class=\"fallback-note\">(Showing cached data)</span>\n </div>\n <mj-query-data-grid\n [ColumnConfigs]=\"GridColumnConfigs\"\n [Data]=\"GridData\"\n [TotalRowCount]=\"PagerTotalRowCount\"\n [PageNumber]=\"PagerPageNumber\"\n [PageSize]=\"PagerPageSize\"\n [ShowToolbar]=\"false\"\n [ShowRefresh]=\"false\"\n [PersistState]=\"false\"\n [SelectionMode]=\"'none'\"\n (EntityLinkClick)=\"OnEntityLinkClick($event)\"\n (PageChange)=\"OnPageChange($event)\"\n Height=\"100%\">\n </mj-query-data-grid>\n } @else if (HasError) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ ErrorMessage }}</p>\n </div>\n } @else {\n <mj-query-data-grid\n [ColumnConfigs]=\"GridColumnConfigs\"\n [Data]=\"GridData\"\n [TotalRowCount]=\"PagerTotalRowCount\"\n [PageNumber]=\"PagerPageNumber\"\n [PageSize]=\"PagerPageSize\"\n [ShowToolbar]=\"false\"\n [ShowRefresh]=\"false\"\n [PersistState]=\"false\"\n [SelectionMode]=\"'none'\"\n (EntityLinkClick)=\"OnEntityLinkClick($event)\"\n (PageChange)=\"OnPageChange($event)\"\n Height=\"100%\">\n </mj-query-data-grid>\n }\n </div>\n } @else if (spec.plan) {\n <!-- Plan-only view (no results yet) -->\n <div class=\"data-toolbar\">\n <div class=\"data-title\">\n <i class=\"fas fa-diagram-project\"></i>\n <span>{{ spec.title || 'Query Plan' }}</span>\n </div>\n </div>\n <div class=\"plan-content\">\n <mj-markdown\n [data]=\"spec.plan\"\n [enableMermaid]=\"true\"\n [enableHighlight]=\"true\"\n [enableCollapsibleHeadings]=\"false\"\n [enableSmartypants]=\"true\">\n </mj-markdown>\n </div>\n } @else {\n <!-- No data and no plan -->\n <div class=\"empty-state\">\n <i class=\"fas fa-inbox\"></i>\n <p>No data to display</p>\n </div>\n }\n } @else if (HasError) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <p>{{ ErrorMessage }}</p>\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fas fa-inbox\"></i>\n <p>No data to display</p>\n </div>\n }\n\n <!-- Save Query Panel (slide-in) -->\n @if (ShowSaveDialog) {\n <mj-save-query-panel\n [QueryName]=\"spec?.title || 'Untitled Query'\"\n [QueryDescription]=\"''\"\n [SQL]=\"spec?.metadata?.sql || ''\"\n [Plan]=\"spec?.plan || ''\"\n (Saved)=\"OnQuerySaved($event)\"\n (Cancelled)=\"ShowSaveDialog = false\">\n </mj-save-query-panel>\n }\n</div>\n", styles: [".data-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.data-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.data-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.data-title i {\n color: var(--mj-text-muted);\n}\n\n.row-count {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.exec-time {\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-status-success);\n}\n\n.live-badge {\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.data-actions {\n display: flex;\n gap: 6px;\n}\n\n.btn-icon {\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: var(--mj-text-secondary);\n}\n\n.btn-icon:hover {\n background: var(--mj-border-default);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-save {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-save:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-color: var(--mj-status-success);\n}\n\n.btn-icon.btn-open {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-open:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.grid-container {\n flex: 1;\n overflow: hidden;\n min-height: 200px;\n height: 500px;\n position: relative;\n}\n\n/* Saving overlay \u2014 semi-transparent panel over the grid */\n.saving-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n}\n\n.error-banner {\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n border-bottom: 1px solid var(--mj-status-warning);\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-status-warning);\n}\n\n.fallback-note {\n font-style: italic;\n color: var(--mj-text-muted);\n}\n\n.empty-state, .error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: var(--mj-text-muted);\n text-align: center;\n gap: 12px;\n}\n\n.empty-state i, .error-state i {\n font-size: 32px;\n}\n\n.error-state {\n color: var(--mj-status-error);\n}\n\n.plan-content {\n flex: 1;\n overflow: auto;\n padding: 16px;\n}\n\n/* Query sync badges */\n.query-badge {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n\n.query-badge-synced {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.query-badge-outdated {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.query-badge-muted {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n/* Dropdown wrapper */\n.dropdown-wrapper {\n position: relative;\n}\n\n.btn-icon.btn-warning {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-warning:hover {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-color: var(--mj-status-warning);\n}\n\n.btn-icon.btn-muted {\n color: var(--mj-text-disabled);\n border-color: var(--mj-border-default);\n}\n\n/* Query actions dropdown */\n.query-dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n min-width: 280px;\n z-index: 100;\n}\n\n.query-dropdown-item {\n padding: 10px 14px;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n cursor: pointer;\n border-bottom: 1px solid var(--mj-border-default);\n transition: background 0.1s;\n}\n\n.query-dropdown-item:last-child {\n border-bottom: none;\n}\n\n.query-dropdown-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.query-dropdown-item i {\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.dropdown-label {\n font-weight: 500;\n}\n\n.dropdown-desc {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n"] }]
823
856
  }], () => [{ type: i0.ChangeDetectorRef }], { openEntityRecord: [{
824
857
  type: Output
825
858
  }], navigationRequest: [{
826
859
  type: Output
827
860
  }] }); })();
828
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DataArtifactViewerComponent, { className: "DataArtifactViewerComponent", filePath: "src/lib/components/plugins/data-artifact-viewer.component.ts", lineNumber: 108 }); })();
861
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DataArtifactViewerComponent, { className: "DataArtifactViewerComponent", filePath: "src/lib/components/plugins/data-artifact-viewer.component.ts", lineNumber: 109 }); })();
829
862
  //# sourceMappingURL=data-artifact-viewer.component.js.map