@memberjunction/ng-artifacts 6.1.4 → 6.2.0-edge.1

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 (125) hide show
  1. package/dist/lib/components/artifact-message-card.component.d.ts +60 -8
  2. package/dist/lib/components/artifact-message-card.component.d.ts.map +1 -1
  3. package/dist/lib/components/artifact-message-card.component.js +135 -39
  4. package/dist/lib/components/artifact-message-card.component.js.map +1 -1
  5. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts +58 -6
  6. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact-type-plugin-viewer.component.js +113 -35
  8. package/dist/lib/components/artifact-type-plugin-viewer.component.js.map +1 -1
  9. package/dist/lib/components/artifact-version-download.d.ts +5 -3
  10. package/dist/lib/components/artifact-version-download.d.ts.map +1 -1
  11. package/dist/lib/components/artifact-version-download.js +11 -7
  12. package/dist/lib/components/artifact-version-download.js.map +1 -1
  13. package/dist/lib/components/artifact-version-history.component.d.ts +74 -8
  14. package/dist/lib/components/artifact-version-history.component.d.ts.map +1 -1
  15. package/dist/lib/components/artifact-version-history.component.js +152 -34
  16. package/dist/lib/components/artifact-version-history.component.js.map +1 -1
  17. package/dist/lib/components/artifact-viewer-panel.component.d.ts +328 -35
  18. package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
  19. package/dist/lib/components/artifact-viewer-panel.component.js +701 -213
  20. package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
  21. package/dist/lib/components/file-artifact-toolbar.component.d.ts +112 -10
  22. package/dist/lib/components/file-artifact-toolbar.component.d.ts.map +1 -1
  23. package/dist/lib/components/file-artifact-toolbar.component.js +197 -23
  24. package/dist/lib/components/file-artifact-toolbar.component.js.map +1 -1
  25. package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts +9 -1
  26. package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts.map +1 -1
  27. package/dist/lib/components/plugins/audio-artifact-viewer.component.js +20 -4
  28. package/dist/lib/components/plugins/audio-artifact-viewer.component.js.map +1 -1
  29. package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts +23 -5
  30. package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts.map +1 -1
  31. package/dist/lib/components/plugins/code-artifact-viewer.component.js +69 -31
  32. package/dist/lib/components/plugins/code-artifact-viewer.component.js.map +1 -1
  33. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +136 -18
  34. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
  35. package/dist/lib/components/plugins/component-artifact-viewer.component.js +285 -97
  36. package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
  37. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts +2 -2
  38. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +7 -7
  39. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -1
  40. package/dist/lib/components/plugins/component-permission-evaluation.d.ts +2 -0
  41. package/dist/lib/components/plugins/component-permission-evaluation.d.ts.map +1 -1
  42. package/dist/lib/components/plugins/component-permission-evaluation.js +6 -2
  43. package/dist/lib/components/plugins/component-permission-evaluation.js.map +1 -1
  44. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts +17 -6
  45. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
  46. package/dist/lib/components/plugins/data-artifact-viewer.component.js +32 -22
  47. package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
  48. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.d.ts +56 -4
  49. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.d.ts.map +1 -1
  50. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js +142 -36
  51. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js.map +1 -1
  52. package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts +14 -2
  53. package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts.map +1 -1
  54. package/dist/lib/components/plugins/docx-artifact-viewer.component.js +32 -8
  55. package/dist/lib/components/plugins/docx-artifact-viewer.component.js.map +1 -1
  56. package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts +17 -3
  57. package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts.map +1 -1
  58. package/dist/lib/components/plugins/html-artifact-viewer.component.js +36 -8
  59. package/dist/lib/components/plugins/html-artifact-viewer.component.js.map +1 -1
  60. package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts +41 -5
  61. package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts.map +1 -1
  62. package/dist/lib/components/plugins/image-artifact-viewer.component.js +102 -30
  63. package/dist/lib/components/plugins/image-artifact-viewer.component.js.map +1 -1
  64. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts +33 -5
  65. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts.map +1 -1
  66. package/dist/lib/components/plugins/json-artifact-viewer.component.js +89 -33
  67. package/dist/lib/components/plugins/json-artifact-viewer.component.js.map +1 -1
  68. package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts +12 -2
  69. package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts.map +1 -1
  70. package/dist/lib/components/plugins/markdown-artifact-viewer.component.js +28 -8
  71. package/dist/lib/components/plugins/markdown-artifact-viewer.component.js.map +1 -1
  72. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts +4 -0
  73. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts.map +1 -1
  74. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js +14 -6
  75. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js.map +1 -1
  76. package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts +47 -5
  77. package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts.map +1 -1
  78. package/dist/lib/components/plugins/pdf-artifact-viewer.component.js +129 -45
  79. package/dist/lib/components/plugins/pdf-artifact-viewer.component.js.map +1 -1
  80. package/dist/lib/components/plugins/save-query-dialog.component.d.ts +5 -1
  81. package/dist/lib/components/plugins/save-query-dialog.component.d.ts.map +1 -1
  82. package/dist/lib/components/plugins/save-query-dialog.component.js +12 -4
  83. package/dist/lib/components/plugins/save-query-dialog.component.js.map +1 -1
  84. package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts +17 -3
  85. package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts.map +1 -1
  86. package/dist/lib/components/plugins/svg-artifact-viewer.component.js +36 -8
  87. package/dist/lib/components/plugins/svg-artifact-viewer.component.js.map +1 -1
  88. package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts +9 -1
  89. package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts.map +1 -1
  90. package/dist/lib/components/plugins/video-artifact-viewer.component.js +20 -4
  91. package/dist/lib/components/plugins/video-artifact-viewer.component.js.map +1 -1
  92. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts +28 -4
  93. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts.map +1 -1
  94. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js +64 -16
  95. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js.map +1 -1
  96. package/dist/lib/components/previews/audio-artifact-preview.component.d.ts +9 -1
  97. package/dist/lib/components/previews/audio-artifact-preview.component.d.ts.map +1 -1
  98. package/dist/lib/components/previews/audio-artifact-preview.component.js +20 -4
  99. package/dist/lib/components/previews/audio-artifact-preview.component.js.map +1 -1
  100. package/dist/lib/components/previews/image-artifact-preview.component.d.ts +16 -2
  101. package/dist/lib/components/previews/image-artifact-preview.component.d.ts.map +1 -1
  102. package/dist/lib/components/previews/image-artifact-preview.component.js +35 -7
  103. package/dist/lib/components/previews/image-artifact-preview.component.js.map +1 -1
  104. package/dist/lib/components/previews/video-artifact-preview.component.d.ts +9 -1
  105. package/dist/lib/components/previews/video-artifact-preview.component.d.ts.map +1 -1
  106. package/dist/lib/components/previews/video-artifact-preview.component.js +20 -4
  107. package/dist/lib/components/previews/video-artifact-preview.component.js.map +1 -1
  108. package/dist/lib/interfaces/artifact-viewer-plugin.interface.js.map +1 -1
  109. package/dist/lib/services/artifact-file.service.d.ts +8 -0
  110. package/dist/lib/services/artifact-file.service.d.ts.map +1 -1
  111. package/dist/lib/services/artifact-file.service.js +22 -6
  112. package/dist/lib/services/artifact-file.service.js.map +1 -1
  113. package/dist/lib/services/artifact-icon.service.d.ts +2 -0
  114. package/dist/lib/services/artifact-icon.service.d.ts.map +1 -1
  115. package/dist/lib/services/artifact-icon.service.js +5 -1
  116. package/dist/lib/services/artifact-icon.service.js.map +1 -1
  117. package/dist/lib/services/artifact-preview-resolver.service.d.ts +2 -0
  118. package/dist/lib/services/artifact-preview-resolver.service.d.ts.map +1 -1
  119. package/dist/lib/services/artifact-preview-resolver.service.js +5 -1
  120. package/dist/lib/services/artifact-preview-resolver.service.js.map +1 -1
  121. package/dist/lib/snapshot-helpers.d.ts +10 -0
  122. package/dist/lib/snapshot-helpers.d.ts.map +1 -1
  123. package/dist/lib/snapshot-helpers.js +25 -5
  124. package/dist/lib/snapshot-helpers.js.map +1 -1
  125. package/package.json +21 -21
@@ -1 +1 @@
1
- {"version":3,"file":"component-permission-evaluation.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/component-permission-evaluation.ts"],"names":[],"mappings":"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","sourcesContent":["import { IMetadataProvider, Metadata, UserInfo } from '@memberjunction/core';\nimport { ComponentSpec } from '@memberjunction/interactive-component-types';\nimport { QueryEngine } from '@memberjunction/core-entities';\n\n/**\n * Result of evaluating a user's permissions against a component's data requirements.\n */\nexport interface PermissionEvaluationResult {\n /** Whether the user can run all data operations the component requires */\n canRun: boolean;\n /** Entity names the user lacks read permission for */\n missingEntities: string[];\n /** Query names the user lacks permission to execute */\n missingQueries: string[];\n}\n\n/**\n * Evaluates whether a user has sufficient permissions to run a component\n * based on its declared dataRequirements. Checks both entity-level read\n * permissions and query-level execution permissions.\n *\n * Runs entirely on client-side metadata — no additional server call needed.\n */\nfunction evaluateComponentPermissionsSingle(\n spec: ComponentSpec,\n currentUser: UserInfo,\n provider?: IMetadataProvider\n): PermissionEvaluationResult {\n const missingEntities: string[] = [];\n const missingQueries: string[] = [];\n const dataReqs = spec.dataRequirements;\n\n if (!dataReqs) {\n return { canRun: true, missingEntities: [], missingQueries: [] };\n }\n\n // Check entity permissions (all current components are read-only)\n const md = provider ?? Metadata.Provider;\n for (const entityReq of dataReqs.entities ?? []) {\n const entityInfo = md.EntityByName(entityReq.name);\n if (!entityInfo) continue; // Unknown entity — skip (may be stale reference)\n\n const perms = entityInfo.GetUserPermisions(currentUser);\n if (!perms?.CanRead) {\n missingEntities.push(entityReq.name);\n }\n }\n\n // Check query permissions using centralized UserCanRun logic\n const qe = QueryEngine.Instance;\n for (const queryReq of dataReqs.queries ?? []) {\n if (!queryReq.name) continue;\n\n const queryInfo = qe.FindQueryByName(queryReq.name);\n if (!queryInfo) continue; // Unknown query — skip\n\n const result = queryInfo.UserCanRun(currentUser);\n if (!result.canRun) {\n missingQueries.push(queryReq.name);\n }\n }\n\n return {\n canRun: missingEntities.length === 0 && missingQueries.length === 0,\n missingEntities,\n missingQueries,\n };\n}\n\n/**\n * Recursively evaluates permissions for a component and all its dependencies.\n * Walks the full dependency tree, deduplicating results.\n */\nexport function evaluateComponentPermissions(\n spec: ComponentSpec,\n currentUser: UserInfo,\n provider?: IMetadataProvider\n): PermissionEvaluationResult {\n const result = evaluateComponentPermissionsSingle(spec, currentUser, provider);\n\n for (const dep of spec.dependencies ?? []) {\n const depResult = evaluateComponentPermissions(dep, currentUser, provider);\n result.missingEntities.push(...depResult.missingEntities);\n result.missingQueries.push(...depResult.missingQueries);\n }\n\n // Deduplicate\n result.missingEntities = [...new Set(result.missingEntities)];\n result.missingQueries = [...new Set(result.missingQueries)];\n result.canRun = result.missingEntities.length === 0 && result.missingQueries.length === 0;\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"component-permission-evaluation.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/component-permission-evaluation.ts"],"names":[],"mappings":"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","sourcesContent":["import { IMetadataProvider, Metadata, UserInfo } from '@memberjunction/core';\nimport { ComponentSpec } from '@memberjunction/interactive-component-types';\nimport { QueryEngine } from '@memberjunction/core-entities';\n\n/**\n * Result of evaluating a user's permissions against a component's data requirements.\n */\nexport interface PermissionEvaluationResult {\n /** Whether the user can run all data operations the component requires */\n canRun: boolean; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n /** Entity names the user lacks read permission for */\n missingEntities: string[]; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n /** Query names the user lacks permission to execute */\n missingQueries: string[]; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n}\n\n/**\n * Evaluates whether a user has sufficient permissions to run a component\n * based on its declared dataRequirements. Checks both entity-level read\n * permissions and query-level execution permissions.\n *\n * Runs entirely on client-side metadata — no additional server call needed.\n */\nfunction evaluateComponentPermissionsSingle(\n spec: ComponentSpec,\n currentUser: UserInfo,\n provider?: IMetadataProvider\n): PermissionEvaluationResult {\n const missingEntities: string[] = [];\n const missingQueries: string[] = [];\n const dataReqs = spec.dataRequirements;\n\n if (!dataReqs) {\n return { canRun: true, missingEntities: [], missingQueries: [] };\n }\n\n // Check entity permissions (all current components are read-only)\n const md = provider ?? Metadata.Provider;\n for (const entityReq of dataReqs.entities ?? []) {\n const entityInfo = md.EntityByName(entityReq.name);\n if (!entityInfo) continue; // Unknown entity — skip (may be stale reference)\n\n const perms = entityInfo.GetUserPermisions(currentUser);\n if (!perms?.CanRead) {\n missingEntities.push(entityReq.name);\n }\n }\n\n // Check query permissions using centralized UserCanRun logic\n const qe = QueryEngine.Instance;\n for (const queryReq of dataReqs.queries ?? []) {\n if (!queryReq.name) continue;\n\n const queryInfo = qe.FindQueryByName(queryReq.name);\n if (!queryInfo) continue; // Unknown query — skip\n\n const result = queryInfo.UserCanRun(currentUser);\n if (!result.canRun) {\n missingQueries.push(queryReq.name);\n }\n }\n\n return {\n canRun: missingEntities.length === 0 && missingQueries.length === 0,\n missingEntities,\n missingQueries,\n };\n}\n\n/**\n * Recursively evaluates permissions for a component and all its dependencies.\n * Walks the full dependency tree, deduplicating results.\n */\nexport function EvaluateComponentPermissions(\n spec: ComponentSpec,\n currentUser: UserInfo,\n provider?: IMetadataProvider\n): PermissionEvaluationResult {\n const result = evaluateComponentPermissionsSingle(spec, currentUser, provider);\n\n for (const dep of spec.dependencies ?? []) {\n const depResult = EvaluateComponentPermissions(dep, currentUser, provider);\n result.missingEntities.push(...depResult.missingEntities);\n result.missingQueries.push(...depResult.missingQueries);\n }\n\n // Deduplicate\n result.missingEntities = [...new Set(result.missingEntities)];\n result.missingQueries = [...new Set(result.missingQueries)];\n result.canRun = result.missingEntities.length === 0 && result.missingQueries.length === 0;\n\n return result;\n}\n\n/** @deprecated Use {@link EvaluateComponentPermissions}. */\nexport function evaluateComponentPermissions(\n spec: ComponentSpec,\n currentUser: UserInfo,\n provider?: IMetadataProvider\n): PermissionEvaluationResult {\n return EvaluateComponentPermissions(spec, currentUser, provider);\n}\n"]}
@@ -56,6 +56,17 @@ type QuerySyncState = 'no-query-latest' | 'no-query-older' | 'synced' | 'outdate
56
56
  */
57
57
  export declare class DataArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit {
58
58
  private cdr;
59
+ OpenEntityRecord: EventEmitter<{
60
+ entityName: string;
61
+ compositeKey: CompositeKey;
62
+ }>;
63
+ /**
64
+ * @deprecated Use {@link OpenEntityRecord}.
65
+ *
66
+ * The same emitter under the old binding name, so a template still binding
67
+ * (openEntityRecord) keeps working. Must stay AFTER OpenEntityRecord: class fields
68
+ * initialise in order, and the other way round this captures undefined.
69
+ */
59
70
  openEntityRecord: EventEmitter<{
60
71
  entityName: string;
61
72
  compositeKey: CompositeKey;
@@ -147,21 +158,21 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
147
158
  * Load data for a specific table.
148
159
  * Handles live SQL execution, inline rows, and caching.
149
160
  */
150
- private LoadTableData;
161
+ private loadTableData;
151
162
  /**
152
163
  * Build QueryGridColumnConfig[] from a DataTable's column metadata.
153
164
  * Returns null if columns have no entity metadata (grid falls back to auto-inference).
154
165
  */
155
- private BuildColumnConfigsForTable;
166
+ private buildColumnConfigsForTable;
156
167
  /**
157
168
  * Handle a table load error by setting error state and falling back to inline data
158
169
  */
159
- private HandleTableError;
170
+ private handleTableError;
160
171
  /**
161
172
  * Initialize query sync state by loading cached metadata.
162
173
  * Resolves the latest version number and compares saved query SQL.
163
174
  */
164
- private InitQuerySyncState;
175
+ private initQuerySyncState;
165
176
  /**
166
177
  * Determine the latest version number for this artifact from cache.
167
178
  * Falls back to current version if cache miss.
@@ -207,7 +218,7 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
207
218
  /** Handle successful save from the dialog (both initial save and "save as new") */
208
219
  OnQuerySaved(event: SaveQueryResult): Promise<void>;
209
220
  /** Persist updated spec back to the artifact version entity */
210
- private PersistArtifactContent;
221
+ private persistArtifactContent;
211
222
  /**
212
223
  * Returns a DataSnapshot with live grid data, current page state,
213
224
  * and query sync state.
@@ -218,7 +229,7 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
218
229
  */
219
230
  GetAdditionalTabs(): ArtifactViewerTab[];
220
231
  static ɵfac: i0.ɵɵFactoryDeclaration<DataArtifactViewerComponent, never>;
221
- static ɵcmp: i0.ɵɵComponentDeclaration<DataArtifactViewerComponent, "mj-data-artifact-viewer", never, {}, { "openEntityRecord": "openEntityRecord"; "navigationRequest": "navigationRequest"; }, never, never, false, never>;
232
+ static ɵcmp: i0.ɵɵComponentDeclaration<DataArtifactViewerComponent, "mj-data-artifact-viewer", never, {}, { "OpenEntityRecord": "OpenEntityRecord"; "openEntityRecord": "openEntityRecord"; "navigationRequest": "navigationRequest"; }, never, never, false, never>;
222
233
  }
223
234
  export {};
224
235
  //# sourceMappingURL=data-artifact-viewer.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/data-artifact-viewer.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/data-artifact-viewer.component.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ import { DataSnapshot, NormalizeToTables, CompositeKey } from '@memberjunction/c
10
10
  import { QueryEngine, ArtifactMetadataEngine } from '@memberjunction/core-entities';
11
11
  import { resolveTargetEntity } from '@memberjunction/ng-query-viewer';
12
12
  import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
13
- import { buildMultiTableSql } from '../../snapshot-helpers';
13
+ import { BuildMultiTableSql } from '../../snapshot-helpers';
14
14
  import * as i0 from "@angular/core";
15
15
  import * as i1 from "@angular/common";
16
16
  import * as i2 from "@memberjunction/ng-markdown";
@@ -384,7 +384,15 @@ function DataArtifactViewerComponent_Conditional_4_Template(rf, ctx) { if (rf &
384
384
  */
385
385
  let DataArtifactViewerComponent = class DataArtifactViewerComponent extends BaseArtifactViewerPluginComponent {
386
386
  cdr;
387
- openEntityRecord = new EventEmitter();
387
+ OpenEntityRecord = new EventEmitter();
388
+ /**
389
+ * @deprecated Use {@link OpenEntityRecord}.
390
+ *
391
+ * The same emitter under the old binding name, so a template still binding
392
+ * (openEntityRecord) keeps working. Must stay AFTER OpenEntityRecord: class fields
393
+ * initialise in order, and the other way round this captures undefined.
394
+ */
395
+ openEntityRecord = this.OpenEntityRecord;
388
396
  navigationRequest = new EventEmitter();
389
397
  tabsChanged = new EventEmitter();
390
398
  spec = null;
@@ -501,7 +509,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
501
509
  }
502
510
  // Build enriched column configs for the first table
503
511
  if (this.ResolvedTables.length > 0) {
504
- this.GridColumnConfigs = this.BuildColumnConfigsForTable(this.ResolvedTables[0]);
512
+ this.GridColumnConfigs = this.buildColumnConfigsForTable(this.ResolvedTables[0]);
505
513
  }
506
514
  // Initialize paging state for all tables
507
515
  for (let i = 0; i < this.ResolvedTables.length; i++) {
@@ -512,10 +520,10 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
512
520
  this.IsLoading = true;
513
521
  }
514
522
  // Load cached metadata and resolve query sync state
515
- await this.InitQuerySyncState();
523
+ await this.initQuerySyncState();
516
524
  // Load data for the first (active) table
517
525
  if (this.ResolvedTables.length > 0) {
518
- await this.LoadTableData(0);
526
+ await this.loadTableData(0);
519
527
  }
520
528
  // Signal parent that tabs/display content may have changed after async load
521
529
  this.tabsChanged.emit();
@@ -530,7 +538,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
530
538
  */
531
539
  async OnRefresh() {
532
540
  this.tableDataCache.delete(this.ActiveTableIndex);
533
- await this.LoadTableData(this.ActiveTableIndex);
541
+ await this.loadTableData(this.ActiveTableIndex);
534
542
  }
535
543
  /**
536
544
  * Handle entity link click from the grid and bubble up as openEntityRecord.
@@ -541,7 +549,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
541
549
  // recordId may be a bare value or a "F1|v1||F2|v2" segment; FromURLSegment reads both against
542
550
  // the entity's real primary key(s) instead of assuming a single column.
543
551
  const compositeKey = CompositeKey.FromURLSegment(md.EntityByName(event.entityName), event.recordId);
544
- this.openEntityRecord.emit({
552
+ this.OpenEntityRecord.emit({
545
553
  entityName: event.entityName,
546
554
  compositeKey
547
555
  });
@@ -558,7 +566,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
558
566
  pageState.pageSize = event.PageSize;
559
567
  // Clear cache so it reloads
560
568
  this.tableDataCache.delete(this.ActiveTableIndex);
561
- await this.LoadTableData(this.ActiveTableIndex);
569
+ await this.loadTableData(this.ActiveTableIndex);
562
570
  }
563
571
  /**
564
572
  * Switch to a different table tab.
@@ -573,7 +581,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
573
581
  return;
574
582
  // Use cached column configs or build new
575
583
  if (!this.tableColumnConfigsCache.has(index)) {
576
- const configs = this.BuildColumnConfigsForTable(table);
584
+ const configs = this.buildColumnConfigsForTable(table);
577
585
  if (configs)
578
586
  this.tableColumnConfigsCache.set(index, configs);
579
587
  }
@@ -587,7 +595,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
587
595
  this.PagerTotalRowCount = pageState.totalRowCount;
588
596
  }
589
597
  else {
590
- await this.LoadTableData(index);
598
+ await this.loadTableData(index);
591
599
  }
592
600
  this.cdr.detectChanges();
593
601
  }
@@ -595,7 +603,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
595
603
  * Load data for a specific table.
596
604
  * Handles live SQL execution, inline rows, and caching.
597
605
  */
598
- async LoadTableData(tableIndex) {
606
+ async loadTableData(tableIndex) {
599
607
  const table = this.ResolvedTables[tableIndex];
600
608
  if (!table)
601
609
  return;
@@ -625,7 +633,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
625
633
  this.liveExecutionTime = result.ExecutionTime;
626
634
  }
627
635
  else {
628
- this.HandleTableError(tableIndex, result.ErrorMessage || 'Query failed');
636
+ this.handleTableError(tableIndex, result.ErrorMessage || 'Query failed');
629
637
  }
630
638
  }
631
639
  else if (table.rows && table.rows.length > 0) {
@@ -639,7 +647,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
639
647
  }
640
648
  }
641
649
  catch (error) {
642
- this.HandleTableError(tableIndex, error instanceof Error ? error.message : 'Load failed');
650
+ this.handleTableError(tableIndex, error instanceof Error ? error.message : 'Load failed');
643
651
  }
644
652
  finally {
645
653
  this.IsLoading = false;
@@ -650,7 +658,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
650
658
  * Build QueryGridColumnConfig[] from a DataTable's column metadata.
651
659
  * Returns null if columns have no entity metadata (grid falls back to auto-inference).
652
660
  */
653
- BuildColumnConfigsForTable(table) {
661
+ buildColumnConfigsForTable(table) {
654
662
  const columns = table.columns;
655
663
  if (!columns?.length)
656
664
  return null;
@@ -699,7 +707,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
699
707
  /**
700
708
  * Handle a table load error by setting error state and falling back to inline data
701
709
  */
702
- HandleTableError(tableIndex, message) {
710
+ handleTableError(tableIndex, message) {
703
711
  this.HasError = true;
704
712
  this.ErrorMessage = message;
705
713
  const table = this.ResolvedTables[tableIndex];
@@ -712,7 +720,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
712
720
  * Initialize query sync state by loading cached metadata.
713
721
  * Resolves the latest version number and compares saved query SQL.
714
722
  */
715
- async InitQuerySyncState() {
723
+ async initQuerySyncState() {
716
724
  // Ensure the artifact-type registry is loaded (not registered for startup).
717
725
  await ArtifactMetadataEngine.Instance.Config(false);
718
726
  // Load THIS artifact's versions on demand (including Content, which
@@ -889,7 +897,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
889
897
  if (saved) {
890
898
  // Update spec with new version tracking
891
899
  this.spec.savedAtVersionNumber = this.CurrentVersionNumber;
892
- await this.PersistArtifactContent();
900
+ await this.persistArtifactContent();
893
901
  // Refresh caches so future lookups see the updated data
894
902
  await QueryEngine.Instance.Config(true);
895
903
  await ArtifactMetadataEngine.Instance.Config(true);
@@ -926,7 +934,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
926
934
  this.spec.savedQueryName = event.queryName;
927
935
  this.spec.savedAtVersionNumber = this.CurrentVersionNumber;
928
936
  // Persist and refresh caches
929
- await this.PersistArtifactContent();
937
+ await this.persistArtifactContent();
930
938
  await QueryEngine.Instance.Config(true);
931
939
  await ArtifactMetadataEngine.Instance.Config(true);
932
940
  await this.ProviderToUse.Refresh();
@@ -943,7 +951,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
943
951
  }
944
952
  }
945
953
  /** Persist updated spec back to the artifact version entity */
946
- async PersistArtifactContent() {
954
+ async persistArtifactContent() {
947
955
  if (!this.artifactVersion || !this.spec)
948
956
  return;
949
957
  this.artifactVersion.Content = JSON.stringify(this.spec);
@@ -991,7 +999,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
991
999
  }
992
1000
  // SQL tab — multi-table shows all queries with headers
993
1001
  if (this.IsMultiTable) {
994
- const multiSql = buildMultiTableSql(this.ResolvedTables);
1002
+ const multiSql = BuildMultiTableSql(this.ResolvedTables);
995
1003
  if (multiSql) {
996
1004
  tabs.push({
997
1005
  label: 'SQL',
@@ -1023,7 +1031,7 @@ let DataArtifactViewerComponent = class DataArtifactViewerComponent extends Base
1023
1031
  return tabs;
1024
1032
  }
1025
1033
  static ɵfac = function DataArtifactViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DataArtifactViewerComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
1026
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DataArtifactViewerComponent, selectors: [["mj-data-artifact-viewer"]], outputs: { openEntityRecord: "openEntityRecord", navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 3, consts: [[1, "data-artifact-viewer", 3, "ngClass"], ["Variant", "error", "Icon", "fa-solid fa-triangle-exclamation", "Title", "Couldn't load data", "Size", "compact", 3, "Message"], ["Icon", "fa-solid fa-inbox", "Title", "No data to display", "Size", "compact"], [3, "QueryName", "QueryDescription", "SQL", "Plan"], [1, "data-toolbar"], [1, "data-title"], [1, "fas", "fa-table"], [1, "live-badge"], [1, "row-count"], [1, "exec-time"], [1, "data-actions"], ["title", "Refresh data", 1, "btn-icon", 3, "disabled"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save"], [1, "table-tabs"], [1, "computations-bar"], [1, "grid-container"], [1, "saving-overlay"], ["text", "Loading data..."], ["Height", "100%", 3, "ColumnConfigs", "Data", "TotalRowCount", "PageNumber", "PageSize", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], ["title", "Refresh data", 1, "btn-icon", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save", 3, "click"], [1, "fas", "fa-save"], [1, "query-badge", "query-badge-synced"], [1, "fas", "fa-check"], ["title", "Open saved query record", 1, "btn-icon", "btn-open", 3, "click"], [1, "fas", "fa-external-link-alt"], [1, "query-badge", "query-badge-outdated"], [1, "fas", "fa-circle-exclamation"], [1, "dropdown-wrapper"], ["title", "Update or save query", 1, "btn-icon", "btn-warning", 3, "click"], [1, "fas", "fa-caret-down"], [1, "query-dropdown"], [1, "query-dropdown", 3, "click"], [1, "query-dropdown-item", 3, "click"], [1, "fas", "fa-arrow-up-from-bracket", 2, "color", "#d97706"], [1, "dropdown-label"], [1, "dropdown-desc"], [1, "fas", "fa-plus", 2, "color", "#16a34a"], [1, "fas", "fa-external-link-alt", 2, "color", "var(--mj-text-muted)"], [1, "query-badge", "query-badge-muted"], [1, "fas", "fa-clock-rotate-left"], ["title", "Open saved query record", 1, "btn-icon", "btn-muted", 3, "click"], [1, "table-tab", 3, "active", "title"], [1, "table-tab", 3, "click", "title"], [1, "table-tab-name"], [1, "table-tab-count"], [1, "computation-chip", 3, "title"], [1, "computation-label"], [1, "computation-value"], [3, "text"], ["Variant", "warning", "Size", "sm", 1, "data-artifact-alert-pos"], [1, "fallback-note"], ["Height", "100%", 3, "EntityLinkClick", "PageChange", "ColumnConfigs", "Data", "TotalRowCount", "PageNumber", "PageSize", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], [1, "fas", "fa-diagram-project"], [1, "plan-content"], [3, "data", "enableMermaid", "enableHighlight", "enableCollapsibleHeadings", "enableSmartypants"], [3, "Saved", "Cancelled", "QueryName", "QueryDescription", "SQL", "Plan"]], template: function DataArtifactViewerComponent_Template(rf, ctx) { if (rf & 1) {
1034
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DataArtifactViewerComponent, selectors: [["mj-data-artifact-viewer"]], outputs: { OpenEntityRecord: "OpenEntityRecord", openEntityRecord: "openEntityRecord", navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 3, consts: [[1, "data-artifact-viewer", 3, "ngClass"], ["Variant", "error", "Icon", "fa-solid fa-triangle-exclamation", "Title", "Couldn't load data", "Size", "compact", 3, "Message"], ["Icon", "fa-solid fa-inbox", "Title", "No data to display", "Size", "compact"], [3, "QueryName", "QueryDescription", "SQL", "Plan"], [1, "data-toolbar"], [1, "data-title"], [1, "fas", "fa-table"], [1, "live-badge"], [1, "row-count"], [1, "exec-time"], [1, "data-actions"], ["title", "Refresh data", 1, "btn-icon", 3, "disabled"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save"], [1, "table-tabs"], [1, "computations-bar"], [1, "grid-container"], [1, "saving-overlay"], ["text", "Loading data..."], ["Height", "100%", 3, "ColumnConfigs", "Data", "TotalRowCount", "PageNumber", "PageSize", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], ["title", "Refresh data", 1, "btn-icon", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], ["title", "Save as reusable query", 1, "btn-icon", "btn-save", 3, "click"], [1, "fas", "fa-save"], [1, "query-badge", "query-badge-synced"], [1, "fas", "fa-check"], ["title", "Open saved query record", 1, "btn-icon", "btn-open", 3, "click"], [1, "fas", "fa-external-link-alt"], [1, "query-badge", "query-badge-outdated"], [1, "fas", "fa-circle-exclamation"], [1, "dropdown-wrapper"], ["title", "Update or save query", 1, "btn-icon", "btn-warning", 3, "click"], [1, "fas", "fa-caret-down"], [1, "query-dropdown"], [1, "query-dropdown", 3, "click"], [1, "query-dropdown-item", 3, "click"], [1, "fas", "fa-arrow-up-from-bracket", 2, "color", "#d97706"], [1, "dropdown-label"], [1, "dropdown-desc"], [1, "fas", "fa-plus", 2, "color", "#16a34a"], [1, "fas", "fa-external-link-alt", 2, "color", "var(--mj-text-muted)"], [1, "query-badge", "query-badge-muted"], [1, "fas", "fa-clock-rotate-left"], ["title", "Open saved query record", 1, "btn-icon", "btn-muted", 3, "click"], [1, "table-tab", 3, "active", "title"], [1, "table-tab", 3, "click", "title"], [1, "table-tab-name"], [1, "table-tab-count"], [1, "computation-chip", 3, "title"], [1, "computation-label"], [1, "computation-value"], [3, "text"], ["Variant", "warning", "Size", "sm", 1, "data-artifact-alert-pos"], [1, "fallback-note"], ["Height", "100%", 3, "EntityLinkClick", "PageChange", "ColumnConfigs", "Data", "TotalRowCount", "PageNumber", "PageSize", "ShowToolbar", "ShowRefresh", "PersistState", "SelectionMode"], [1, "fas", "fa-diagram-project"], [1, "plan-content"], [3, "data", "enableMermaid", "enableHighlight", "enableCollapsibleHeadings", "enableSmartypants"], [3, "Saved", "Cancelled", "QueryName", "QueryDescription", "SQL", "Plan"]], template: function DataArtifactViewerComponent_Template(rf, ctx) { if (rf & 1) {
1027
1035
  i0.ɵɵelementStart(0, "div", 0);
1028
1036
  i0.ɵɵconditionalCreate(1, DataArtifactViewerComponent_Conditional_1_Template, 3, 1)(2, DataArtifactViewerComponent_Conditional_2_Template, 1, 1, "mj-empty-state", 1)(3, DataArtifactViewerComponent_Conditional_3_Template, 1, 0, "mj-empty-state", 2);
1029
1037
  i0.ɵɵconditionalCreate(4, DataArtifactViewerComponent_Conditional_4_Template, 1, 4, "mj-save-query-panel", 3);
@@ -1043,7 +1051,9 @@ export { DataArtifactViewerComponent };
1043
1051
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DataArtifactViewerComponent, [{
1044
1052
  type: Component,
1045
1053
  args: [{ standalone: false, selector: 'mj-data-artifact-viewer', template: "<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 | number }} rows</span>\n }\n @if (DisplayExecutionTime != null) {\n <span class=\"exec-time\">{{ DisplayExecutionTime }}ms</span>\n }\n </div>\n <div class=\"data-actions\">\n @if (IsLive) {\n <button class=\"btn-icon\" title=\"Refresh data\" (click)=\"OnRefresh()\" [disabled]=\"IsLoading\">\n <i class=\"fas fa-sync-alt\" [class.fa-spin]=\"IsLoading\"></i> Refresh\n </button>\n }\n\n @switch (QuerySyncState) {\n <!-- S1: No saved query, latest version \u2192 Save Query -->\n @case (\"no-query-latest\") {\n <button class=\"btn-icon btn-save\" title=\"Save as reusable query\" (click)=\"OnShowSaveDialog()\"><i class=\"fas fa-save\"></i> Save Query</button>\n }\n\n <!-- S2: SQL matches \u2192 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 \u2192 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 \u2192 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 <mj-alert Variant=\"warning\" Size=\"sm\" class=\"data-artifact-alert-pos\">\n {{ ErrorMessage }}\n <span class=\"fallback-note\">(Showing cached data)</span>\n </mj-alert>\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 <mj-empty-state\n Variant=\"error\"\n Icon=\"fa-solid fa-triangle-exclamation\"\n Title=\"Couldn't load data\"\n [Message]=\"ErrorMessage\"\n Size=\"compact\" />\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 <mj-empty-state\n Icon=\"fa-solid fa-inbox\"\n Title=\"No data to display\"\n Size=\"compact\" />\n }\n } @else if (HasError) {\n <mj-empty-state\n Variant=\"error\"\n Icon=\"fa-solid fa-triangle-exclamation\"\n Title=\"Couldn't load data\"\n [Message]=\"ErrorMessage\"\n Size=\"compact\" />\n } @else {\n <mj-empty-state\n Icon=\"fa-solid fa-inbox\"\n Title=\"No data to display\"\n Size=\"compact\" />\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", styles: [".data-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.data-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.data-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.data-title i {\n color: var(--mj-text-muted);\n}\n\n.row-count {\n padding: 2px 8px;\n background: var(--mj-border-default);\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.exec-time {\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-status-success);\n}\n\n.live-badge {\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n}\n\n.data-actions {\n display: flex;\n gap: 6px;\n}\n\n.btn-icon {\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n color: var(--mj-text-secondary);\n}\n\n.btn-icon:hover {\n background: var(--mj-border-default);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.btn-icon.btn-save {\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-save:hover {\n background: color-mix(in srgb, var(--mj-status-success) 8%, var(--mj-bg-surface));\n border-color: var(--mj-status-success);\n}\n\n.btn-icon.btn-open {\n color: var(--mj-brand-primary);\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-open:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.grid-container {\n flex: 1;\n overflow: hidden;\n min-height: 200px;\n height: 500px;\n position: relative;\n}\n\n/* Saving overlay \u2014 semi-transparent panel over the grid */\n.saving-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-surface) 80%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 50;\n}\n\n/* Positioning only \u2014 mj-alert owns its own box (bg/border/radius/padding/icon). */\n.data-artifact-alert-pos {\n margin: 0 0 8px;\n}\n\n.fallback-note {\n font-style: italic;\n color: var(--mj-text-muted);\n}\n\n.plan-content {\n flex: 1;\n overflow: auto;\n padding: 16px;\n}\n\n/* Query sync badges */\n.query-badge {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n white-space: nowrap;\n}\n\n.query-badge-synced {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.query-badge-outdated {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.query-badge-muted {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n/* Dropdown wrapper */\n.dropdown-wrapper {\n position: relative;\n}\n\n.btn-icon.btn-warning {\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, var(--mj-bg-surface));\n}\n\n.btn-icon.btn-warning:hover {\n background: color-mix(in srgb, var(--mj-status-warning) 8%, var(--mj-bg-surface));\n border-color: var(--mj-status-warning);\n}\n\n.btn-icon.btn-muted {\n color: var(--mj-text-disabled);\n border-color: var(--mj-border-default);\n}\n\n/* Query actions dropdown */\n.query-dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n min-width: 280px;\n z-index: 100;\n}\n\n.query-dropdown-item {\n padding: 10px 14px;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n cursor: pointer;\n border-bottom: 1px solid var(--mj-border-default);\n transition: background 0.1s;\n}\n\n.query-dropdown-item:last-child {\n border-bottom: none;\n}\n\n.query-dropdown-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.query-dropdown-item i {\n width: 16px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.dropdown-label {\n font-weight: 500;\n}\n\n.dropdown-desc {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n/* \u2500\u2500\u2500 Table Tab Strip \u2500\u2500\u2500 */\n\n.table-tabs {\n display: flex;\n gap: 0;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 var(--mj-spacing-md, 16px);\n background: var(--mj-bg-surface);\n overflow-x: auto;\n}\n\n.table-tab {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n transition: color 150ms ease, border-color 150ms ease;\n white-space: nowrap;\n}\n\n.table-tab:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.table-tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.table-tab-name {\n text-transform: capitalize;\n}\n\n.table-tab-count {\n color: var(--mj-text-muted);\n font-weight: 400;\n font-size: 12px;\n}\n\n.table-tab.active .table-tab-count {\n color: var(--mj-brand-primary);\n opacity: 0.7;\n}\n\n/* \u2500\u2500\u2500 Computations Summary Bar \u2500\u2500\u2500 */\n\n.computations-bar {\n display: flex;\n gap: 12px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-subtle);\n overflow-x: auto;\n flex-wrap: wrap;\n}\n\n.computation-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 13px;\n white-space: nowrap;\n}\n\n.computation-label {\n color: var(--mj-text-secondary);\n font-weight: 400;\n}\n\n.computation-value {\n color: var(--mj-text-primary);\n font-weight: 600;\n}\n"] }]
1046
- }], () => [{ type: i0.ChangeDetectorRef }], { openEntityRecord: [{
1054
+ }], () => [{ type: i0.ChangeDetectorRef }], { OpenEntityRecord: [{
1055
+ type: Output
1056
+ }], openEntityRecord: [{
1047
1057
  type: Output
1048
1058
  }], navigationRequest: [{
1049
1059
  type: Output