@memberjunction/ng-artifacts 5.28.0 → 5.29.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 (65) hide show
  1. package/dist/lib/__tests__/artifact-snapshots.test.d.ts +2 -0
  2. package/dist/lib/__tests__/artifact-snapshots.test.d.ts.map +1 -0
  3. package/dist/lib/__tests__/artifact-snapshots.test.js +155 -0
  4. package/dist/lib/__tests__/artifact-snapshots.test.js.map +1 -0
  5. package/dist/lib/components/artifact-viewer-panel.component.d.ts +16 -2
  6. package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact-viewer-panel.component.js +128 -98
  8. package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
  9. package/dist/lib/components/base-artifact-viewer.component.d.ts +24 -0
  10. package/dist/lib/components/base-artifact-viewer.component.d.ts.map +1 -1
  11. package/dist/lib/components/base-artifact-viewer.component.js +15 -1
  12. package/dist/lib/components/base-artifact-viewer.component.js.map +1 -1
  13. package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts +2 -0
  14. package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts.map +1 -1
  15. package/dist/lib/components/plugins/code-artifact-viewer.component.js +5 -1
  16. package/dist/lib/components/plugins/code-artifact-viewer.component.js.map +1 -1
  17. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +2 -1
  18. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
  19. package/dist/lib/components/plugins/component-artifact-viewer.component.js +29 -0
  20. package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
  21. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts +50 -43
  22. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
  23. package/dist/lib/components/plugins/data-artifact-viewer.component.js +336 -137
  24. package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
  25. package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts +2 -0
  26. package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts.map +1 -1
  27. package/dist/lib/components/plugins/docx-artifact-viewer.component.js +21 -6
  28. package/dist/lib/components/plugins/docx-artifact-viewer.component.js.map +1 -1
  29. package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts +2 -0
  30. package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts.map +1 -1
  31. package/dist/lib/components/plugins/html-artifact-viewer.component.js +11 -1
  32. package/dist/lib/components/plugins/html-artifact-viewer.component.js.map +1 -1
  33. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts +2 -0
  34. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts.map +1 -1
  35. package/dist/lib/components/plugins/json-artifact-viewer.component.js +5 -1
  36. package/dist/lib/components/plugins/json-artifact-viewer.component.js.map +1 -1
  37. package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts +2 -0
  38. package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts.map +1 -1
  39. package/dist/lib/components/plugins/markdown-artifact-viewer.component.js +5 -1
  40. package/dist/lib/components/plugins/markdown-artifact-viewer.component.js.map +1 -1
  41. package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts +2 -0
  42. package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts.map +1 -1
  43. package/dist/lib/components/plugins/pdf-artifact-viewer.component.js +29 -10
  44. package/dist/lib/components/plugins/pdf-artifact-viewer.component.js.map +1 -1
  45. package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts +2 -0
  46. package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts.map +1 -1
  47. package/dist/lib/components/plugins/svg-artifact-viewer.component.js +11 -1
  48. package/dist/lib/components/plugins/svg-artifact-viewer.component.js.map +1 -1
  49. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts +2 -0
  50. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts.map +1 -1
  51. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js +39 -13
  52. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js.map +1 -1
  53. package/dist/lib/services/analyze-artifact.service.d.ts +77 -0
  54. package/dist/lib/services/analyze-artifact.service.d.ts.map +1 -0
  55. package/dist/lib/services/analyze-artifact.service.js +120 -0
  56. package/dist/lib/services/analyze-artifact.service.js.map +1 -0
  57. package/dist/lib/snapshot-helpers.d.ts +48 -0
  58. package/dist/lib/snapshot-helpers.d.ts.map +1 -0
  59. package/dist/lib/snapshot-helpers.js +79 -0
  60. package/dist/lib/snapshot-helpers.js.map +1 -0
  61. package/dist/public-api.d.ts +2 -0
  62. package/dist/public-api.d.ts.map +1 -1
  63. package/dist/public-api.js +3 -0
  64. package/dist/public-api.js.map +1 -1
  65. package/package.json +16 -16
@@ -1 +1 @@
1
- {"version":3,"file":"data-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/data-artifact-viewer.component.ts","../../../../src/lib/components/plugins/data-artifact-viewer.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ChangeDetectorRef, Output, EventEmitter } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { Metadata, RunQuery, CompositeKey, KeyValuePair } from '@memberjunction/core';\nimport { QueryEngine, ArtifactMetadataEngine } from '@memberjunction/core-entities';\nimport { QueryGridColumnConfig, QueryEntityLinkClickEvent, resolveTargetEntity } from '@memberjunction/ng-query-viewer';\nimport { PageChangeEvent } from '@memberjunction/ng-pagination';\nimport { BaseArtifactViewerPluginComponent, ArtifactViewerTab, NavigationRequest } from '../base-artifact-viewer.component';\nimport { SaveQueryResult } from './save-query-dialog.component';\n\n/**\n * JSON schema for Data artifact content.\n * The agent produces this structure when emitting query/view results.\n */\ninterface DataArtifactSpec {\n /** Data source type */\n source: 'query' | 'view';\n\n /** Display title for the data */\n title?: string;\n\n /** For query source: the query ID to render via mj-query-viewer */\n queryId?: string;\n\n /** For query source: parameter values to pass */\n parameters?: Record<string, string | number | boolean>;\n\n /** For view source: the entity name */\n entityName?: string;\n\n /** For view source: extra WHERE filter */\n extraFilter?: string;\n\n /** Column definitions for inline data display */\n columns?: DataArtifactColumn[];\n\n /** Inline row data (when results are embedded directly) */\n rows?: Record<string, unknown>[];\n\n /** Optional markdown plan/approach description (mermaid diagrams, explanations) */\n plan?: string;\n\n /** Query metadata */\n metadata?: {\n sql?: string;\n rowCount?: number;\n executionTimeMs?: number;\n };\n\n /** ID of saved query (set after user saves from artifact) */\n savedQueryId?: string;\n\n /** Name of saved query (for display) */\n savedQueryName?: string;\n\n /** Version number this query was saved/updated from */\n savedAtVersionNumber?: number;\n}\n\ninterface DataArtifactColumn {\n field: string;\n headerName?: string;\n width?: number;\n\n /** MJ entity name this column originates from (e.g., \"Members\") */\n sourceEntity?: string;\n\n /** Field name in that entity (e.g., \"ID\", \"FirstName\") */\n sourceFieldName?: string;\n\n /** True for calculated expressions (CASE, ROUND, CONCAT, etc.) */\n isComputed?: boolean;\n\n /** True for aggregate functions (SUM, COUNT, AVG, etc.) */\n isSummary?: boolean;\n\n /** SQL data type: int, nvarchar, uniqueidentifier, datetime, decimal, bit, money, etc. */\n sqlBaseType?: string;\n}\n\n/**\n * Describes the relationship between the current artifact version's SQL\n * and the saved query record. Drives the toolbar UI.\n */\ntype QuerySyncState =\n | 'no-query-latest' // No saved query, viewing latest version → show \"Save Query\"\n | 'no-query-older' // No saved query, viewing older version → no actions\n | 'synced' // SQL matches saved query → green badge + \"Open Query\"\n | 'outdated-latest' // SQL differs, viewing latest → amber badge + dropdown\n | 'query-ahead' // Viewing older version, query was updated at a newer version\n | 'query-behind'; // Viewing middle version, saved at older, not latest → muted\n\n/**\n * Viewer component for Data artifacts.\n *\n * Displays tabular data using AG Grid via mj-query-data-grid. Supports two modes:\n * 1. **Live data**: When metadata.sql is present, executes the query dynamically via RunQuery({ SQL })\n * to fetch fresh data on each view. Falls back to inline rows on error.\n * 2. **Inline data**: Rows embedded directly in the artifact JSON (backward compat with older artifacts)\n *\n * The Query Builder agent emits artifacts with metadata.sql for live execution.\n */\n@Component({\n standalone: false,\n selector: 'mj-data-artifact-viewer',\n templateUrl: './data-artifact-viewer.component.html',\n styleUrls: ['./data-artifact-viewer.component.css']\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'DataArtifactViewerPlugin')\nexport class DataArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {\n @Output() openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() override navigationRequest = new EventEmitter<NavigationRequest>();\n public override tabsChanged = new EventEmitter<void>();\n\n public spec: DataArtifactSpec | null = null;\n public GridData: Record<string, unknown>[] = [];\n public GridColumnConfigs: QueryGridColumnConfig[] | null = null;\n public IsLoading = false;\n public IsLive = false;\n public HasError = false;\n public ErrorMessage = '';\n public ShowSaveDialog = false;\n public ShowUpdateDropdown = false;\n public IsSaving = false;\n public SavingMessage = '';\n\n /** Paging state — passed through to mj-query-data-grid's embedded pager */\n public PagerTotalRowCount = 0;\n public PagerPageNumber = 1;\n public PagerPageSize = 100;\n\n /** Query sync state — drives the toolbar UI for saved query actions */\n public QuerySyncState: QuerySyncState = 'no-query-latest';\n\n /** Latest version number for this artifact (from cache) */\n public LatestVersionNumber = 0;\n\n /** Metadata from live execution (overrides spec.metadata when live) */\n private liveRowCount: number | null = null;\n private liveExecutionTime: number | null = null;\n\n /** SQL from the saved query record (for comparison) */\n private savedQuerySql: string | null = null;\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n public override get hasDisplayContent(): boolean {\n return this.spec != null && (this.HasData || this.IsLoading);\n }\n\n public override get parentShouldShowRawContent(): boolean {\n return true;\n }\n\n public get HasData(): boolean {\n return this.GridData.length > 0;\n }\n\n public get HasInlineData(): boolean {\n return !!(this.spec?.rows && this.spec.rows.length > 0);\n }\n\n public get DisplayRowCount(): number | null {\n return this.liveRowCount ?? this.spec?.metadata?.rowCount ?? null;\n }\n\n public get DisplayExecutionTime(): number | null {\n return this.liveExecutionTime ?? this.spec?.metadata?.executionTimeMs ?? null;\n }\n\n /** Current artifact version number */\n public get CurrentVersionNumber(): number {\n return this.artifactVersion?.VersionNumber || 1;\n }\n\n /** Whether this is the latest version of the artifact */\n public get IsLatestVersion(): boolean {\n return this.CurrentVersionNumber === this.LatestVersionNumber;\n }\n\n /**\n * The effective version number at which the query was last saved/updated.\n * When viewing an older version, this looks ahead through newer versions\n * to find the most recent savedAtVersionNumber for the same query,\n * giving the user accurate context (e.g., \"Query updated at v3\" instead\n * of the stale \"Saved at v1\" from this version's snapshot).\n */\n public EffectiveSavedAtVersion: number | null = null;\n\n /** Alias used by the template */\n public get SavedAtVersion(): number | null {\n return this.EffectiveSavedAtVersion;\n }\n\n /** Display name for the saved query */\n public get SavedQueryDisplayName(): string {\n return this.spec?.savedQueryName || 'Saved Query';\n }\n\n async ngOnInit(): Promise<void> {\n try {\n this.spec = this.parseJsonContent<DataArtifactSpec>();\n if (!this.spec) {\n this.HasError = true;\n this.ErrorMessage = 'Failed to parse data artifact content';\n return;\n }\n\n // Build enriched column configs from agent metadata (if available)\n this.GridColumnConfigs = this.BuildColumnConfigs();\n\n // Set loading early (synchronously) so hasDisplayContent is true immediately.\n // This ensures the Display tab is available when onPluginLoaded fires,\n // showing a loading indicator instead of briefly flashing the Plan tab.\n if (this.spec.metadata?.sql || this.HasInlineData) {\n this.IsLoading = true;\n }\n\n // Load cached metadata and resolve query sync state\n await this.InitQuerySyncState();\n\n // If SQL is available, execute it live\n if (this.spec.metadata?.sql) {\n await this.LoadLiveData();\n } else if (this.HasInlineData) {\n // Fall back to embedded rows\n this.GridData = this.spec.rows!;\n this.IsLoading = false;\n }\n\n // Signal parent that tabs/display content may have changed after async load\n this.tabsChanged.emit();\n } catch (error) {\n this.HasError = true;\n this.ErrorMessage = error instanceof Error ? error.message : 'Failed to load data';\n }\n }\n\n /**\n * Re-execute the live SQL query\n */\n public async OnRefresh(): Promise<void> {\n if (this.spec?.metadata?.sql) {\n await this.LoadLiveData();\n }\n }\n\n /**\n * Handle entity link click from the grid and bubble up as openEntityRecord.\n * Converts the grid's recordId string into a CompositeKey for the artifact viewer pipeline.\n */\n public OnEntityLinkClick(event: QueryEntityLinkClickEvent): void {\n const md = new Metadata();\n const entity = md.Entities.find(e => e.Name === event.entityName);\n const pkFieldName = entity?.FirstPrimaryKey?.Name ?? 'ID';\n\n const compositeKey = new CompositeKey([\n new KeyValuePair(pkFieldName, event.recordId)\n ]);\n this.openEntityRecord.emit({\n entityName: event.entityName,\n compositeKey\n });\n }\n\n /**\n * Handle page change from the data grid's embedded pager.\n * Re-executes the live SQL with the new page parameters.\n */\n public async OnPageChange(event: PageChangeEvent): Promise<void> {\n if (!this.spec?.metadata?.sql) return;\n this.PagerPageNumber = event.PageNumber;\n this.PagerPageSize = event.PageSize;\n await this.LoadLiveData();\n }\n\n /**\n * Execute the SQL query via RunQuery and populate the grid.\n * Falls back to inline data on error.\n */\n private async LoadLiveData(): Promise<void> {\n this.IsLoading = true;\n this.HasError = false;\n this.cdr.detectChanges();\n\n try {\n const rq = new RunQuery();\n const startRow = (this.PagerPageNumber - 1) * this.PagerPageSize;\n const result = await rq.RunQuery({\n SQL: this.spec!.metadata!.sql!,\n StartRow: startRow,\n MaxRows: this.PagerPageSize\n });\n\n if (result.Success) {\n this.GridData = result.Results;\n this.liveRowCount = result.RowCount;\n this.liveExecutionTime = result.ExecutionTime;\n this.IsLive = true;\n\n // Update pager state from result\n if (result.TotalRowCount != null) {\n this.PagerTotalRowCount = result.TotalRowCount;\n }\n if (result.PageNumber != null) {\n this.PagerPageNumber = result.PageNumber;\n }\n if (result.PageSize != null) {\n this.PagerPageSize = result.PageSize;\n }\n } else {\n this.HandleQueryError(result.ErrorMessage || 'Query execution failed');\n }\n } catch (error) {\n this.HandleQueryError(error instanceof Error ? error.message : 'Query execution failed');\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Build QueryGridColumnConfig[] from enriched artifact column metadata.\n * Returns null if columns have no entity metadata (grid falls back to auto-inference).\n */\n private BuildColumnConfigs(): QueryGridColumnConfig[] | null {\n if (!this.spec?.columns?.length) return null;\n\n // Only build if at least one column has entity metadata or type info\n const hasMetadata = this.spec.columns.some(c => c.sourceEntity || c.sqlBaseType);\n if (!hasMetadata) return null;\n\n const md = new Metadata();\n return this.spec.columns.map((col, index) => {\n const target = resolveTargetEntity(col.sourceEntity, col.sourceFieldName, md);\n const isEntityLink = !!(target.targetEntityName && (target.isPrimaryKey || target.isForeignKey));\n const baseType = (col.sqlBaseType || 'nvarchar').toLowerCase();\n\n let align: 'left' | 'center' | 'right' = 'left';\n if (['int', 'bigint', 'decimal', 'numeric', 'float', 'money', 'smallmoney', 'real'].includes(baseType)) {\n align = 'right';\n } else if (baseType === 'bit') {\n align = 'center';\n }\n\n return {\n field: col.field,\n title: col.headerName || col.field,\n visible: true,\n sortable: true,\n resizable: true,\n reorderable: true,\n sqlBaseType: col.sqlBaseType || 'nvarchar',\n sqlFullType: col.sqlBaseType || 'nvarchar',\n align,\n order: index,\n sourceEntityName: col.sourceEntity,\n sourceFieldName: col.sourceFieldName,\n isEntityLink,\n targetEntityName: target.targetEntityName,\n targetEntityId: target.targetEntityId,\n targetEntityIcon: target.targetEntityIcon,\n isPrimaryKey: target.isPrimaryKey,\n isForeignKey: target.isForeignKey,\n pinned: null,\n } as QueryGridColumnConfig;\n });\n }\n\n /**\n * Handle a query error by setting error state and falling back to inline data\n */\n private HandleQueryError(message: string): void {\n this.HasError = true;\n this.ErrorMessage = message;\n if (this.HasInlineData) {\n this.GridData = this.spec!.rows!;\n }\n }\n\n // ─── Query Sync State ────────────────────────────────────────────\n\n /**\n * Initialize query sync state by loading cached metadata.\n * Resolves the latest version number and compares saved query SQL.\n */\n private async InitQuerySyncState(): Promise<void> {\n // Ensure artifact cache is loaded (not registered for startup)\n await ArtifactMetadataEngine.Instance.Config(false);\n\n this.LatestVersionNumber = this.resolveLatestVersionNumber();\n\n // If cache is stale (doesn't know about the version we're viewing),\n // force-refresh and re-resolve. This happens when new versions are\n // created during a conversation after the cache was first loaded.\n if (this.LatestVersionNumber < this.CurrentVersionNumber) {\n await ArtifactMetadataEngine.Instance.Config(true);\n this.LatestVersionNumber = this.resolveLatestVersionNumber();\n }\n\n this.EffectiveSavedAtVersion = this.resolveEffectiveSavedAtVersion();\n await this.resolveSavedQuerySql();\n this.QuerySyncState = this.computeQuerySyncState();\n }\n\n /**\n * Determine the latest version number for this artifact from cache.\n * Falls back to current version if cache miss.\n */\n private resolveLatestVersionNumber(): number {\n if (!this.artifactVersion?.ArtifactID) {\n return this.CurrentVersionNumber;\n }\n\n const versions = ArtifactMetadataEngine.Instance.GetVersionsForArtifact(this.artifactVersion.ArtifactID);\n if (versions.length > 0) {\n // GetVersionsForArtifact returns DESC sorted\n return versions[0].VersionNumber || 1;\n }\n\n // Cache miss — current version is our best guess\n return this.CurrentVersionNumber;\n }\n\n /**\n * Scan all versions of this artifact to find the most recent savedAtVersionNumber\n * for the same savedQueryId. When viewing an older version, this tells the user\n * where the query was *actually* last updated, not just what this version's\n * snapshot recorded at the time.\n */\n private resolveEffectiveSavedAtVersion(): number | null {\n const queryId = this.spec?.savedQueryId;\n if (!queryId) return null;\n\n // Start with this version's own value\n let effective = this.spec?.savedAtVersionNumber ?? null;\n\n if (!this.artifactVersion?.ArtifactID) return effective;\n\n // GetVersionsForArtifact returns DESC sorted — scan all versions\n const versions = ArtifactMetadataEngine.Instance.GetVersionsForArtifact(this.artifactVersion.ArtifactID);\n for (const v of versions) {\n try {\n if (!v.Content) continue;\n const content = typeof v.Content === 'string' ? JSON.parse(v.Content) : v.Content;\n if (content.savedQueryId === queryId && content.savedAtVersionNumber != null) {\n const vSavedAt = content.savedAtVersionNumber as number;\n if (effective == null || vSavedAt > effective) {\n effective = vSavedAt;\n }\n }\n } catch {\n // Skip versions with unparseable content\n }\n }\n\n return effective;\n }\n\n /**\n * Look up the saved query's SQL from QueryEngine cache for comparison.\n * Only fetches if savedQueryId is present.\n */\n private async resolveSavedQuerySql(): Promise<void> {\n if (!this.spec?.savedQueryId) {\n this.savedQuerySql = null;\n return;\n }\n\n // QueryEngine is registered for startup, should already be loaded\n let query = QueryEngine.Instance.FindQueryByID(this.spec.savedQueryId);\n\n if (!query) {\n // Cache miss — force refresh and retry\n await QueryEngine.Instance.Config(true);\n query = QueryEngine.Instance.FindQueryByID(this.spec.savedQueryId);\n }\n\n this.savedQuerySql = query?.SQL ?? null;\n }\n\n /**\n * Compute the query sync state from current spec, version, and saved query SQL.\n * Implements the decision tree from the UX design.\n */\n private computeQuerySyncState(): QuerySyncState {\n const hasSavedQuery = !!this.spec?.savedQueryId;\n const isLatest = this.IsLatestVersion;\n\n if (!hasSavedQuery) {\n return isLatest ? 'no-query-latest' : 'no-query-older';\n }\n\n // Compare SQL (normalize whitespace for reliable comparison)\n const specSql = this.normalizeSql(this.spec?.metadata?.sql);\n const querySql = this.normalizeSql(this.savedQuerySql);\n const sqlMatches = specSql != null && querySql != null && specSql === querySql;\n\n // Only truly synced if SQL matches AND this is the version it was saved at.\n // Even with identical SQL, a newer version should show the dropdown so the\n // user can update the version association (re-save at current version).\n const savedAtCurrent = this.EffectiveSavedAtVersion === this.CurrentVersionNumber;\n if (sqlMatches && savedAtCurrent) {\n return 'synced';\n }\n\n // SQL differs — determine position relative to saved version\n if (isLatest) {\n return 'outdated-latest';\n }\n\n // Use effective saved-at (looks ahead through newer versions)\n const savedAt = this.EffectiveSavedAtVersion;\n if (savedAt != null && this.CurrentVersionNumber < savedAt) {\n return 'query-ahead'; // query was updated at a newer version\n }\n\n return 'query-behind'; // ahead of saved but not latest\n }\n\n /** Normalize SQL for comparison: trim and collapse whitespace */\n private normalizeSql(sql: string | null | undefined): string | null {\n if (sql == null) return null;\n return sql.trim().replace(/\\s+/g, ' ');\n }\n\n // ─── Actions ────────────────────────────────────────────────────\n\n /** Navigate to the saved query in the Data Explorer's Queries browser */\n public OnOpenSavedQuery(): void {\n if (!this.spec?.savedQueryId) return;\n this.navigationRequest.emit({\n appName: 'Data Explorer',\n navItemName: 'Queries',\n queryParams: { queryId: this.spec.savedQueryId }\n });\n }\n\n /** Show the save panel for creating a brand-new query */\n public OnShowSaveDialog(): void {\n this.ShowSaveDialog = true;\n this.ShowUpdateDropdown = false;\n }\n\n /** Toggle the update query dropdown */\n public OnToggleUpdateDropdown(): void {\n this.ShowUpdateDropdown = !this.ShowUpdateDropdown;\n }\n\n /** Close the dropdown (e.g., on outside click) */\n public OnCloseDropdown(): void {\n this.ShowUpdateDropdown = false;\n }\n\n /**\n * Update the existing saved query's SQL to match this version.\n * Only available from the latest version (Scenario 3).\n */\n public async OnUpdateExistingQuery(): Promise<void> {\n this.ShowUpdateDropdown = false;\n if (!this.spec?.savedQueryId || !this.spec.metadata?.sql) return;\n\n this.IsSaving = true;\n this.SavingMessage = `Updating \"${this.SavedQueryDisplayName}\"...`;\n this.cdr.detectChanges();\n\n try {\n const md = new Metadata();\n const query = await md.GetEntityObject<import('@memberjunction/core-entities').MJQueryEntity>('MJ: Queries');\n const loaded = await query.Load(this.spec.savedQueryId);\n\n if (!loaded) {\n console.error('Failed to load saved query for update');\n return;\n }\n\n query.SQL = this.spec.metadata.sql;\n if (this.spec.plan?.trim()) {\n query.TechnicalDescription = this.spec.plan.trim();\n }\n const saved = await query.Save();\n\n if (saved) {\n // Update spec with new version tracking\n this.spec.savedAtVersionNumber = this.CurrentVersionNumber;\n await this.PersistArtifactContent();\n\n // Refresh caches so future lookups see the updated data\n await QueryEngine.Instance.Config(true);\n await ArtifactMetadataEngine.Instance.Config(true);\n await md.Refresh();\n\n this.savedQuerySql = this.spec.metadata.sql;\n this.EffectiveSavedAtVersion = this.CurrentVersionNumber;\n this.QuerySyncState = 'synced';\n }\n } catch (error) {\n console.error('Failed to update saved query:', error);\n } finally {\n this.IsSaving = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Save as a new query (from the dropdown).\n * Opens the save dialog which creates a fresh query record.\n */\n public OnSaveAsNewQuery(): void {\n this.ShowUpdateDropdown = false;\n this.ShowSaveDialog = true;\n }\n\n /** Handle successful save from the dialog (both initial save and \"save as new\") */\n public async OnQuerySaved(event: SaveQueryResult): Promise<void> {\n this.ShowSaveDialog = false;\n this.IsSaving = true;\n this.SavingMessage = 'Saving query...';\n this.cdr.detectChanges();\n\n try {\n // Update spec with saved query info and version tracking\n this.spec!.savedQueryId = event.queryId;\n this.spec!.savedQueryName = event.queryName;\n this.spec!.savedAtVersionNumber = this.CurrentVersionNumber;\n\n // Persist and refresh caches\n await this.PersistArtifactContent();\n await QueryEngine.Instance.Config(true);\n await ArtifactMetadataEngine.Instance.Config(true);\n await new Metadata().Refresh();\n\n this.savedQuerySql = this.spec!.metadata?.sql ?? null;\n this.EffectiveSavedAtVersion = this.CurrentVersionNumber;\n this.QuerySyncState = 'synced';\n } catch (error) {\n console.error('Failed to save query:', error);\n } finally {\n this.IsSaving = false;\n this.cdr.detectChanges();\n }\n }\n\n /** Persist updated spec back to the artifact version entity */\n private async PersistArtifactContent(): Promise<void> {\n if (!this.artifactVersion || !this.spec) return;\n this.artifactVersion.Content = JSON.stringify(this.spec);\n await this.artifactVersion.Save();\n }\n\n // ─── Tabs ───────────────────────────────────────────────────────\n\n /**\n * Provide Plan tab (markdown) and SQL tab (code) when available\n */\n public GetAdditionalTabs(): ArtifactViewerTab[] {\n const tabs: ArtifactViewerTab[] = [];\n\n if (this.spec?.plan) {\n tabs.push({\n label: 'Plan',\n icon: 'fa-diagram-project',\n contentType: 'markdown',\n content: this.spec.plan\n });\n }\n\n if (this.spec?.metadata?.sql) {\n tabs.push({\n label: 'SQL',\n icon: 'fa-database',\n contentType: 'code',\n language: 'sql',\n content: this.spec.metadata.sql\n });\n }\n\n return tabs;\n }\n}\n","<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 → 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 → 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 → 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 → 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"]}
1
+ {"version":3,"file":"data-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/data-artifact-viewer.component.ts","../../../../src/lib/components/plugins/data-artifact-viewer.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ChangeDetectorRef, Output, EventEmitter } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { DataSnapshot, DataTable, DataComputation, MJColumnDescriptor, NormalizeToTables, Metadata, RunQuery, CompositeKey, KeyValuePair } from '@memberjunction/core';\nimport { QueryEngine, ArtifactMetadataEngine } from '@memberjunction/core-entities';\nimport { QueryGridColumnConfig, QueryEntityLinkClickEvent, resolveTargetEntity } from '@memberjunction/ng-query-viewer';\nimport { PageChangeEvent } from '@memberjunction/ng-pagination';\nimport { BaseArtifactViewerPluginComponent, ArtifactViewerTab, NavigationRequest } from '../base-artifact-viewer.component';\nimport { SaveQueryResult } from './save-query-dialog.component';\nimport { createDataSnapshot, buildMultiTableSql } from '../../snapshot-helpers';\n\n/**\n * Data artifact content shape as parsed from JSON.\n *\n * Core tabular data fields (source, columns, rows, tables, metadata, etc.)\n * are handled by NormalizeToTables() from @memberjunction/core.\n * This interface adds viewer-specific fields for query sync and display.\n *\n * Columns may use either `displayName` (new) or `headerName` (legacy).\n * BuildColumnConfigsForTable handles both.\n */\ninterface DataArtifactSpec {\n source?: 'query' | 'view';\n title?: string;\n queryId?: string;\n parameters?: Record<string, string | number | boolean>;\n entityName?: string;\n extraFilter?: string;\n columns?: Array<MJColumnDescriptor & { headerName?: string }>;\n rows?: Record<string, unknown>[];\n tables?: DataTable[];\n plan?: string;\n interpretation?: string;\n computations?: DataComputation[];\n metadata?: { sql?: string; rowCount?: number; executionTimeMs?: number };\n savedQueryId?: string;\n savedQueryName?: string;\n savedAtVersionNumber?: number;\n}\n\n/**\n * Describes the relationship between the current artifact version's SQL\n * and the saved query record. Drives the toolbar UI.\n */\ntype QuerySyncState =\n | 'no-query-latest' // No saved query, viewing latest version → show \"Save Query\"\n | 'no-query-older' // No saved query, viewing older version → no actions\n | 'synced' // SQL matches saved query → green badge + \"Open Query\"\n | 'outdated-latest' // SQL differs, viewing latest → amber badge + dropdown\n | 'query-ahead' // Viewing older version, query was updated at a newer version\n | 'query-behind'; // Viewing middle version, saved at older, not latest → muted\n\n/**\n * Viewer component for Data artifacts.\n *\n * Displays tabular data using AG Grid via mj-query-data-grid. Supports two modes:\n * 1. **Live data**: When metadata.sql is present, executes the query dynamically via RunQuery({ SQL })\n * to fetch fresh data on each view. Falls back to inline rows on error.\n * 2. **Inline data**: Rows embedded directly in the artifact JSON (backward compat with older artifacts)\n *\n * The Query Builder agent emits artifacts with metadata.sql for live execution.\n */\n@Component({\n standalone: false,\n selector: 'mj-data-artifact-viewer',\n templateUrl: './data-artifact-viewer.component.html',\n styleUrls: ['./data-artifact-viewer.component.css']\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'DataArtifactViewerPlugin')\nexport class DataArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {\n @Output() openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n @Output() override navigationRequest = new EventEmitter<NavigationRequest>();\n public override tabsChanged = new EventEmitter<void>();\n\n public spec: DataArtifactSpec | null = null;\n public GridData: Record<string, unknown>[] = [];\n public GridColumnConfigs: QueryGridColumnConfig[] | null = null;\n public IsLoading = false;\n public IsLive = false;\n public HasError = false;\n public ErrorMessage = '';\n public ShowSaveDialog = false;\n public ShowUpdateDropdown = false;\n public IsSaving = false;\n public SavingMessage = '';\n\n /** Paging state — passed through to mj-query-data-grid's embedded pager */\n public PagerTotalRowCount = 0;\n public PagerPageNumber = 1;\n public PagerPageSize = 100;\n\n // ─── Multi-Table State ───\n\n /** All resolved tables (from multi-table or wrapped single-table) */\n public ResolvedTables: DataTable[] = [];\n\n /** Index of the currently active table tab */\n public ActiveTableIndex = 0;\n\n /** Per-table paging state */\n private tablePageState: Map<number, { pageNumber: number; pageSize: number; totalRowCount: number }> = new Map();\n\n /** Per-table live data cache (loaded lazily on tab switch) */\n private tableDataCache: Map<number, Record<string, unknown>[]> = new Map();\n\n /** Per-table column configs cache */\n private tableColumnConfigsCache: Map<number, QueryGridColumnConfig[]> = new Map();\n\n /** Whether we're in multi-table mode */\n public get IsMultiTable(): boolean {\n return this.ResolvedTables.length > 1;\n }\n\n /** The currently active table */\n public get ActiveTable(): DataTable | null {\n return this.ResolvedTables[this.ActiveTableIndex] ?? null;\n }\n\n /** Query sync state — drives the toolbar UI for saved query actions */\n public QuerySyncState: QuerySyncState = 'no-query-latest';\n\n /** Latest version number for this artifact (from cache) */\n public LatestVersionNumber = 0;\n\n /** Metadata from live execution (overrides spec.metadata when live) */\n private liveRowCount: number | null = null;\n private liveExecutionTime: number | null = null;\n\n /** SQL from the saved query record (for comparison) */\n private savedQuerySql: string | null = null;\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n public override get hasDisplayContent(): boolean {\n return this.spec != null && (this.HasData || this.IsLoading || this.ResolvedTables.length > 0);\n }\n\n public override get parentShouldShowRawContent(): boolean {\n return true;\n }\n\n public get HasData(): boolean {\n return this.GridData.length > 0;\n }\n\n public get HasInlineData(): boolean {\n // Check root-level rows (legacy single-table) or any resolved table with rows\n return !!(this.spec?.rows && this.spec.rows.length > 0) ||\n this.ResolvedTables.some(t => t.rows && t.rows.length > 0);\n }\n\n public get DisplayRowCount(): number | null {\n return this.liveRowCount ?? this.spec?.metadata?.rowCount ?? null;\n }\n\n public get DisplayExecutionTime(): number | null {\n return this.liveExecutionTime ?? this.spec?.metadata?.executionTimeMs ?? null;\n }\n\n /** Current artifact version number */\n public get CurrentVersionNumber(): number {\n return this.artifactVersion?.VersionNumber || 1;\n }\n\n /** Whether this is the latest version of the artifact */\n public get IsLatestVersion(): boolean {\n return this.CurrentVersionNumber === this.LatestVersionNumber;\n }\n\n /**\n * The effective version number at which the query was last saved/updated.\n * When viewing an older version, this looks ahead through newer versions\n * to find the most recent savedAtVersionNumber for the same query,\n * giving the user accurate context (e.g., \"Query updated at v3\" instead\n * of the stale \"Saved at v1\" from this version's snapshot).\n */\n public EffectiveSavedAtVersion: number | null = null;\n\n /** Alias used by the template */\n public get SavedAtVersion(): number | null {\n return this.EffectiveSavedAtVersion;\n }\n\n /** Display name for the saved query */\n public get SavedQueryDisplayName(): string {\n return this.spec?.savedQueryName || 'Saved Query';\n }\n\n async ngOnInit(): Promise<void> {\n try {\n this.spec = this.parseJsonContent<DataArtifactSpec>();\n if (!this.spec) {\n this.HasError = true;\n this.ErrorMessage = 'Failed to parse data artifact content';\n return;\n }\n\n // Resolve to tables array (handles both single and multi-table)\n this.ResolvedTables = NormalizeToTables(\n this.spec as unknown as Record<string, unknown>,\n this.spec.title || 'Results'\n );\n\n if (this.ResolvedTables.length === 0 && !this.spec.plan) {\n return;\n }\n\n // Build enriched column configs for the first table\n if (this.ResolvedTables.length > 0) {\n this.GridColumnConfigs = this.BuildColumnConfigsForTable(this.ResolvedTables[0]);\n }\n\n // Initialize paging state for all tables\n for (let i = 0; i < this.ResolvedTables.length; i++) {\n this.tablePageState.set(i, { pageNumber: 1, pageSize: 100, totalRowCount: 0 });\n }\n\n // Set loading early (synchronously) so hasDisplayContent is true immediately\n if (this.ResolvedTables.some(t => t.metadata?.sql) || this.HasInlineData) {\n this.IsLoading = true;\n }\n\n // Load cached metadata and resolve query sync state\n await this.InitQuerySyncState();\n\n // Load data for the first (active) table\n if (this.ResolvedTables.length > 0) {\n await this.LoadTableData(0);\n }\n\n // Signal parent that tabs/display content may have changed after async load\n this.tabsChanged.emit();\n } catch (error) {\n this.HasError = true;\n this.ErrorMessage = error instanceof Error ? error.message : 'Failed to load data';\n }\n }\n\n /**\n * Re-execute the live SQL query for the active table\n */\n public async OnRefresh(): Promise<void> {\n this.tableDataCache.delete(this.ActiveTableIndex);\n await this.LoadTableData(this.ActiveTableIndex);\n }\n\n /**\n * Handle entity link click from the grid and bubble up as openEntityRecord.\n * Converts the grid's recordId string into a CompositeKey for the artifact viewer pipeline.\n */\n public OnEntityLinkClick(event: QueryEntityLinkClickEvent): void {\n const md = new Metadata();\n const entity = md.Entities.find(e => e.Name === event.entityName);\n const pkFieldName = entity?.FirstPrimaryKey?.Name ?? 'ID';\n\n const compositeKey = new CompositeKey([\n new KeyValuePair(pkFieldName, event.recordId)\n ]);\n this.openEntityRecord.emit({\n entityName: event.entityName,\n compositeKey\n });\n }\n\n /**\n * Handle page change from the data grid's embedded pager.\n * Re-executes the query for the active table with new page parameters.\n */\n public async OnPageChange(event: PageChangeEvent): Promise<void> {\n const pageState = this.tablePageState.get(this.ActiveTableIndex);\n if (!pageState) return;\n\n pageState.pageNumber = event.PageNumber;\n pageState.pageSize = event.PageSize;\n\n // Clear cache so it reloads\n this.tableDataCache.delete(this.ActiveTableIndex);\n await this.LoadTableData(this.ActiveTableIndex);\n }\n\n /**\n * Switch to a different table tab.\n * Loads data lazily if not already cached.\n */\n public async OnTableTabClick(index: number): Promise<void> {\n if (index === this.ActiveTableIndex) return;\n this.ActiveTableIndex = index;\n\n const table = this.ResolvedTables[index];\n if (!table) return;\n\n // Use cached column configs or build new\n if (!this.tableColumnConfigsCache.has(index)) {\n const configs = this.BuildColumnConfigsForTable(table);\n if (configs) this.tableColumnConfigsCache.set(index, configs);\n }\n this.GridColumnConfigs = this.tableColumnConfigsCache.get(index) ?? null;\n\n // Use cached data or load fresh\n if (this.tableDataCache.has(index)) {\n this.GridData = this.tableDataCache.get(index)!;\n const pageState = this.tablePageState.get(index)!;\n this.PagerPageNumber = pageState.pageNumber;\n this.PagerPageSize = pageState.pageSize;\n this.PagerTotalRowCount = pageState.totalRowCount;\n } else {\n await this.LoadTableData(index);\n }\n\n this.cdr.detectChanges();\n }\n\n /**\n * Load data for a specific table.\n * Handles live SQL execution, inline rows, and caching.\n */\n private async LoadTableData(tableIndex: number): Promise<void> {\n const table = this.ResolvedTables[tableIndex];\n if (!table) return;\n\n this.IsLoading = true;\n this.HasError = false;\n this.cdr.detectChanges();\n\n try {\n if (table.metadata?.sql) {\n // Live SQL execution\n const pageState = this.tablePageState.get(tableIndex)!;\n const rq = new RunQuery();\n const startRow = (pageState.pageNumber - 1) * pageState.pageSize;\n const result = await rq.RunQuery({\n SQL: table.metadata.sql,\n StartRow: startRow,\n MaxRows: pageState.pageSize\n });\n\n if (result.Success) {\n this.tableDataCache.set(tableIndex, result.Results);\n this.GridData = result.Results;\n this.IsLive = true;\n\n pageState.totalRowCount = result.TotalRowCount ?? result.RowCount ?? 0;\n this.PagerTotalRowCount = pageState.totalRowCount;\n this.PagerPageNumber = pageState.pageNumber;\n this.PagerPageSize = pageState.pageSize;\n\n this.liveRowCount = result.RowCount;\n this.liveExecutionTime = result.ExecutionTime;\n } else {\n this.HandleTableError(tableIndex, result.ErrorMessage || 'Query failed');\n }\n } else if (table.rows && table.rows.length > 0) {\n // Inline data\n this.tableDataCache.set(tableIndex, table.rows);\n this.GridData = table.rows;\n this.liveRowCount = table.rows.length;\n } else {\n this.GridData = [];\n }\n } catch (error) {\n this.HandleTableError(tableIndex, error instanceof Error ? error.message : 'Load failed');\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Build QueryGridColumnConfig[] from a DataTable's column metadata.\n * Returns null if columns have no entity metadata (grid falls back to auto-inference).\n */\n private BuildColumnConfigsForTable(table: DataTable): QueryGridColumnConfig[] | null {\n const columns = table.columns;\n if (!columns?.length) return null;\n\n // Only build if at least one column has entity metadata or type info\n const hasMetadata = columns.some(c => c.sourceEntity || c.sqlBaseType);\n if (!hasMetadata) return null;\n\n const md = new Metadata();\n return columns.map((col, index) => {\n const target = resolveTargetEntity(col.sourceEntity, col.sourceFieldName, md);\n const isEntityLink = !!(target.targetEntityName && (target.isPrimaryKey || target.isForeignKey));\n const baseType = (col.sqlBaseType || 'nvarchar').toLowerCase();\n\n let align: 'left' | 'center' | 'right' = 'left';\n if (['int', 'bigint', 'decimal', 'numeric', 'float', 'money', 'smallmoney', 'real'].includes(baseType)) {\n align = 'right';\n } else if (baseType === 'bit') {\n align = 'center';\n }\n\n // Support both displayName (new) and headerName (legacy) for backward compat\n const colAny = col as unknown as Record<string, unknown>;\n const title = col.displayName || (colAny['headerName'] as string) || col.field;\n\n return {\n field: col.field,\n title,\n visible: true,\n sortable: true,\n resizable: true,\n reorderable: true,\n sqlBaseType: col.sqlBaseType || 'nvarchar',\n sqlFullType: col.sqlFullType || col.sqlBaseType || 'nvarchar',\n align,\n order: index,\n sourceEntityName: col.sourceEntity,\n sourceFieldName: col.sourceFieldName,\n isEntityLink,\n targetEntityName: target.targetEntityName,\n targetEntityId: target.targetEntityId,\n targetEntityIcon: target.targetEntityIcon,\n isPrimaryKey: target.isPrimaryKey,\n isForeignKey: target.isForeignKey,\n pinned: null,\n } as QueryGridColumnConfig;\n });\n }\n\n /**\n * Handle a table load error by setting error state and falling back to inline data\n */\n private HandleTableError(tableIndex: number, message: string): void {\n this.HasError = true;\n this.ErrorMessage = message;\n const table = this.ResolvedTables[tableIndex];\n if (table?.rows && table.rows.length > 0) {\n this.GridData = table.rows;\n }\n }\n\n // ─── Query Sync State ────────────────────────────────────────────\n\n /**\n * Initialize query sync state by loading cached metadata.\n * Resolves the latest version number and compares saved query SQL.\n */\n private async InitQuerySyncState(): Promise<void> {\n // Ensure artifact cache is loaded (not registered for startup)\n await ArtifactMetadataEngine.Instance.Config(false);\n\n this.LatestVersionNumber = this.resolveLatestVersionNumber();\n\n // If cache is stale (doesn't know about the version we're viewing),\n // force-refresh and re-resolve. This happens when new versions are\n // created during a conversation after the cache was first loaded.\n if (this.LatestVersionNumber < this.CurrentVersionNumber) {\n await ArtifactMetadataEngine.Instance.Config(true);\n this.LatestVersionNumber = this.resolveLatestVersionNumber();\n }\n\n this.EffectiveSavedAtVersion = this.resolveEffectiveSavedAtVersion();\n await this.resolveSavedQuerySql();\n this.QuerySyncState = this.computeQuerySyncState();\n }\n\n /**\n * Determine the latest version number for this artifact from cache.\n * Falls back to current version if cache miss.\n */\n private resolveLatestVersionNumber(): number {\n if (!this.artifactVersion?.ArtifactID) {\n return this.CurrentVersionNumber;\n }\n\n const versions = ArtifactMetadataEngine.Instance.GetVersionsForArtifact(this.artifactVersion.ArtifactID);\n if (versions.length > 0) {\n // GetVersionsForArtifact returns DESC sorted\n return versions[0].VersionNumber || 1;\n }\n\n // Cache miss — current version is our best guess\n return this.CurrentVersionNumber;\n }\n\n /**\n * Scan all versions of this artifact to find the most recent savedAtVersionNumber\n * for the same savedQueryId. When viewing an older version, this tells the user\n * where the query was *actually* last updated, not just what this version's\n * snapshot recorded at the time.\n */\n private resolveEffectiveSavedAtVersion(): number | null {\n const queryId = this.spec?.savedQueryId;\n if (!queryId) return null;\n\n // Start with this version's own value\n let effective = this.spec?.savedAtVersionNumber ?? null;\n\n if (!this.artifactVersion?.ArtifactID) return effective;\n\n // GetVersionsForArtifact returns DESC sorted — scan all versions\n const versions = ArtifactMetadataEngine.Instance.GetVersionsForArtifact(this.artifactVersion.ArtifactID);\n for (const v of versions) {\n try {\n if (!v.Content) continue;\n const content = typeof v.Content === 'string' ? JSON.parse(v.Content) : v.Content;\n if (content.savedQueryId === queryId && content.savedAtVersionNumber != null) {\n const vSavedAt = content.savedAtVersionNumber as number;\n if (effective == null || vSavedAt > effective) {\n effective = vSavedAt;\n }\n }\n } catch {\n // Skip versions with unparseable content\n }\n }\n\n return effective;\n }\n\n /**\n * Look up the saved query's SQL from QueryEngine cache for comparison.\n * Only fetches if savedQueryId is present.\n */\n private async resolveSavedQuerySql(): Promise<void> {\n if (!this.spec?.savedQueryId) {\n this.savedQuerySql = null;\n return;\n }\n\n // QueryEngine is registered for startup, should already be loaded\n let query = QueryEngine.Instance.FindQueryByID(this.spec.savedQueryId);\n\n if (!query) {\n // Cache miss — force refresh and retry\n await QueryEngine.Instance.Config(true);\n query = QueryEngine.Instance.FindQueryByID(this.spec.savedQueryId);\n }\n\n this.savedQuerySql = query?.SQL ?? null;\n }\n\n /**\n * Compute the query sync state from current spec, version, and saved query SQL.\n * Implements the decision tree from the UX design.\n */\n private computeQuerySyncState(): QuerySyncState {\n const hasSavedQuery = !!this.spec?.savedQueryId;\n const isLatest = this.IsLatestVersion;\n\n if (!hasSavedQuery) {\n return isLatest ? 'no-query-latest' : 'no-query-older';\n }\n\n // Compare SQL (normalize whitespace for reliable comparison)\n const specSql = this.normalizeSql(this.spec?.metadata?.sql);\n const querySql = this.normalizeSql(this.savedQuerySql);\n const sqlMatches = specSql != null && querySql != null && specSql === querySql;\n\n // Only truly synced if SQL matches AND this is the version it was saved at.\n // Even with identical SQL, a newer version should show the dropdown so the\n // user can update the version association (re-save at current version).\n const savedAtCurrent = this.EffectiveSavedAtVersion === this.CurrentVersionNumber;\n if (sqlMatches && savedAtCurrent) {\n return 'synced';\n }\n\n // SQL differs — determine position relative to saved version\n if (isLatest) {\n return 'outdated-latest';\n }\n\n // Use effective saved-at (looks ahead through newer versions)\n const savedAt = this.EffectiveSavedAtVersion;\n if (savedAt != null && this.CurrentVersionNumber < savedAt) {\n return 'query-ahead'; // query was updated at a newer version\n }\n\n return 'query-behind'; // ahead of saved but not latest\n }\n\n /** Normalize SQL for comparison: trim and collapse whitespace */\n private normalizeSql(sql: string | null | undefined): string | null {\n if (sql == null) return null;\n return sql.trim().replace(/\\s+/g, ' ');\n }\n\n // ─── Actions ────────────────────────────────────────────────────\n\n /** Navigate to the saved query in the Data Explorer's Queries browser */\n public OnOpenSavedQuery(): void {\n if (!this.spec?.savedQueryId) return;\n this.navigationRequest.emit({\n appName: 'Data Explorer',\n navItemName: 'Queries',\n queryParams: { queryId: this.spec.savedQueryId }\n });\n }\n\n /** Show the save panel for creating a brand-new query */\n public OnShowSaveDialog(): void {\n this.ShowSaveDialog = true;\n this.ShowUpdateDropdown = false;\n }\n\n /** Toggle the update query dropdown */\n public OnToggleUpdateDropdown(): void {\n this.ShowUpdateDropdown = !this.ShowUpdateDropdown;\n }\n\n /** Close the dropdown (e.g., on outside click) */\n public OnCloseDropdown(): void {\n this.ShowUpdateDropdown = false;\n }\n\n /**\n * Update the existing saved query's SQL to match this version.\n * Only available from the latest version (Scenario 3).\n */\n public async OnUpdateExistingQuery(): Promise<void> {\n this.ShowUpdateDropdown = false;\n if (!this.spec?.savedQueryId || !this.spec.metadata?.sql) return;\n\n this.IsSaving = true;\n this.SavingMessage = `Updating \"${this.SavedQueryDisplayName}\"...`;\n this.cdr.detectChanges();\n\n try {\n const md = new Metadata();\n const query = await md.GetEntityObject<import('@memberjunction/core-entities').MJQueryEntity>('MJ: Queries');\n const loaded = await query.Load(this.spec.savedQueryId);\n\n if (!loaded) {\n console.error('Failed to load saved query for update');\n return;\n }\n\n query.SQL = this.spec.metadata.sql;\n if (this.spec.plan?.trim()) {\n query.TechnicalDescription = this.spec.plan.trim();\n }\n const saved = await query.Save();\n\n if (saved) {\n // Update spec with new version tracking\n this.spec.savedAtVersionNumber = this.CurrentVersionNumber;\n await this.PersistArtifactContent();\n\n // Refresh caches so future lookups see the updated data\n await QueryEngine.Instance.Config(true);\n await ArtifactMetadataEngine.Instance.Config(true);\n await md.Refresh();\n\n this.savedQuerySql = this.spec.metadata.sql;\n this.EffectiveSavedAtVersion = this.CurrentVersionNumber;\n this.QuerySyncState = 'synced';\n }\n } catch (error) {\n console.error('Failed to update saved query:', error);\n } finally {\n this.IsSaving = false;\n this.cdr.detectChanges();\n }\n }\n\n /**\n * Save as a new query (from the dropdown).\n * Opens the save dialog which creates a fresh query record.\n */\n public OnSaveAsNewQuery(): void {\n this.ShowUpdateDropdown = false;\n this.ShowSaveDialog = true;\n }\n\n /** Handle successful save from the dialog (both initial save and \"save as new\") */\n public async OnQuerySaved(event: SaveQueryResult): Promise<void> {\n this.ShowSaveDialog = false;\n this.IsSaving = true;\n this.SavingMessage = 'Saving query...';\n this.cdr.detectChanges();\n\n try {\n // Update spec with saved query info and version tracking\n this.spec!.savedQueryId = event.queryId;\n this.spec!.savedQueryName = event.queryName;\n this.spec!.savedAtVersionNumber = this.CurrentVersionNumber;\n\n // Persist and refresh caches\n await this.PersistArtifactContent();\n await QueryEngine.Instance.Config(true);\n await ArtifactMetadataEngine.Instance.Config(true);\n await new Metadata().Refresh();\n\n this.savedQuerySql = this.spec!.metadata?.sql ?? null;\n this.EffectiveSavedAtVersion = this.CurrentVersionNumber;\n this.QuerySyncState = 'synced';\n } catch (error) {\n console.error('Failed to save query:', error);\n } finally {\n this.IsSaving = false;\n this.cdr.detectChanges();\n }\n }\n\n /** Persist updated spec back to the artifact version entity */\n private async PersistArtifactContent(): Promise<void> {\n if (!this.artifactVersion || !this.spec) return;\n this.artifactVersion.Content = JSON.stringify(this.spec);\n await this.artifactVersion.Save();\n }\n\n /**\n * Returns a DataSnapshot with live grid data, current page state,\n * and query sync state.\n */\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n if (!this.spec) return null;\n\n const tables = NormalizeToTables(\n this.spec as unknown as Record<string, unknown>,\n this.spec.title || 'Results'\n );\n const activeTable = tables[this.ActiveTableIndex];\n\n if (activeTable) {\n // Override with live data for the active table\n if (this.IsLive) activeTable.rows = this.GridData;\n activeTable.pageNumber = this.PagerPageNumber;\n activeTable.metadata = {\n ...activeTable.metadata,\n ...(this.liveRowCount != null ? { rowCount: this.liveRowCount } : {}),\n ...(this.liveExecutionTime != null\n ? { executionTimeMs: this.liveExecutionTime } : {}),\n ...(this.PagerTotalRowCount > 0\n ? { totalAvailableRows: this.PagerTotalRowCount } : {}),\n pageSize: this.PagerPageSize\n };\n }\n\n return DataSnapshot.FromTables(tables, this.spec.title);\n }\n\n // ─── Tabs ───────────────────────────────────────────────────────\n\n /**\n * Provide Plan tab (markdown), SQL tab (code), and Interpretation tab when available\n */\n public GetAdditionalTabs(): ArtifactViewerTab[] {\n const tabs: ArtifactViewerTab[] = [];\n\n if (this.spec?.plan) {\n tabs.push({\n label: 'Plan',\n icon: 'fa-diagram-project',\n contentType: 'markdown',\n content: this.spec.plan\n });\n }\n\n // SQL tab — multi-table shows all queries with headers\n if (this.IsMultiTable) {\n const multiSql = buildMultiTableSql(this.ResolvedTables);\n if (multiSql) {\n tabs.push({\n label: 'SQL',\n icon: 'fa-database',\n contentType: 'code',\n language: 'sql',\n content: multiSql\n });\n }\n } else if (this.spec?.metadata?.sql) {\n tabs.push({\n label: 'SQL',\n icon: 'fa-database',\n contentType: 'code',\n language: 'sql',\n content: this.spec.metadata.sql\n });\n }\n\n // Interpretation tab\n if (this.spec?.interpretation) {\n tabs.push({\n label: 'Interpretation',\n icon: 'fa-lightbulb',\n contentType: 'markdown',\n content: this.spec.interpretation\n });\n }\n\n return tabs;\n }\n}\n","<div class=\"data-artifact-viewer\" [ngClass]=\"cssClass\">\n @if (spec) {\n @if (HasData || IsLoading || ResolvedTables.length > 0) {\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 → Save Query -->\n @case (\"no-query-latest\") {\n <button class=\"btn-icon btn-save\" title=\"Save as reusable query\" (click)=\"OnShowSaveDialog()\"><i class=\"fas fa-save\"></i> Save Query</button>\n }\n\n <!-- S2: SQL matches → green badge + Open -->\n @case (\"synced\") {\n <span class=\"query-badge query-badge-synced\"> <i class=\"fas fa-check\"></i> Saved at v{{ SavedAtVersion }} </span>\n <button class=\"btn-icon btn-open\" title=\"Open saved query record\" (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S3: SQL differs, latest version → amber badge + dropdown -->\n @case (\"outdated-latest\") {\n <span class=\"query-badge query-badge-outdated\"> <i class=\"fas fa-circle-exclamation\"></i> Saved at v{{ SavedAtVersion }} </span>\n <div class=\"dropdown-wrapper\">\n <button class=\"btn-icon btn-warning\" title=\"Update or save query\" (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\"> <i class=\"fas fa-clock-rotate-left\"></i> Query updated at v{{ SavedAtVersion }} </span>\n <button class=\"btn-icon btn-muted\" title=\"Open saved query record\" (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\"> <i class=\"fas fa-clock-rotate-left\"></i> Saved at v{{ SavedAtVersion }} </span>\n <button class=\"btn-icon btn-muted\" title=\"Open saved query record\" (click)=\"OnOpenSavedQuery()\">\n <i class=\"fas fa-external-link-alt\"></i> Open Query\n </button>\n }\n\n <!-- S6: No saved query, older version → no actions -->\n @case (\"no-query-older\") {\n <!-- No query actions available on older versions -->\n }\n }\n </div>\n </div>\n\n <!-- Multi-table tab strip -->\n @if (IsMultiTable) {\n <div class=\"table-tabs\">\n @for (table of ResolvedTables; track table.name; let i = $index) {\n <button class=\"table-tab\" [class.active]=\"i === ActiveTableIndex\" [title]=\"table.description || table.name\" (click)=\"OnTableTabClick(i)\">\n <span class=\"table-tab-name\">{{ table.name }}</span>\n @if (table.metadata?.rowCount != null || table.rows.length) {\n <span class=\"table-tab-count\"> ({{ table.metadata?.rowCount ?? table.rows.length }} rows) </span>\n }\n </button>\n }\n </div>\n }\n\n <!-- Computations summary bar -->\n @if (spec.computations?.length) {\n <div class=\"computations-bar\">\n @for (comp of spec.computations; track comp.name) {\n @if (!IsMultiTable || !comp.table || comp.table === ActiveTable?.name) {\n <div class=\"computation-chip\" [title]=\"comp.description || comp.name\">\n <span class=\"computation-label\">{{ comp.name }}</span>\n <span class=\"computation-value\">\n {{ comp.formattedValue || comp.value }}\n </span>\n </div>\n }\n }\n </div>\n }\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 >\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 >\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 [data]=\"spec.plan\" [enableMermaid]=\"true\" [enableHighlight]=\"true\" [enableCollapsibleHeadings]=\"false\" [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 >\n </mj-save-query-panel>\n }\n</div>\n"]}
@@ -1,5 +1,6 @@
1
1
  import { OnInit, ChangeDetectorRef } from '@angular/core';
2
2
  import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
3
+ import { DataSnapshot } from '@memberjunction/core';
3
4
  import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
4
5
  import { ArtifactFileService } from '../../services/artifact-file.service';
5
6
  import * as i0 from "@angular/core";
@@ -34,6 +35,7 @@ export declare class DocxArtifactViewerComponent extends BaseArtifactViewerPlugi
34
35
  /** Open a minimal print window containing only the document HTML. */
35
36
  private openPrintWindow;
36
37
  private showError;
38
+ GetCurrentStateSnapshot(): DataSnapshot | null;
37
39
  static ɵfac: i0.ɵɵFactoryDeclaration<DocxArtifactViewerComponent, never>;
38
40
  static ɵcmp: i0.ɵɵComponentDeclaration<DocxArtifactViewerComponent, "mj-docx-artifact-viewer", never, {}, {}, never, never, false, never>;
39
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"docx-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/docx-artifact-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,iBAAiB,EAAmB,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;;AAE3E;;;;;;;;GAQG;AACH,qBAsGa,2BAA4B,SAAQ,iCAAkC,YAAW,MAAM;IAYhG,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IAZN,SAAS,UAAQ;IACjB,aAAa,UAAS;IACtB,YAAY,SAAM;IAClB,QAAQ,EAAE,QAAQ,CAAM;IAE/B,qDAAqD;IACrD,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,WAAW,CAAM;gBAGf,WAAW,EAAE,mBAAmB,EAChC,SAAS,EAAE,YAAY,EACvB,GAAG,EAAE,iBAAiB;IAKhC,IAAoB,iBAAiB,IAAI,OAAO,CAAiB;IAE3D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC,OAAO,IAAI,IAAI;YASR,YAAY;YAuCZ,iBAAiB;YAUjB,kBAAkB;IAQhC,qEAAqE;IACrE,OAAO,CAAC,eAAe;IA6BvB,OAAO,CAAC,SAAS;yCA1IN,2BAA2B;2CAA3B,2BAA2B;CAgJvC"}
1
+ {"version":3,"file":"docx-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/docx-artifact-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAE,iBAAiB,EAAmB,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;;AAE3E;;;;;;;;GAQG;AACH,qBAyGa,2BAA4B,SAAQ,iCAAkC,YAAW,MAAM;IAWhG,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IAZN,SAAS,UAAQ;IACjB,aAAa,UAAS;IACtB,YAAY,SAAM;IAClB,QAAQ,EAAE,QAAQ,CAAM;IAE/B,qDAAqD;IACrD,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,WAAW,CAAM;gBAGf,WAAW,EAAE,mBAAmB,EAChC,SAAS,EAAE,YAAY,EACvB,GAAG,EAAE,iBAAiB;IAKhC,IAAoB,iBAAiB,IAAI,OAAO,CAE/C;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAcjC,OAAO,IAAI,IAAI;YASR,YAAY;YAuCZ,iBAAiB;YAUjB,kBAAkB;IAQhC,qEAAqE;IACrE,OAAO,CAAC,eAAe;IA6BvB,OAAO,CAAC,SAAS;IAMD,uBAAuB,IAAI,YAAY,GAAG,IAAI;yCA9InD,2BAA2B;2CAA3B,2BAA2B;CAyJvC"}
@@ -6,6 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { Component, SecurityContext } from '@angular/core';
8
8
  import { RegisterClass } from '@memberjunction/global';
9
+ import { DataSnapshot } from '@memberjunction/core';
9
10
  import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
10
11
  import * as i0 from "@angular/core";
11
12
  import * as i1 from "../../services/artifact-file.service";
@@ -61,7 +62,9 @@ let DocxArtifactViewerComponent = class DocxArtifactViewerComponent extends Base
61
62
  this.sanitizer = sanitizer;
62
63
  this.cdr = cdr;
63
64
  }
64
- get hasDisplayContent() { return true; }
65
+ get hasDisplayContent() {
66
+ return true;
67
+ }
65
68
  async ngOnInit() {
66
69
  await this.loadDocument();
67
70
  }
@@ -125,7 +128,7 @@ let DocxArtifactViewerComponent = class DocxArtifactViewerComponent extends Base
125
128
  const result = await mammoth.convertToHtml({ arrayBuffer });
126
129
  if (result.messages?.length) {
127
130
  // Log warnings from mammoth (e.g. unsupported features) without breaking display
128
- result.messages.forEach(m => console.warn('[DocxViewer] mammoth:', m.message));
131
+ result.messages.forEach((m) => console.warn('[DocxViewer] mammoth:', m.message));
129
132
  }
130
133
  return result.value;
131
134
  }
@@ -170,6 +173,17 @@ let DocxArtifactViewerComponent = class DocxArtifactViewerComponent extends Base
170
173
  this.errorMessage = message;
171
174
  this.cdr.markForCheck();
172
175
  }
176
+ GetCurrentStateSnapshot() {
177
+ const snap = new DataSnapshot();
178
+ snap.title = this.getDisplayTitle() ?? undefined;
179
+ snap.interpretation = 'Word document (.docx).';
180
+ snap.custom = {
181
+ fileName: this.artifactVersion.FileName ?? undefined,
182
+ mimeType: this.artifactVersion.MimeType ?? 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
183
+ contentMode: this.artifactVersion.ContentMode,
184
+ };
185
+ return snap;
186
+ }
173
187
  static ɵfac = function DocxArtifactViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DocxArtifactViewerComponent)(i0.ɵɵdirectiveInject(i1.ArtifactFileService), i0.ɵɵdirectiveInject(i2.DomSanitizer), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
174
188
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DocxArtifactViewerComponent, selectors: [["mj-docx-artifact-viewer"]], standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 4, consts: [[1, "docx-viewer"], [3, "download", "print", "fileName", "isDownloading", "showPrint"], [1, "docx-viewer__body"], [1, "docx-viewer__state"], [1, "docx-viewer__state", "docx-viewer__state--error"], [1, "docx-viewer__content", 3, "innerHTML"], [1, "fas", "fa-spinner", "fa-spin"], [1, "fas", "fa-exclamation-triangle"]], template: function DocxArtifactViewerComponent_Template(rf, ctx) { if (rf & 1) {
175
189
  i0.ɵɵelementStart(0, "div", 0)(1, "mj-file-artifact-toolbar", 1);
@@ -183,7 +197,7 @@ let DocxArtifactViewerComponent = class DocxArtifactViewerComponent extends Base
183
197
  i0.ɵɵproperty("fileName", (ctx.artifactVersion == null ? null : ctx.artifactVersion.FileName) || "document.docx")("isDownloading", ctx.isDownloading)("showPrint", true);
184
198
  i0.ɵɵadvance(2);
185
199
  i0.ɵɵconditional(ctx.isLoading ? 3 : ctx.errorMessage ? 4 : 5);
186
- } }, dependencies: [i3.FileArtifactToolbarComponent], styles: [".docx-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .docx-viewer__body[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n\n .docx-viewer__state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 100%;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .docx-viewer__state--error[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] {\n padding: 32px 48px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.7;\n }\n\n \n\n .docx-viewer__content[_ngcontent-%COMP%] :is(h1[_ngcontent-%COMP%], h2[_ngcontent-%COMP%], h3[_ngcontent-%COMP%], h4[_ngcontent-%COMP%], h5[_ngcontent-%COMP%], h6[_ngcontent-%COMP%]) {\n color: var(--mj-text-primary);\n margin-top: 1.5em;\n margin-bottom: 0.5em;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] :is(td[_ngcontent-%COMP%], th[_ngcontent-%COMP%]) {\n border: 1px solid var(--mj-border-default);\n padding: 6px 10px;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--mj-text-link);\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n max-width: 100%;\n height: auto;\n }"] });
200
+ } }, dependencies: [i3.FileArtifactToolbarComponent], styles: [".docx-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .docx-viewer__body[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n\n .docx-viewer__state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 100%;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .docx-viewer__state--error[_ngcontent-%COMP%] {\n color: var(--mj-status-error-text);\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] {\n padding: 32px 48px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.7;\n }\n\n \n\n .docx-viewer__content[_ngcontent-%COMP%] :is(h1[_ngcontent-%COMP%], h2[_ngcontent-%COMP%], h3[_ngcontent-%COMP%], h4[_ngcontent-%COMP%], h5[_ngcontent-%COMP%], h6[_ngcontent-%COMP%]) {\n color: var(--mj-text-primary);\n margin-top: 1.5em;\n margin-bottom: 0.5em;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] :is(td[_ngcontent-%COMP%], th[_ngcontent-%COMP%]) {\n border: 1px solid var(--mj-border-default);\n padding: 6px 10px;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] a[_ngcontent-%COMP%] {\n color: var(--mj-text-link);\n }\n\n .docx-viewer__content[_ngcontent-%COMP%] img[_ngcontent-%COMP%] {\n max-width: 100%;\n height: auto;\n }"] });
187
201
  };
188
202
  DocxArtifactViewerComponent = __decorate([
189
203
  RegisterClass(BaseArtifactViewerPluginComponent, 'DocxArtifactViewerPlugin')
@@ -198,7 +212,8 @@ export { DocxArtifactViewerComponent };
198
212
  [isDownloading]="isDownloading"
199
213
  [showPrint]="true"
200
214
  (download)="onDownload()"
201
- (print)="onPrint()">
215
+ (print)="onPrint()"
216
+ >
202
217
  </mj-file-artifact-toolbar>
203
218
 
204
219
  <div class="docx-viewer__body">
@@ -217,7 +232,7 @@ export { DocxArtifactViewerComponent };
217
232
  }
218
233
  </div>
219
234
  </div>
220
- `, styles: ["\n .docx-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .docx-viewer__body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n\n .docx-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 100%;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .docx-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n\n .docx-viewer__content {\n padding: 32px 48px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.7;\n }\n\n /* Normalize headings produced by mammoth */\n .docx-viewer__content :is(h1, h2, h3, h4, h5, h6) {\n color: var(--mj-text-primary);\n margin-top: 1.5em;\n margin-bottom: 0.5em;\n }\n\n .docx-viewer__content table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .docx-viewer__content :is(td, th) {\n border: 1px solid var(--mj-border-default);\n padding: 6px 10px;\n }\n\n .docx-viewer__content th {\n background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n\n .docx-viewer__content a {\n color: var(--mj-text-link);\n }\n\n .docx-viewer__content img {\n max-width: 100%;\n height: auto;\n }\n "] }]
235
+ `, styles: ["\n .docx-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .docx-viewer__body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n\n .docx-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 100%;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .docx-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n\n .docx-viewer__content {\n padding: 32px 48px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.7;\n }\n\n /* Normalize headings produced by mammoth */\n .docx-viewer__content :is(h1, h2, h3, h4, h5, h6) {\n color: var(--mj-text-primary);\n margin-top: 1.5em;\n margin-bottom: 0.5em;\n }\n\n .docx-viewer__content table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .docx-viewer__content :is(td, th) {\n border: 1px solid var(--mj-border-default);\n padding: 6px 10px;\n }\n\n .docx-viewer__content th {\n background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n\n .docx-viewer__content a {\n color: var(--mj-text-link);\n }\n\n .docx-viewer__content img {\n max-width: 100%;\n height: auto;\n }\n "] }]
221
236
  }], () => [{ type: i1.ArtifactFileService }, { type: i2.DomSanitizer }, { type: i0.ChangeDetectorRef }], null); })();
222
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DocxArtifactViewerComponent, { className: "DocxArtifactViewerComponent", filePath: "src/lib/components/plugins/docx-artifact-viewer.component.ts", lineNumber: 118 }); })();
237
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DocxArtifactViewerComponent, { className: "DocxArtifactViewerComponent", filePath: "src/lib/components/plugins/docx-artifact-viewer.component.ts", lineNumber: 122 }); })();
223
238
  //# sourceMappingURL=docx-artifact-viewer.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"docx-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/docx-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ChangeDetectorRef, SecurityContext } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\nimport { ArtifactFileService } from '../../services/artifact-file.service';\n\n/**\n * Viewer plugin for Word (DOCX) artifact versions stored in MJStorage.\n *\n * Downloads the binary file, converts it to HTML using mammoth.js, then\n * sanitizes the HTML before binding it with [innerHTML].\n *\n * Printing opens the sanitized content in a child window so the browser's\n * native print dialog renders the Word document faithfully.\n */\n@Component({\n standalone: false,\n selector: 'mj-docx-artifact-viewer',\n template: `\n <div class=\"docx-viewer\">\n <mj-file-artifact-toolbar\n [fileName]=\"artifactVersion?.FileName || 'document.docx'\"\n [isDownloading]=\"isDownloading\"\n [showPrint]=\"true\"\n (download)=\"onDownload()\"\n (print)=\"onPrint()\">\n </mj-file-artifact-toolbar>\n\n <div class=\"docx-viewer__body\">\n @if (isLoading) {\n <div class=\"docx-viewer__state\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading document…</span>\n </div>\n } @else if (errorMessage) {\n <div class=\"docx-viewer__state docx-viewer__state--error\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else {\n <div class=\"docx-viewer__content\" [innerHTML]=\"safeHtml\"></div>\n }\n </div>\n </div>\n `,\n styles: [`\n .docx-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .docx-viewer__body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n\n .docx-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 100%;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .docx-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n\n .docx-viewer__content {\n padding: 32px 48px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.7;\n }\n\n /* Normalize headings produced by mammoth */\n .docx-viewer__content :is(h1, h2, h3, h4, h5, h6) {\n color: var(--mj-text-primary);\n margin-top: 1.5em;\n margin-bottom: 0.5em;\n }\n\n .docx-viewer__content table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .docx-viewer__content :is(td, th) {\n border: 1px solid var(--mj-border-default);\n padding: 6px 10px;\n }\n\n .docx-viewer__content th {\n background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n\n .docx-viewer__content a {\n color: var(--mj-text-link);\n }\n\n .docx-viewer__content img {\n max-width: 100%;\n height: auto;\n }\n `]\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'DocxArtifactViewerPlugin')\nexport class DocxArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {\n\n public isLoading = true;\n public isDownloading = false;\n public errorMessage = '';\n public safeHtml: SafeHtml = '';\n\n /** Raw HTML produced by mammoth — kept for print. */\n private rawHtml = '';\n private downloadUrl = '';\n\n constructor(\n private fileService: ArtifactFileService,\n private sanitizer: DomSanitizer,\n private cdr: ChangeDetectorRef,\n ) {\n super();\n }\n\n public override get hasDisplayContent(): boolean { return true; }\n\n async ngOnInit(): Promise<void> {\n await this.loadDocument();\n }\n\n public async onDownload(): Promise<void> {\n if (!this.downloadUrl || this.isDownloading) {\n return;\n }\n this.isDownloading = true;\n this.cdr.markForCheck();\n try {\n await this.triggerBrowserDownload(\n this.downloadUrl,\n this.artifactVersion?.FileName || 'document.docx',\n );\n } finally {\n this.isDownloading = false;\n this.cdr.markForCheck();\n }\n }\n\n public onPrint(): void {\n if (!this.rawHtml) {\n return;\n }\n this.openPrintWindow(this.rawHtml);\n }\n\n // ─── Private helpers ────────────────────────────────────────────────────────\n\n private async loadDocument(): Promise<void> {\n if (!this.artifactVersion?.ID) {\n this.showError('No artifact version provided.');\n return;\n }\n\n try {\n let arrayBuffer: ArrayBuffer;\n\n if (this.artifactVersion.ContentMode === 'File') {\n // File-backed: download from storage via pre-auth URL\n this.downloadUrl = await this.fileService.getDownloadUrl(this.artifactVersion.ID);\n arrayBuffer = await this.fetchAsArrayBuffer(this.downloadUrl);\n } else {\n // Inline: content is a base64 data URL stored in the artifact version\n const content = this.artifactVersion.Content;\n if (!content) {\n this.showError('Artifact has no content.');\n return;\n }\n arrayBuffer = this.fileService.dataUrlToArrayBuffer(content);\n // Create an object URL for download support\n this.downloadUrl = this.fileService.dataUrlToObjectUrl(\n content,\n this.artifactVersion.MimeType || 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'\n );\n }\n\n const html = await this.convertDocxToHtml(arrayBuffer);\n this.rawHtml = html;\n const sanitized = this.sanitizer.sanitize(SecurityContext.HTML, html) ?? '';\n this.safeHtml = sanitized;\n this.isLoading = false;\n this.cdr.markForCheck();\n } catch (err) {\n this.showError(`Could not load document: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n private async convertDocxToHtml(arrayBuffer: ArrayBuffer): Promise<string> {\n const mammoth = await import('mammoth');\n const result = await mammoth.convertToHtml({ arrayBuffer });\n if (result.messages?.length) {\n // Log warnings from mammoth (e.g. unsupported features) without breaking display\n result.messages.forEach(m => console.warn('[DocxViewer] mammoth:', m.message));\n }\n return result.value;\n }\n\n private async fetchAsArrayBuffer(url: string): Promise<ArrayBuffer> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} fetching file`);\n }\n return response.arrayBuffer();\n }\n\n /** Open a minimal print window containing only the document HTML. */\n private openPrintWindow(html: string): void {\n const printWindow = window.open('', '_blank', 'width=900,height=700');\n if (!printWindow) {\n console.warn('[DocxViewer] Popup was blocked — cannot print');\n return;\n }\n printWindow.document.write(`\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>${this.artifactVersion?.FileName ?? 'Document'}</title>\n <style>\n body { font-family: Georgia, serif; font-size: 13pt; line-height: 1.6; margin: 2cm; color: #000; }\n table { border-collapse: collapse; width: 100%; }\n td, th { border: 1px solid #999; padding: 4px 8px; }\n th { background: #eee; font-weight: bold; }\n img { max-width: 100%; }\n </style>\n </head>\n <body>${html}</body>\n </html>\n `);\n printWindow.document.close();\n printWindow.focus();\n printWindow.print();\n printWindow.close();\n }\n\n private showError(message: string): void {\n this.isLoading = false;\n this.errorMessage = message;\n this.cdr.markForCheck();\n }\n\n}\n\n"]}
1
+ {"version":3,"file":"docx-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/docx-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, ChangeDetectorRef, SecurityContext } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { RegisterClass } from '@memberjunction/global';\nimport { DataSnapshot } from '@memberjunction/core';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\nimport { ArtifactFileService } from '../../services/artifact-file.service';\n\n/**\n * Viewer plugin for Word (DOCX) artifact versions stored in MJStorage.\n *\n * Downloads the binary file, converts it to HTML using mammoth.js, then\n * sanitizes the HTML before binding it with [innerHTML].\n *\n * Printing opens the sanitized content in a child window so the browser's\n * native print dialog renders the Word document faithfully.\n */\n@Component({\n standalone: false,\n selector: 'mj-docx-artifact-viewer',\n template: `\n <div class=\"docx-viewer\">\n <mj-file-artifact-toolbar\n [fileName]=\"artifactVersion?.FileName || 'document.docx'\"\n [isDownloading]=\"isDownloading\"\n [showPrint]=\"true\"\n (download)=\"onDownload()\"\n (print)=\"onPrint()\"\n >\n </mj-file-artifact-toolbar>\n\n <div class=\"docx-viewer__body\">\n @if (isLoading) {\n <div class=\"docx-viewer__state\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading document…</span>\n </div>\n } @else if (errorMessage) {\n <div class=\"docx-viewer__state docx-viewer__state--error\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else {\n <div class=\"docx-viewer__content\" [innerHTML]=\"safeHtml\"></div>\n }\n </div>\n </div>\n `,\n styles: [\n `\n .docx-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface);\n }\n\n .docx-viewer__body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n\n .docx-viewer__state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 100%;\n color: var(--mj-text-muted);\n font-size: 14px;\n }\n\n .docx-viewer__state--error {\n color: var(--mj-status-error-text);\n }\n\n .docx-viewer__content {\n padding: 32px 48px;\n max-width: 900px;\n margin: 0 auto;\n color: var(--mj-text-primary);\n font-size: 14px;\n line-height: 1.7;\n }\n\n /* Normalize headings produced by mammoth */\n .docx-viewer__content :is(h1, h2, h3, h4, h5, h6) {\n color: var(--mj-text-primary);\n margin-top: 1.5em;\n margin-bottom: 0.5em;\n }\n\n .docx-viewer__content table {\n border-collapse: collapse;\n width: 100%;\n margin: 1em 0;\n }\n\n .docx-viewer__content :is(td, th) {\n border: 1px solid var(--mj-border-default);\n padding: 6px 10px;\n }\n\n .docx-viewer__content th {\n background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n\n .docx-viewer__content a {\n color: var(--mj-text-link);\n }\n\n .docx-viewer__content img {\n max-width: 100%;\n height: auto;\n }\n `,\n ],\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'DocxArtifactViewerPlugin')\nexport class DocxArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {\n public isLoading = true;\n public isDownloading = false;\n public errorMessage = '';\n public safeHtml: SafeHtml = '';\n\n /** Raw HTML produced by mammoth — kept for print. */\n private rawHtml = '';\n private downloadUrl = '';\n\n constructor(\n private fileService: ArtifactFileService,\n private sanitizer: DomSanitizer,\n private cdr: ChangeDetectorRef,\n ) {\n super();\n }\n\n public override get hasDisplayContent(): boolean {\n return true;\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadDocument();\n }\n\n public async onDownload(): Promise<void> {\n if (!this.downloadUrl || this.isDownloading) {\n return;\n }\n this.isDownloading = true;\n this.cdr.markForCheck();\n try {\n await this.triggerBrowserDownload(this.downloadUrl, this.artifactVersion?.FileName || 'document.docx');\n } finally {\n this.isDownloading = false;\n this.cdr.markForCheck();\n }\n }\n\n public onPrint(): void {\n if (!this.rawHtml) {\n return;\n }\n this.openPrintWindow(this.rawHtml);\n }\n\n // ─── Private helpers ────────────────────────────────────────────────────────\n\n private async loadDocument(): Promise<void> {\n if (!this.artifactVersion?.ID) {\n this.showError('No artifact version provided.');\n return;\n }\n\n try {\n let arrayBuffer: ArrayBuffer;\n\n if (this.artifactVersion.ContentMode === 'File') {\n // File-backed: download from storage via pre-auth URL\n this.downloadUrl = await this.fileService.getDownloadUrl(this.artifactVersion.ID);\n arrayBuffer = await this.fetchAsArrayBuffer(this.downloadUrl);\n } else {\n // Inline: content is a base64 data URL stored in the artifact version\n const content = this.artifactVersion.Content;\n if (!content) {\n this.showError('Artifact has no content.');\n return;\n }\n arrayBuffer = this.fileService.dataUrlToArrayBuffer(content);\n // Create an object URL for download support\n this.downloadUrl = this.fileService.dataUrlToObjectUrl(\n content,\n this.artifactVersion.MimeType || 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n );\n }\n\n const html = await this.convertDocxToHtml(arrayBuffer);\n this.rawHtml = html;\n const sanitized = this.sanitizer.sanitize(SecurityContext.HTML, html) ?? '';\n this.safeHtml = sanitized;\n this.isLoading = false;\n this.cdr.markForCheck();\n } catch (err) {\n this.showError(`Could not load document: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n private async convertDocxToHtml(arrayBuffer: ArrayBuffer): Promise<string> {\n const mammoth = await import('mammoth');\n const result = await mammoth.convertToHtml({ arrayBuffer });\n if (result.messages?.length) {\n // Log warnings from mammoth (e.g. unsupported features) without breaking display\n result.messages.forEach((m) => console.warn('[DocxViewer] mammoth:', m.message));\n }\n return result.value;\n }\n\n private async fetchAsArrayBuffer(url: string): Promise<ArrayBuffer> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} fetching file`);\n }\n return response.arrayBuffer();\n }\n\n /** Open a minimal print window containing only the document HTML. */\n private openPrintWindow(html: string): void {\n const printWindow = window.open('', '_blank', 'width=900,height=700');\n if (!printWindow) {\n console.warn('[DocxViewer] Popup was blocked — cannot print');\n return;\n }\n printWindow.document.write(`\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>${this.artifactVersion?.FileName ?? 'Document'}</title>\n <style>\n body { font-family: Georgia, serif; font-size: 13pt; line-height: 1.6; margin: 2cm; color: #000; }\n table { border-collapse: collapse; width: 100%; }\n td, th { border: 1px solid #999; padding: 4px 8px; }\n th { background: #eee; font-weight: bold; }\n img { max-width: 100%; }\n </style>\n </head>\n <body>${html}</body>\n </html>\n `);\n printWindow.document.close();\n printWindow.focus();\n printWindow.print();\n printWindow.close();\n }\n\n private showError(message: string): void {\n this.isLoading = false;\n this.errorMessage = message;\n this.cdr.markForCheck();\n }\n\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n const snap = new DataSnapshot();\n snap.title = this.getDisplayTitle() ?? undefined;\n snap.interpretation = 'Word document (.docx).';\n snap.custom = {\n fileName: this.artifactVersion.FileName ?? undefined,\n mimeType: this.artifactVersion.MimeType ?? 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n contentMode: this.artifactVersion.ContentMode,\n };\n return snap;\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
2
+ import { DataSnapshot } from '@memberjunction/core';
2
3
  import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
3
4
  import * as i0 from "@angular/core";
4
5
  /**
@@ -15,6 +16,7 @@ export declare class HtmlArtifactViewerComponent extends BaseArtifactViewerPlugi
15
16
  get hasDisplayContent(): boolean;
16
17
  constructor(sanitizer: DomSanitizer);
17
18
  ngOnInit(): void;
19
+ GetCurrentStateSnapshot(): DataSnapshot | null;
18
20
  onCopy(): void;
19
21
  static ɵfac: i0.ɵɵFactoryDeclaration<HtmlArtifactViewerComponent, never>;
20
22
  static ɵcmp: i0.ɵɵComponentDeclaration<HtmlArtifactViewerComponent, "mj-html-artifact-viewer", never, {}, {}, never, never, false, never>;
@@ -1 +1 @@
1
- {"version":3,"file":"html-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/html-artifact-viewer.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;;AAEtF;;GAEG;AACH,qBAwFa,2BAA4B,SAAQ,iCAAiC;IAYpE,OAAO,CAAC,SAAS;IAXtB,WAAW,SAAM;IACjB,eAAe,EAAE,QAAQ,CAAM;IAC/B,QAAQ,EAAE,SAAS,GAAG,QAAQ,CAAa;IAElD;;OAEG;IACH,IAAoB,iBAAiB,IAAI,OAAO,CAE/C;gBAEmB,SAAS,EAAE,YAAY;IAI3C,QAAQ,IAAI,IAAI;IAqBhB,MAAM,IAAI,IAAI;yCArCH,2BAA2B;2CAA3B,2BAA2B;CA8CvC"}
1
+ {"version":3,"file":"html-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/html-artifact-viewer.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;;AAEtF;;GAEG;AACH,qBAwFa,2BAA4B,SAAQ,iCAAiC;IAYpE,OAAO,CAAC,SAAS;IAXtB,WAAW,SAAM;IACjB,eAAe,EAAE,QAAQ,CAAM;IAC/B,QAAQ,EAAE,SAAS,GAAG,QAAQ,CAAa;IAElD;;OAEG;IACH,IAAoB,iBAAiB,IAAI,OAAO,CAE/C;gBAEmB,SAAS,EAAE,YAAY;IAI3C,QAAQ,IAAI,IAAI;IAqBA,uBAAuB,IAAI,YAAY,GAAG,IAAI;IAS9D,MAAM,IAAI,IAAI;yCA9CH,2BAA2B;2CAA3B,2BAA2B;CAuDvC"}
@@ -5,6 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { Component } from '@angular/core';
8
+ import { DataSnapshot } from '@memberjunction/core';
8
9
  import { RegisterClass } from '@memberjunction/global';
9
10
  import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
10
11
  import * as i0 from "@angular/core";
@@ -65,6 +66,15 @@ let HtmlArtifactViewerComponent = class HtmlArtifactViewerComponent extends Base
65
66
  this.htmlContent = content;
66
67
  this.safeHtmlContent = this.sanitizer.sanitize(1, this.htmlContent) || '';
67
68
  }
69
+ GetCurrentStateSnapshot() {
70
+ const content = this.getRawContent();
71
+ if (!content)
72
+ return null;
73
+ const snap = new DataSnapshot();
74
+ snap.title = this.getDisplayTitle() ?? undefined;
75
+ snap.custom = { content };
76
+ return snap;
77
+ }
68
78
  onCopy() {
69
79
  if (this.htmlContent) {
70
80
  navigator.clipboard.writeText(this.htmlContent).then(() => {
@@ -142,5 +152,5 @@ export { HtmlArtifactViewerComponent };
142
152
  </div>
143
153
  `, styles: ["\n .html-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .html-toolbar {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n padding: 8px;\n background: #f5f5f5;\n border-bottom: 1px solid #ddd;\n }\n\n .btn-icon {\n padding: 6px 12px;\n background: white;\n border: 1px solid #ccc;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .btn-icon:hover {\n background: #e9ecef;\n border-color: #999;\n }\n\n .btn-icon.active {\n background: #007acc;\n color: white;\n border-color: #007acc;\n }\n\n .html-content-container {\n flex: 1;\n overflow: auto;\n }\n\n .html-preview {\n padding: 20px;\n background: white;\n height: 100%;\n overflow: auto;\n }\n "] }]
144
154
  }], () => [{ type: i1.DomSanitizer }], null); })();
145
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(HtmlArtifactViewerComponent, { className: "HtmlArtifactViewerComponent", filePath: "src/lib/components/plugins/html-artifact-viewer.component.ts", lineNumber: 97 }); })();
155
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(HtmlArtifactViewerComponent, { className: "HtmlArtifactViewerComponent", filePath: "src/lib/components/plugins/html-artifact-viewer.component.ts", lineNumber: 98 }); })();
146
156
  //# sourceMappingURL=html-artifact-viewer.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/html-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\n\n/**\n * Viewer component for HTML artifacts\n */\n@Component({\n standalone: false,\n selector: 'mj-html-artifact-viewer',\n template: `\n <div class=\"html-artifact-viewer\" [ngClass]=\"cssClass\">\n <div class=\"html-toolbar\">\n <button class=\"btn-icon\" [class.active]=\"viewMode === 'preview'\"\n title=\"Preview\" (click)=\"viewMode = 'preview'\">\n <i class=\"fas fa-eye\"></i> Preview\n </button>\n <button class=\"btn-icon\" [class.active]=\"viewMode === 'source'\"\n title=\"Source\" (click)=\"viewMode = 'source'\">\n <i class=\"fas fa-code\"></i> Source\n </button>\n <button class=\"btn-icon\" title=\"Copy HTML\" (click)=\"onCopy()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"html-content-container\">\n @if (viewMode === 'preview') {\n <div class=\"html-preview\">\n <div [innerHTML]=\"safeHtmlContent\"></div>\n </div>\n } @else {\n <mj-code-editor\n [(ngModel)]=\"htmlContent\"\n [language]=\"'html'\"\n [readonly]=\"readonly\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n }\n </div>\n </div>\n `,\n styles: [`\n .html-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .html-toolbar {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n padding: 8px;\n background: #f5f5f5;\n border-bottom: 1px solid #ddd;\n }\n\n .btn-icon {\n padding: 6px 12px;\n background: white;\n border: 1px solid #ccc;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .btn-icon:hover {\n background: #e9ecef;\n border-color: #999;\n }\n\n .btn-icon.active {\n background: #007acc;\n color: white;\n border-color: #007acc;\n }\n\n .html-content-container {\n flex: 1;\n overflow: auto;\n }\n\n .html-preview {\n padding: 20px;\n background: white;\n height: 100%;\n overflow: auto;\n }\n `]\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'HtmlArtifactViewerPlugin')\nexport class HtmlArtifactViewerComponent extends BaseArtifactViewerPluginComponent {\n public htmlContent = '';\n public safeHtmlContent: SafeHtml = '';\n public viewMode: 'preview' | 'source' = 'preview';\n\n /**\n * HTML artifacts always have content to display\n */\n public override get hasDisplayContent(): boolean {\n return true;\n }\n\n constructor(private sanitizer: DomSanitizer) {\n super();\n }\n\n ngOnInit(): void {\n // Get content and clean up double-escaped characters that can appear in LLM-generated HTML\n // These appear as literal \"\\\\n\", \"\\\\t\", \"\\\\\\\"\" in the string and cause rendering issues\n let content = this.getContent();\n\n // Remove escaped quotes (\\\" becomes \")\n content = content.replace(/\\\\\"/g, '\"');\n\n // Remove double-escaped newlines (\\\\n becomes nothing)\n // HTML doesn't need whitespace for formatting, and these cause display issues\n content = content.replace(/\\\\n/g, '');\n content = content.replace(/\\\\\\\\n/g, '');\n\n // Also remove double-escaped tabs if present\n content = content.replace(/\\\\t/g, '');\n content = content.replace(/\\\\\\\\t/g, '');\n\n this.htmlContent = content;\n this.safeHtmlContent = this.sanitizer.sanitize(1, this.htmlContent) || '';\n }\n\n onCopy(): void {\n if (this.htmlContent) {\n navigator.clipboard.writeText(this.htmlContent).then(() => {\n console.log('✅ Copied HTML to clipboard');\n }).catch(err => {\n console.error('Failed to copy to clipboard:', err);\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"html-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/html-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { DataSnapshot } from '@memberjunction/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\n\n/**\n * Viewer component for HTML artifacts\n */\n@Component({\n standalone: false,\n selector: 'mj-html-artifact-viewer',\n template: `\n <div class=\"html-artifact-viewer\" [ngClass]=\"cssClass\">\n <div class=\"html-toolbar\">\n <button class=\"btn-icon\" [class.active]=\"viewMode === 'preview'\"\n title=\"Preview\" (click)=\"viewMode = 'preview'\">\n <i class=\"fas fa-eye\"></i> Preview\n </button>\n <button class=\"btn-icon\" [class.active]=\"viewMode === 'source'\"\n title=\"Source\" (click)=\"viewMode = 'source'\">\n <i class=\"fas fa-code\"></i> Source\n </button>\n <button class=\"btn-icon\" title=\"Copy HTML\" (click)=\"onCopy()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"html-content-container\">\n @if (viewMode === 'preview') {\n <div class=\"html-preview\">\n <div [innerHTML]=\"safeHtmlContent\"></div>\n </div>\n } @else {\n <mj-code-editor\n [(ngModel)]=\"htmlContent\"\n [language]=\"'html'\"\n [readonly]=\"readonly\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n }\n </div>\n </div>\n `,\n styles: [`\n .html-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .html-toolbar {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n padding: 8px;\n background: #f5f5f5;\n border-bottom: 1px solid #ddd;\n }\n\n .btn-icon {\n padding: 6px 12px;\n background: white;\n border: 1px solid #ccc;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .btn-icon:hover {\n background: #e9ecef;\n border-color: #999;\n }\n\n .btn-icon.active {\n background: #007acc;\n color: white;\n border-color: #007acc;\n }\n\n .html-content-container {\n flex: 1;\n overflow: auto;\n }\n\n .html-preview {\n padding: 20px;\n background: white;\n height: 100%;\n overflow: auto;\n }\n `]\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'HtmlArtifactViewerPlugin')\nexport class HtmlArtifactViewerComponent extends BaseArtifactViewerPluginComponent {\n public htmlContent = '';\n public safeHtmlContent: SafeHtml = '';\n public viewMode: 'preview' | 'source' = 'preview';\n\n /**\n * HTML artifacts always have content to display\n */\n public override get hasDisplayContent(): boolean {\n return true;\n }\n\n constructor(private sanitizer: DomSanitizer) {\n super();\n }\n\n ngOnInit(): void {\n // Get content and clean up double-escaped characters that can appear in LLM-generated HTML\n // These appear as literal \"\\\\n\", \"\\\\t\", \"\\\\\\\"\" in the string and cause rendering issues\n let content = this.getContent();\n\n // Remove escaped quotes (\\\" becomes \")\n content = content.replace(/\\\\\"/g, '\"');\n\n // Remove double-escaped newlines (\\\\n becomes nothing)\n // HTML doesn't need whitespace for formatting, and these cause display issues\n content = content.replace(/\\\\n/g, '');\n content = content.replace(/\\\\\\\\n/g, '');\n\n // Also remove double-escaped tabs if present\n content = content.replace(/\\\\t/g, '');\n content = content.replace(/\\\\\\\\t/g, '');\n\n this.htmlContent = content;\n this.safeHtmlContent = this.sanitizer.sanitize(1, this.htmlContent) || '';\n }\n\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n const content = this.getRawContent();\n if (!content) return null;\n const snap = new DataSnapshot();\n snap.title = this.getDisplayTitle() ?? undefined;\n snap.custom = { content };\n return snap;\n }\n\n onCopy(): void {\n if (this.htmlContent) {\n navigator.clipboard.writeText(this.htmlContent).then(() => {\n console.log('✅ Copied HTML to clipboard');\n }).catch(err => {\n console.error('Failed to copy to clipboard:', err);\n });\n }\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { OnInit, OnDestroy, ChangeDetectorRef, ElementRef } from '@angular/core';
2
2
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
3
3
  import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
4
+ import { DataSnapshot } from '@memberjunction/core';
4
5
  import * as i0 from "@angular/core";
5
6
  /**
6
7
  * Viewer component for JSON artifacts.
@@ -42,6 +43,7 @@ export declare class JsonArtifactViewerComponent extends BaseArtifactViewerPlugi
42
43
  openInNewWindow(): void;
43
44
  printHtml(): void;
44
45
  onCopy(): void;
46
+ GetCurrentStateSnapshot(): DataSnapshot | null;
45
47
  /**
46
48
  * Clean up double-escaped characters that appear in LLM-generated HTML
47
49
  * Removes literal "\\n", "\\t", and "\\\"" which cause rendering issues