@memberjunction/ng-artifacts 5.28.0 → 5.30.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.
- package/dist/lib/__tests__/artifact-snapshots.test.d.ts +2 -0
- package/dist/lib/__tests__/artifact-snapshots.test.d.ts.map +1 -0
- package/dist/lib/__tests__/artifact-snapshots.test.js +155 -0
- package/dist/lib/__tests__/artifact-snapshots.test.js.map +1 -0
- package/dist/lib/components/artifact-viewer-panel.component.d.ts +16 -2
- package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
- package/dist/lib/components/artifact-viewer-panel.component.js +128 -98
- package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
- package/dist/lib/components/base-artifact-viewer.component.d.ts +24 -0
- package/dist/lib/components/base-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/base-artifact-viewer.component.js +15 -1
- package/dist/lib/components/base-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/code-artifact-viewer.component.js +5 -1
- package/dist/lib/components/plugins/code-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +2 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.js +29 -0
- package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts +50 -43
- package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.js +336 -137
- package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/docx-artifact-viewer.component.js +21 -6
- package/dist/lib/components/plugins/docx-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/html-artifact-viewer.component.js +11 -1
- package/dist/lib/components/plugins/html-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/json-artifact-viewer.component.js +5 -1
- package/dist/lib/components/plugins/json-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/markdown-artifact-viewer.component.js +5 -1
- package/dist/lib/components/plugins/markdown-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/pdf-artifact-viewer.component.js +29 -10
- package/dist/lib/components/plugins/pdf-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/save-query-dialog.component.js +2 -2
- package/dist/lib/components/plugins/save-query-dialog.component.js.map +1 -1
- package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/svg-artifact-viewer.component.js +11 -1
- package/dist/lib/components/plugins/svg-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js +39 -13
- package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js.map +1 -1
- package/dist/lib/services/analyze-artifact.service.d.ts +77 -0
- package/dist/lib/services/analyze-artifact.service.d.ts.map +1 -0
- package/dist/lib/services/analyze-artifact.service.js +120 -0
- package/dist/lib/services/analyze-artifact.service.js.map +1 -0
- package/dist/lib/snapshot-helpers.d.ts +48 -0
- package/dist/lib/snapshot-helpers.d.ts.map +1 -0
- package/dist/lib/snapshot-helpers.js +79 -0
- package/dist/lib/snapshot-helpers.js.map +1 -0
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +16 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-artifact-viewer.component.js","sourceRoot":"","sources":["../../../src/lib/components/base-artifact-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,KAAK,EAAQ,MAAM,eAAe,CAAC;;AAqErE;;;;GAIG;AAKH,MAAM,OAAgB,iCAAiC;IACrD;;OAEG;IACM,eAAe,CAA2B;IAEnD;;OAEG;IACM,MAAM,CAAU;IAEzB;;OAEG;IACM,QAAQ,GAAY,IAAI,CAAC;IAElC;;OAEG;IACM,QAAQ,CAAU;IAE3B;;;;;;;;;OASG;IACH,IAAW,wBAAwB;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;;;OAWG;IACH,IAAW,0BAA0B;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,IAAW,iBAAiB;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACO,UAAU;QAClB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,CAAC;YACnC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;QACtC,CAAC;QAED,wCAAwC;QACxC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACO,gBAAgB;QACxB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACO,cAAc;QACtB,OAAO,IAAI,CAAC,eAAe,EAAE,IAAI,IAAI,mBAAmB,CAAC;IAC3D,CAAC;IAED;;OAEG;IACO,cAAc;QACtB,OAAO,IAAI,CAAC,eAAe,EAAE,WAAW,IAAI,EAAE,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACI,WAAW,CAAsB;IAExC;;;;;;OAMG;IACI,iBAAiB,CAAmC;IAE3D;;;;;;OAMG;IACH,IAAW,gBAAgB;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACI,kBAAkB;QACvB,+CAA+C;IACjD,CAAC;IAsBD;;;;OAIG;IACO,KAAK,CAAC,sBAAsB,CAAC,GAAW,EAAE,QAAgB;QAClE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;QACxB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;2HArLmB,iCAAiC;6DAAjC,iCAAiC;;iFAAjC,iCAAiC;cAJtD,SAAS;eAAC;gBACT,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,EAAE;aACb;;kBAKE,KAAK;;kBAKL,KAAK;;kBAKL,KAAK;;kBAKL,KAAK;;kFAnBc,iCAAiC","sourcesContent":["import { Component, EventEmitter, Input, Type } from '@angular/core';\nimport { MJArtifactVersionEntity } from '@memberjunction/core-entities';\nimport { IArtifactViewerComponent } from '../interfaces/artifact-viewer-plugin.interface';\n\n/**\n * General-purpose navigation request emitted by artifact viewer plugins.\n * Allows plugins to request app-level navigation (e.g., switch to a specific\n * application, open a nav item, and set query parameters) without depending\n * on NavigationService directly.\n *\n * The event bubbles through ArtifactTypePluginViewer → ArtifactViewerPanel →\n * consumer (conversations, dashboards, etc.) → ultimately the Explorer wrapper\n * where NavigationService lives.\n */\nexport interface NavigationRequest {\n /** Target application name (e.g., 'Data Explorer'). If omitted, stays in current app. */\n appName?: string;\n\n /** Target navigation item label within the app (e.g., 'Queries') */\n navItemName: string;\n\n /** Query parameters to pass to the navigation target (e.g., { queryId: 'xxx' }) */\n queryParams?: Record<string, string>;\n}\n\n/**\n * Represents an additional tab that a plugin can provide to the artifact viewer.\n *\n * Tabs can render content in two ways:\n * 1. **String content** - Use `contentType` with `content` for built-in renderers (markdown, json, code, etc.)\n * 2. **Custom component** - Use `contentType: 'component'` with `component` and optional `componentInputs`\n *\n * @example\n * // String content tab\n * {\n * label: 'Code',\n * icon: 'fa-code',\n * contentType: 'code',\n * content: () => this.getCodeContent(),\n * language: 'typescript'\n * }\n *\n * @example\n * // Custom component tab\n * {\n * label: 'Data',\n * icon: 'fa-database',\n * contentType: 'component',\n * component: DataRequirementsViewerComponent,\n * componentInputs: { dataRequirements: this.spec.dataRequirements }\n * }\n */\nexport interface ArtifactViewerTab {\n /** Display label for the tab */\n label: string;\n /** Font Awesome icon class (without 'fas' prefix) */\n icon?: string;\n /** Type of content to render */\n contentType: 'plaintext' | 'html' | 'markdown' | 'json' | 'code' | 'component';\n /** String content or function returning string (for non-component tabs) */\n content?: string | (() => string);\n /** Language hint for code highlighting (used with 'code' contentType) */\n language?: string;\n /** Angular component class to render (used with 'component' contentType) */\n component?: Type<any>;\n /** Inputs to pass to the custom component */\n componentInputs?: Record<string, any> | (() => Record<string, any>);\n}\n\n/**\n * Abstract base component for all artifact viewer plugins.\n * Provides common functionality and enforces the contract.\n * Note: This is an abstract class and should not be declared in Angular module.\n */\n@Component({\n standalone: false,\n template: ''\n})\nexport abstract class BaseArtifactViewerPluginComponent implements IArtifactViewerComponent {\n /**\n * The artifact version to display\n */\n @Input() artifactVersion!: MJArtifactVersionEntity;\n\n /**\n * Optional: Custom height for the viewer (defaults to auto)\n */\n @Input() height?: string;\n\n /**\n * Optional: Whether the viewer is in readonly mode\n */\n @Input() readonly: boolean = true;\n\n /**\n * Optional: Additional CSS classes to apply\n */\n @Input() cssClass?: string;\n\n /**\n * Whether this plugin is showing an \"elevated\" display (e.g., extracted markdown/HTML)\n * vs raw content. When true and content type is JSON, the wrapper will show a JSON tab.\n *\n * Subclasses should override this getter to return the appropriate value based on their\n * current display state. For example, JSON plugin returns true when showing displayMarkdown\n * or displayHtml, false when showing raw JSON editor.\n *\n * Default: false (showing raw content)\n */\n public get isShowingElevatedDisplay(): boolean {\n return false;\n }\n\n /**\n * Whether the parent wrapper should show a raw content tab (e.g., JSON tab for JSON content).\n * This gives plugins fine-grained control over the parent's tab display.\n *\n * Use cases:\n * - JSON plugin with extract rules: true (show JSON tab to view source)\n * - Component plugin: true (show JSON tab even when displaying elevated component)\n * - Code plugin: false (already showing raw content)\n *\n * Subclasses can override this to control parent behavior.\n * Default: true (parent should show raw content tab if applicable)\n */\n public get parentShouldShowRawContent(): boolean {\n return true;\n }\n\n /**\n * Whether this plugin has content to display in the Display tab.\n * Used by the parent wrapper to determine if the Display tab should be shown.\n *\n * Subclasses should override this getter to return true when they have\n * meaningful content to display.\n *\n * Default: false (subclasses must opt-in to showing Display tab)\n */\n public get hasDisplayContent(): boolean {\n return false;\n }\n\n /**\n * Get the content from the artifact version.\n * Handles both string content and JSON objects.\n */\n protected getContent(): string {\n if (!this.artifactVersion?.Content) {\n return '';\n }\n\n if (typeof this.artifactVersion.Content === 'string') {\n return this.artifactVersion.Content;\n }\n\n // If Content is an object, stringify it\n return JSON.stringify(this.artifactVersion.Content, null, 2);\n }\n\n /**\n * Parse JSON content safely\n */\n protected parseJsonContent<T = any>(): T | null {\n try {\n const content = this.getContent();\n return JSON.parse(content);\n } catch (error) {\n console.error('Failed to parse artifact content as JSON:', error);\n return null;\n }\n }\n\n /**\n * Get a safe display name for the artifact version\n */\n protected getDisplayName(): string {\n return this.artifactVersion?.Name || 'Untitled Artifact';\n }\n\n /**\n * Get the description\n */\n protected getDescription(): string {\n return this.artifactVersion?.Description || '';\n }\n\n /**\n * Optional: Emitted when the plugin's additional tabs change after async loading.\n * Plugins that load data asynchronously (e.g., from a component registry) should\n * emit this when loading completes and new tabs become available. The parent panel\n * listens for this to re-run change detection and render the updated tab list.\n */\n public tabsChanged?: EventEmitter<void>;\n\n /**\n * Optional: Emitted when the plugin wants to navigate to a different app/nav item.\n * Plugins that need app-level navigation (e.g., \"Open Query\" navigating to the\n * Data Explorer's Queries nav item) should instantiate this emitter and emit a\n * NavigationRequest. The event bubbles up through the artifact viewer chain to the\n * host application where NavigationService handles the actual navigation.\n */\n public navigationRequest?: EventEmitter<NavigationRequest>;\n\n /**\n * Whether this plugin supports user feedback.\n * Plugins that return true will get a feedback button in the artifact viewer header.\n * Override this getter to return true when feedback is available.\n *\n * Default: false\n */\n public get SupportsFeedback(): boolean {\n return false;\n }\n\n /**\n * Ask the user for feedback on the current artifact.\n * Called by the artifact viewer panel when the user clicks the feedback button in the header.\n * Each plugin implements its own feedback UX (dialog, panel, inline form, etc.).\n *\n * Default: no-op. Subclasses should override to implement artifact-type-specific feedback.\n */\n public AskUserForFeedback(): void {\n // Subclasses override to implement feedback UX\n }\n\n /**\n * Get additional tabs that this plugin wants to provide to the artifact viewer.\n * Override this method to provide custom tabs for viewing metadata, code, etc.\n *\n * @returns Array of tab definitions, or undefined if no additional tabs\n */\n public GetAdditionalTabs?(): ArtifactViewerTab[];\n\n /**\n * Get list of standard tabs that this plugin wants to hide/remove.\n * Use this when the plugin provides custom alternatives to standard tabs.\n *\n * Example: Component viewer provides custom \"Resolved JSON\" tab, so removes standard \"JSON\" tab\n *\n * @returns Array of standard tab names to remove (case-insensitive)\n * Valid values: 'JSON', 'Details', 'Links'\n * Note: 'Display' cannot be removed (it's the main view)\n */\n public GetStandardTabRemovals?(): string[];\n\n /**\n * Trigger a browser file download from a URL.\n * Shared by all file-backed viewer plugins (PDF, XLSX, DOCX) so the fetch →\n * blob → object-URL → anchor pattern lives in exactly one place.\n */\n protected async triggerBrowserDownload(url: string, fileName: string): Promise<void> {\n const response = await fetch(url);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = objectUrl;\n anchor.download = fileName;\n anchor.click();\n URL.revokeObjectURL(objectUrl);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base-artifact-viewer.component.js","sourceRoot":"","sources":["../../../src/lib/components/base-artifact-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,KAAK,EAAQ,MAAM,eAAe,CAAC;;AAsErE;;;;GAIG;AAKH,MAAM,OAAgB,iCAAiC;IACrD;;OAEG;IACM,eAAe,CAA2B;IAEnD;;OAEG;IACM,MAAM,CAAU;IAEzB;;OAEG;IACM,QAAQ,GAAY,IAAI,CAAC;IAElC;;OAEG;IACM,QAAQ,CAAU;IAE3B;;;;;;;;;OASG;IACH,IAAW,wBAAwB;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;;;OAWG;IACH,IAAW,0BAA0B;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,IAAW,iBAAiB;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACO,UAAU;QAClB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,CAAC;YACnC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;QACtC,CAAC;QAED,wCAAwC;QACxC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACO,gBAAgB;QACxB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACO,cAAc;QACtB,OAAO,IAAI,CAAC,eAAe,EAAE,IAAI,IAAI,mBAAmB,CAAC;IAC3D,CAAC;IAED;;OAEG;IACO,cAAc;QACtB,OAAO,IAAI,CAAC,eAAe,EAAE,WAAW,IAAI,EAAE,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACI,WAAW,CAAsB;IAExC;;;;;;OAMG;IACI,iBAAiB,CAAmC;IAE3D;;;;;;OAMG;IACH,IAAW,gBAAgB;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACI,kBAAkB;QACvB,+CAA+C;IACjD,CAAC;IAoCD;;;OAGG;IACO,aAAa;QACrB,OAAO,IAAI,CAAC,eAAe,EAAE,OAAO,IAAI,IAAI,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACO,eAAe;QACvB,OAAO,IAAI,CAAC,eAAe,EAAE,IAAI,IAAI,IAAI,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,sBAAsB,CAAC,GAAW,EAAE,QAAgB;QAClE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC;QACxB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;2HAnNmB,iCAAiC;6DAAjC,iCAAiC;;iFAAjC,iCAAiC;cAJtD,SAAS;eAAC;gBACT,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,EAAE;aACb;;kBAKE,KAAK;;kBAKL,KAAK;;kBAKL,KAAK;;kBAKL,KAAK;;kFAnBc,iCAAiC","sourcesContent":["import { Component, EventEmitter, Input, Type } from '@angular/core';\nimport { DataSnapshot } from '@memberjunction/core';\nimport { MJArtifactVersionEntity } from '@memberjunction/core-entities';\nimport { IArtifactViewerComponent } from '../interfaces/artifact-viewer-plugin.interface';\n\n/**\n * General-purpose navigation request emitted by artifact viewer plugins.\n * Allows plugins to request app-level navigation (e.g., switch to a specific\n * application, open a nav item, and set query parameters) without depending\n * on NavigationService directly.\n *\n * The event bubbles through ArtifactTypePluginViewer → ArtifactViewerPanel →\n * consumer (conversations, dashboards, etc.) → ultimately the Explorer wrapper\n * where NavigationService lives.\n */\nexport interface NavigationRequest {\n /** Target application name (e.g., 'Data Explorer'). If omitted, stays in current app. */\n appName?: string;\n\n /** Target navigation item label within the app (e.g., 'Queries') */\n navItemName: string;\n\n /** Query parameters to pass to the navigation target (e.g., { queryId: 'xxx' }) */\n queryParams?: Record<string, string>;\n}\n\n/**\n * Represents an additional tab that a plugin can provide to the artifact viewer.\n *\n * Tabs can render content in two ways:\n * 1. **String content** - Use `contentType` with `content` for built-in renderers (markdown, json, code, etc.)\n * 2. **Custom component** - Use `contentType: 'component'` with `component` and optional `componentInputs`\n *\n * @example\n * // String content tab\n * {\n * label: 'Code',\n * icon: 'fa-code',\n * contentType: 'code',\n * content: () => this.getCodeContent(),\n * language: 'typescript'\n * }\n *\n * @example\n * // Custom component tab\n * {\n * label: 'Data',\n * icon: 'fa-database',\n * contentType: 'component',\n * component: DataRequirementsViewerComponent,\n * componentInputs: { dataRequirements: this.spec.dataRequirements }\n * }\n */\nexport interface ArtifactViewerTab {\n /** Display label for the tab */\n label: string;\n /** Font Awesome icon class (without 'fas' prefix) */\n icon?: string;\n /** Type of content to render */\n contentType: 'plaintext' | 'html' | 'markdown' | 'json' | 'code' | 'component';\n /** String content or function returning string (for non-component tabs) */\n content?: string | (() => string);\n /** Language hint for code highlighting (used with 'code' contentType) */\n language?: string;\n /** Angular component class to render (used with 'component' contentType) */\n component?: Type<any>;\n /** Inputs to pass to the custom component */\n componentInputs?: Record<string, any> | (() => Record<string, any>);\n}\n\n/**\n * Abstract base component for all artifact viewer plugins.\n * Provides common functionality and enforces the contract.\n * Note: This is an abstract class and should not be declared in Angular module.\n */\n@Component({\n standalone: false,\n template: ''\n})\nexport abstract class BaseArtifactViewerPluginComponent implements IArtifactViewerComponent {\n /**\n * The artifact version to display\n */\n @Input() artifactVersion!: MJArtifactVersionEntity;\n\n /**\n * Optional: Custom height for the viewer (defaults to auto)\n */\n @Input() height?: string;\n\n /**\n * Optional: Whether the viewer is in readonly mode\n */\n @Input() readonly: boolean = true;\n\n /**\n * Optional: Additional CSS classes to apply\n */\n @Input() cssClass?: string;\n\n /**\n * Whether this plugin is showing an \"elevated\" display (e.g., extracted markdown/HTML)\n * vs raw content. When true and content type is JSON, the wrapper will show a JSON tab.\n *\n * Subclasses should override this getter to return the appropriate value based on their\n * current display state. For example, JSON plugin returns true when showing displayMarkdown\n * or displayHtml, false when showing raw JSON editor.\n *\n * Default: false (showing raw content)\n */\n public get isShowingElevatedDisplay(): boolean {\n return false;\n }\n\n /**\n * Whether the parent wrapper should show a raw content tab (e.g., JSON tab for JSON content).\n * This gives plugins fine-grained control over the parent's tab display.\n *\n * Use cases:\n * - JSON plugin with extract rules: true (show JSON tab to view source)\n * - Component plugin: true (show JSON tab even when displaying elevated component)\n * - Code plugin: false (already showing raw content)\n *\n * Subclasses can override this to control parent behavior.\n * Default: true (parent should show raw content tab if applicable)\n */\n public get parentShouldShowRawContent(): boolean {\n return true;\n }\n\n /**\n * Whether this plugin has content to display in the Display tab.\n * Used by the parent wrapper to determine if the Display tab should be shown.\n *\n * Subclasses should override this getter to return true when they have\n * meaningful content to display.\n *\n * Default: false (subclasses must opt-in to showing Display tab)\n */\n public get hasDisplayContent(): boolean {\n return false;\n }\n\n /**\n * Get the content from the artifact version.\n * Handles both string content and JSON objects.\n */\n protected getContent(): string {\n if (!this.artifactVersion?.Content) {\n return '';\n }\n\n if (typeof this.artifactVersion.Content === 'string') {\n return this.artifactVersion.Content;\n }\n\n // If Content is an object, stringify it\n return JSON.stringify(this.artifactVersion.Content, null, 2);\n }\n\n /**\n * Parse JSON content safely\n */\n protected parseJsonContent<T = any>(): T | null {\n try {\n const content = this.getContent();\n return JSON.parse(content);\n } catch (error) {\n console.error('Failed to parse artifact content as JSON:', error);\n return null;\n }\n }\n\n /**\n * Get a safe display name for the artifact version\n */\n protected getDisplayName(): string {\n return this.artifactVersion?.Name || 'Untitled Artifact';\n }\n\n /**\n * Get the description\n */\n protected getDescription(): string {\n return this.artifactVersion?.Description || '';\n }\n\n /**\n * Optional: Emitted when the plugin's additional tabs change after async loading.\n * Plugins that load data asynchronously (e.g., from a component registry) should\n * emit this when loading completes and new tabs become available. The parent panel\n * listens for this to re-run change detection and render the updated tab list.\n */\n public tabsChanged?: EventEmitter<void>;\n\n /**\n * Optional: Emitted when the plugin wants to navigate to a different app/nav item.\n * Plugins that need app-level navigation (e.g., \"Open Query\" navigating to the\n * Data Explorer's Queries nav item) should instantiate this emitter and emit a\n * NavigationRequest. The event bubbles up through the artifact viewer chain to the\n * host application where NavigationService handles the actual navigation.\n */\n public navigationRequest?: EventEmitter<NavigationRequest>;\n\n /**\n * Whether this plugin supports user feedback.\n * Plugins that return true will get a feedback button in the artifact viewer header.\n * Override this getter to return true when feedback is available.\n *\n * Default: false\n */\n public get SupportsFeedback(): boolean {\n return false;\n }\n\n /**\n * Ask the user for feedback on the current artifact.\n * Called by the artifact viewer panel when the user clicks the feedback button in the header.\n * Each plugin implements its own feedback UX (dialog, panel, inline form, etc.).\n *\n * Default: no-op. Subclasses should override to implement artifact-type-specific feedback.\n */\n public AskUserForFeedback(): void {\n // Subclasses override to implement feedback UX\n }\n\n /**\n * Get additional tabs that this plugin wants to provide to the artifact viewer.\n * Override this method to provide custom tabs for viewing metadata, code, etc.\n *\n * @returns Array of tab definitions, or undefined if no additional tabs\n */\n public GetAdditionalTabs?(): ArtifactViewerTab[];\n\n /**\n * Get list of standard tabs that this plugin wants to hide/remove.\n * Use this when the plugin provides custom alternatives to standard tabs.\n *\n * Example: Component viewer provides custom \"Resolved JSON\" tab, so removes standard \"JSON\" tab\n *\n * @returns Array of standard tab names to remove (case-insensitive)\n * Valid values: 'JSON', 'Details', 'Links'\n * Note: 'Display' cannot be removed (it's the main view)\n */\n public GetStandardTabRemovals?(): string[];\n\n /**\n * Return a point-in-time snapshot of the data this viewer is currently displaying.\n * Every viewer plugin MUST implement this with type-appropriate content.\n *\n * Guidelines for file-based viewers:\n * - PDF: page count, current page in interpretation, extracted text summary in custom\n * - Excel: each sheet as a DataTable in tables[], active sheet in activeTab\n * - Word: section count in interpretation, extracted text in custom\n * - For all: use getDisplayTitle() for snap.title\n *\n * @returns A DataSnapshot describing the current state, or null if no data is available.\n */\n public abstract GetCurrentStateSnapshot(): DataSnapshot | null;\n\n /**\n * Get the raw text content from the artifact version.\n * Returns null if no content is available.\n */\n protected getRawContent(): string | null {\n return this.artifactVersion?.Content ?? null;\n }\n\n /**\n * Get a display-friendly title for the artifact.\n * Returns null if no name is available.\n */\n protected getDisplayTitle(): string | null {\n return this.artifactVersion?.Name ?? null;\n }\n\n /**\n * Trigger a browser file download from a URL.\n * Shared by all file-backed viewer plugins (PDF, XLSX, DOCX) so the fetch →\n * blob → object-URL → anchor pattern lives in exactly one place.\n */\n protected async triggerBrowserDownload(url: string, fileName: string): Promise<void> {\n const response = await fetch(url);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = objectUrl;\n anchor.download = fileName;\n anchor.click();\n URL.revokeObjectURL(objectUrl);\n }\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DataSnapshot } from '@memberjunction/core';
|
|
1
2
|
import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
|
|
2
3
|
import * as i0 from "@angular/core";
|
|
3
4
|
/**
|
|
@@ -14,6 +15,7 @@ export declare class CodeArtifactViewerComponent extends BaseArtifactViewerPlugi
|
|
|
14
15
|
get hasDisplayContent(): boolean;
|
|
15
16
|
ngOnInit(): void;
|
|
16
17
|
private detectLanguage;
|
|
18
|
+
GetCurrentStateSnapshot(): DataSnapshot | null;
|
|
17
19
|
onCopy(): void;
|
|
18
20
|
static ɵfac: i0.ɵɵFactoryDeclaration<CodeArtifactViewerComponent, never>;
|
|
19
21
|
static ɵcmp: i0.ɵɵComponentDeclaration<CodeArtifactViewerComponent, "mj-code-artifact-viewer", never, { "contentType": { "alias": "contentType"; "required": false; }; }, {}, never, never, false, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/code-artifact-viewer.component.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"code-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/code-artifact-viewer.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,iCAAiC,EAAE,MAAM,mCAAmC,CAAC;;AAGtF;;GAEG;AACH,qBAwEa,2BAA4B,SAAQ,iCAAiC;IACzE,WAAW,SAAM;IACjB,QAAQ,SAAe;IACvB,aAAa,SAAU;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;OAEG;IACH,IAAoB,iBAAiB,IAAI,OAAO,CAE/C;IAED,QAAQ,IAAI,IAAI;IAKhB,OAAO,CAAC,cAAc;IAkCN,uBAAuB,IAAI,YAAY,GAAG,IAAI;IAI9D,MAAM,IAAI,IAAI;yCAzDH,2BAA2B;2CAA3B,2BAA2B;CAkEvC"}
|
|
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { Component, Input } from '@angular/core';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
|
|
10
|
+
import { createCodeSnapshot } from '../../snapshot-helpers';
|
|
10
11
|
import * as i0 from "@angular/core";
|
|
11
12
|
import * as i1 from "@angular/common";
|
|
12
13
|
import * as i2 from "@angular/forms";
|
|
@@ -69,6 +70,9 @@ let CodeArtifactViewerComponent = class CodeArtifactViewerComponent extends Base
|
|
|
69
70
|
this.languageLabel = 'Code';
|
|
70
71
|
}
|
|
71
72
|
}
|
|
73
|
+
GetCurrentStateSnapshot() {
|
|
74
|
+
return createCodeSnapshot(this.getRawContent(), this.getDisplayTitle());
|
|
75
|
+
}
|
|
72
76
|
onCopy() {
|
|
73
77
|
if (this.codeContent) {
|
|
74
78
|
navigator.clipboard.writeText(this.codeContent).then(() => {
|
|
@@ -127,5 +131,5 @@ export { CodeArtifactViewerComponent };
|
|
|
127
131
|
}], null, { contentType: [{
|
|
128
132
|
type: Input
|
|
129
133
|
}] }); })();
|
|
130
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CodeArtifactViewerComponent, { className: "CodeArtifactViewerComponent", filePath: "src/lib/components/plugins/code-artifact-viewer.component.ts", lineNumber:
|
|
134
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CodeArtifactViewerComponent, { className: "CodeArtifactViewerComponent", filePath: "src/lib/components/plugins/code-artifact-viewer.component.ts", lineNumber: 82 }); })();
|
|
131
135
|
//# sourceMappingURL=code-artifact-viewer.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/code-artifact-viewer.component.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"code-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/code-artifact-viewer.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input } from '@angular/core';\nimport { DataSnapshot } from '@memberjunction/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';\nimport { createCodeSnapshot } from '../../snapshot-helpers';\n\n/**\n * Viewer component for code artifacts (Python, C#, Java, TypeScript, JavaScript, SQL, CSS, XML)\n */\n@Component({\n standalone: false,\n selector: 'mj-code-artifact-viewer',\n template: `\n <div class=\"code-artifact-viewer\" [ngClass]=\"cssClass\">\n <div class=\"code-toolbar\">\n <div class=\"language-badge\">{{ languageLabel }}</div>\n <button class=\"btn-icon\" title=\"Copy Code\" (click)=\"onCopy()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"code-editor-container\">\n <mj-code-editor\n [(ngModel)]=\"codeContent\"\n [language]=\"language\"\n [readonly]=\"readonly\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n `,\n styles: [`\n .code-artifact-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .code-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px;\n background: #f5f5f5;\n border-bottom: 1px solid #ddd;\n }\n\n .language-badge {\n padding: 4px 12px;\n background: #007acc;\n color: white;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\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 .code-editor-container {\n flex: 1;\n overflow: auto;\n }\n `]\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'CodeArtifactViewerPlugin')\nexport class CodeArtifactViewerComponent extends BaseArtifactViewerPluginComponent {\n public codeContent = '';\n public language = 'plaintext';\n public languageLabel = 'Code';\n\n @Input() contentType?: string;\n\n /**\n * Code artifacts always have content to display\n */\n public override get hasDisplayContent(): boolean {\n return true;\n }\n\n ngOnInit(): void {\n this.codeContent = this.getContent();\n this.detectLanguage();\n }\n\n private detectLanguage(): void {\n const ct = this.contentType?.toLowerCase() || '';\n\n // Map content types to Monaco editor language modes\n if (ct.includes('python')) {\n this.language = 'python';\n this.languageLabel = 'Python';\n } else if (ct.includes('csharp') || ct.includes('c#')) {\n this.language = 'csharp';\n this.languageLabel = 'C#';\n } else if (ct.includes('java')) {\n this.language = 'java';\n this.languageLabel = 'Java';\n } else if (ct.includes('typescript')) {\n this.language = 'typescript';\n this.languageLabel = 'TypeScript';\n } else if (ct.includes('javascript')) {\n this.language = 'javascript';\n this.languageLabel = 'JavaScript';\n } else if (ct.includes('sql')) {\n this.language = 'sql';\n this.languageLabel = 'SQL';\n } else if (ct.includes('css')) {\n this.language = 'css';\n this.languageLabel = 'CSS';\n } else if (ct.includes('xml')) {\n this.language = 'xml';\n this.languageLabel = 'XML';\n } else {\n this.language = 'plaintext';\n this.languageLabel = 'Code';\n }\n }\n\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n return createCodeSnapshot(this.getRawContent(), this.getDisplayTitle());\n }\n\n onCopy(): void {\n if (this.codeContent) {\n navigator.clipboard.writeText(this.codeContent).then(() => {\n console.log('✅ Copied code to clipboard');\n }).catch(err => {\n console.error('Failed to copy to clipboard:', err);\n });\n }\n }\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import { AfterViewInit, OnInit, OnChanges, SimpleChanges, EventEmitter } from '@
|
|
|
2
2
|
import { BaseArtifactViewerPluginComponent, ArtifactViewerTab } from '../base-artifact-viewer.component';
|
|
3
3
|
import { MJReactComponent, AngularAdapterService } from '@memberjunction/ng-react';
|
|
4
4
|
import { ComponentSpec } from '@memberjunction/interactive-component-types';
|
|
5
|
-
import { CompositeKey } from '@memberjunction/core';
|
|
5
|
+
import { CompositeKey, DataSnapshot } from '@memberjunction/core';
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
7
|
/**
|
|
8
8
|
* Viewer component for interactive Component artifacts (React-based UI components)
|
|
@@ -86,6 +86,7 @@ export declare class ComponentArtifactViewerComponent extends BaseArtifactViewer
|
|
|
86
86
|
entityName: string;
|
|
87
87
|
key: CompositeKey;
|
|
88
88
|
}): void;
|
|
89
|
+
GetCurrentStateSnapshot(): DataSnapshot | null;
|
|
89
90
|
/**
|
|
90
91
|
* Component artifacts support feedback when a resolved spec is available.
|
|
91
92
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/component-artifact-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAU,YAAY,EAAE,MAAM,eAAe,CAAC;AAE5H,OAAO,EAAE,iCAAiC,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAA8B,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;;
|
|
1
|
+
{"version":3,"file":"component-artifact-viewer.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/plugins/component-artifact-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAU,YAAY,EAAE,MAAM,eAAe,CAAC;AAE5H,OAAO,EAAE,iCAAiC,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAA8B,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;;AAIlE;;;;;;;GAOG;AACH,qBAOa,gCAAiC,SAAQ,iCAAkC,YAAW,MAAM,EAAE,aAAa,EAAE,SAAS;IA6CrH,OAAO,CAAC,OAAO;IA5CE,cAAc,CAAC,EAAE,gBAAgB,CAAC;IACrD,WAAW,qBAA4B;IACvC,gBAAgB;oBAAiC,MAAM;sBAAgB,YAAY;OAAK;IAG3F,SAAS,EAAE,aAAa,GAAG,IAAI,CAAQ;IACvC,aAAa,EAAE,MAAM,CAAM;IAC3B,aAAa,EAAE,MAAM,CAAM;IAElC;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAA8B;IAEzD,IAAW,qBAAqB,IAAI,aAAa,GAAG,IAAI,CAKvD;IAGM,iBAAiB,UAAS;IAG1B,QAAQ,UAAS;IACjB,YAAY,SAAM;IAClB,YAAY,SAAM;IAEzB;;;;;;;;OAQG;IACH,IAAoB,iBAAiB,IAAI,OAAO,CAG/C;gBAEmB,OAAO,EAAE,qBAAqB;IAI5C,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAYzB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC;;OAEG;IACI,iBAAiB,IAAI,iBAAiB,EAAE;IA+D/C;;;OAGG;IACI,sBAAsB,IAAI,MAAM,EAAE;IAIzC,OAAO,CAAC,qBAAqB;IAS7B;;;;;;OAMG;IACH,2BAA2B,IAAI,IAAI;IASnC,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAYtC;;;OAGG;IACH,kBAAkB,CAAC,KAAK,EAAE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,YAAY,CAAA;KAAC,GAAG,IAAI;IAQxD,uBAAuB,IAAI,YAAY,GAAG,IAAI;IA8B9D;;OAEG;IACH,IAAoB,gBAAgB,IAAI,OAAO,CAE9C;IAED;;OAEG;IACa,kBAAkB,IAAI,IAAI;yCA7Q/B,gCAAgC;2CAAhC,gCAAgC;CAgR5C"}
|
|
@@ -8,6 +8,7 @@ import { Component, ViewChild, Output, EventEmitter } from '@angular/core';
|
|
|
8
8
|
import { RegisterClass, SafeJSONParse } from '@memberjunction/global';
|
|
9
9
|
import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
|
|
10
10
|
import { BuildComponentCompleteCode } from '@memberjunction/interactive-component-types';
|
|
11
|
+
import { DataSnapshot } from '@memberjunction/core';
|
|
11
12
|
import { DataRequirementsViewerComponent } from './data-requirements-viewer/data-requirements-viewer.component';
|
|
12
13
|
import * as i0 from "@angular/core";
|
|
13
14
|
import * as i1 from "@memberjunction/ng-react";
|
|
@@ -314,6 +315,34 @@ let ComponentArtifactViewerComponent = class ComponentArtifactViewerComponent ex
|
|
|
314
315
|
compositeKey: event.key
|
|
315
316
|
});
|
|
316
317
|
}
|
|
318
|
+
GetCurrentStateSnapshot() {
|
|
319
|
+
// First try the component's explicit or auto-captured data state.
|
|
320
|
+
// MJReactComponent.getCurrentDataState() already includes the fallback
|
|
321
|
+
// to intercepted RunView/RunQuery results when the React component
|
|
322
|
+
// doesn't register getCurrentDataState() via callbacks.RegisterMethod.
|
|
323
|
+
const dataState = this.reactComponent?.getCurrentDataState?.();
|
|
324
|
+
if (dataState && typeof dataState === 'object') {
|
|
325
|
+
return dataState;
|
|
326
|
+
}
|
|
327
|
+
// Fallback for components with no captured data — static mockups,
|
|
328
|
+
// pure-display components, or components whose data hooks haven't fired.
|
|
329
|
+
// Rather than short-circuit Analyze with "No data available", emit a
|
|
330
|
+
// minimal snapshot so the user can still open an agent conversation about
|
|
331
|
+
// the component. The artifact itself is attached to the conversation as an
|
|
332
|
+
// Input junction, so the agent can reason from the spec + any static data
|
|
333
|
+
// baked into the component code.
|
|
334
|
+
const spec = this.resolvedComponentSpec;
|
|
335
|
+
if (!spec)
|
|
336
|
+
return null;
|
|
337
|
+
const snap = new DataSnapshot();
|
|
338
|
+
snap.title = spec.title || spec.name || this.getDisplayTitle() || undefined;
|
|
339
|
+
snap.interpretation =
|
|
340
|
+
`Interactive component artifact${spec.name ? ` "${spec.name}"` : ''}. ` +
|
|
341
|
+
`No live data was captured — the component either has no data-fetching ` +
|
|
342
|
+
`hooks or has not yet run its queries. The component specification is ` +
|
|
343
|
+
`attached to this conversation; the agent should inspect it directly.`;
|
|
344
|
+
return snap;
|
|
345
|
+
}
|
|
317
346
|
/**
|
|
318
347
|
* Component artifacts support feedback when a resolved spec is available.
|
|
319
348
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/component-artifact-viewer.component.ts","../../../../src/lib/components/plugins/component-artifact-viewer.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ViewChild, AfterViewInit, OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';\nimport { RegisterClass, SafeJSONParse } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent, ArtifactViewerTab } from '../base-artifact-viewer.component';\nimport { MJReactComponent, AngularAdapterService } from '@memberjunction/ng-react';\nimport { BuildComponentCompleteCode, ComponentSpec } from '@memberjunction/interactive-component-types';\nimport { CompositeKey } from '@memberjunction/core';\nimport { DataRequirementsViewerComponent } from './data-requirements-viewer/data-requirements-viewer.component';\nimport { ComponentFeedbackPanelComponent } from './component-feedback-panel/component-feedback-panel.component';\n\n/**\n * Viewer component for interactive Component artifacts (React-based UI components)\n *\n * Features:\n * - Live component preview with React rendering\n * - Dynamic tabs for component metadata (via GetAdditionalTabs)\n * - Provides tabs for: Code, Functional Requirements, Technical Design, Data Requirements\n */\n@Component({\n standalone: false,\n selector: 'mj-component-artifact-viewer',\n templateUrl: './component-artifact-viewer.component.html',\n styleUrls: ['./component-artifact-viewer.component.css']\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'ComponentArtifactViewerPlugin')\nexport class ComponentArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit, AfterViewInit, OnChanges {\n @ViewChild('reactComponent') reactComponent?: MJReactComponent;\n @Output() tabsChanged = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n // Component data\n public component: ComponentSpec | null = null;\n public componentCode: string = \"\";\n public componentName: string = '';\n\n /**\n * Cached resolved spec from the registry, preserved even after the React component\n * is destroyed (e.g., when a render error removes <mj-react-component> from the DOM).\n */\n private _cachedResolvedSpec: ComponentSpec | null = null;\n\n public get resolvedComponentSpec(): ComponentSpec | null {\n // Prefer the live React component's resolved spec (most up-to-date),\n // then fall back to our cached copy (survives DOM destruction),\n // then fall back to the stripped local spec as last resort.\n return this.reactComponent?.resolvedComponentSpec || this._cachedResolvedSpec || this.component;\n }\n\n // Feedback panel\n public ShowFeedbackPanel = false;\n\n // Error state\n public hasError = false;\n public errorMessage = '';\n public errorDetails = '';\n\n /**\n * Whether this plugin has content to display in the Display tab.\n * Returns true only if the component has code that can be rendered.\n *\n * IMPORTANT: Uses this.component (synchronously loaded from artifact JSON)\n * instead of resolvedComponentSpec (which depends on async React loading).\n * This ensures hasDisplayContent returns correct value immediately when\n * pluginLoaded fires, before React component finishes loading.\n */\n public override get hasDisplayContent(): boolean {\n // Use this.component directly - it's available synchronously after loadComponentSpec()\n return !!this.component?.namespace || !!this.component?.code\n }\n\n constructor(private adapter: AngularAdapterService) {\n super();\n }\n\n async ngOnChanges(changes: SimpleChanges): Promise<void> {\n // When artifactVersion input changes, reload the component spec\n if (changes['artifactVersion']) {\n this.loadComponentSpec();\n // Notify parent that tabs may have changed (on subsequent changes)\n if (!changes['artifactVersion'].firstChange) {\n this.tabsChanged.emit();\n }\n }\n }\n\n /**\n * Synchronously load the component spec from artifact content.\n * This is intentionally synchronous so that tabs are available immediately\n * when the parent queries GetAdditionalTabs() after pluginLoaded fires.\n */\n private loadComponentSpec(): void {\n try {\n // Clear cached resolved spec from previous version so stale data doesn't persist\n this._cachedResolvedSpec = null;\n\n if (this.artifactVersion?.Content) {\n this.component = SafeJSONParse(this.artifactVersion.Content) as ComponentSpec;\n this.extractComponentParts();\n } else {\n throw new Error('Artifact content is empty');\n }\n } catch (error) {\n console.error('Failed to load component spec:', error);\n this.hasError = true;\n this.errorMessage = 'Failed to load component';\n this.errorDetails = error instanceof Error ? error.message : String(error);\n }\n }\n\n /**\n * Component initialization.\n * Note: loadComponentSpec() is called in ngOnChanges which runs before ngOnInit,\n * ensuring tabs are available when pluginLoaded fires.\n * The async adapter initialization happens here and doesn't block tab availability.\n */\n async ngOnInit(): Promise<void> {\n // Initialize Angular adapter for React components (async operation)\n try {\n await this.adapter.initialize();\n } catch (error) {\n console.error('Failed to initialize Angular adapter:', error);\n this.hasError = true;\n this.errorMessage = 'Failed to initialize component runtime';\n this.errorDetails = error instanceof Error ? error.message : String(error);\n }\n }\n\n async ngAfterViewInit(): Promise<void> {\n // Component initialization happens automatically via mj-react-component\n }\n\n /**\n * Provide additional tabs for viewing component metadata\n */\n public GetAdditionalTabs(): ArtifactViewerTab[] {\n const tabs: ArtifactViewerTab[] = [];\n\n const resolvedComponent = this.resolvedComponentSpec;\n\n if (!resolvedComponent) {\n return tabs;\n }\n\n // Functional Requirements tab\n if (resolvedComponent.functionalRequirements) {\n tabs.push({\n label: 'Functional',\n icon: 'fa-clipboard-list',\n contentType: 'markdown',\n content: resolvedComponent.functionalRequirements\n });\n }\n\n // Technical Design tab\n if (resolvedComponent.technicalDesign) {\n tabs.push({\n label: 'Technical',\n icon: 'fa-wrench',\n contentType: 'markdown',\n content: resolvedComponent.technicalDesign\n });\n }\n\n // Data Requirements tab - uses custom component for rich visualization\n if (resolvedComponent.dataRequirements) {\n tabs.push({\n label: 'Data',\n icon: 'fa-database',\n contentType: 'component',\n component: DataRequirementsViewerComponent,\n componentInputs: { dataRequirements: resolvedComponent.dataRequirements }\n });\n }\n\n // Code tab (lazy-loaded) - only show if there's actual code\n if (resolvedComponent.code && resolvedComponent.code.trim()) {\n tabs.push({\n label: 'Code',\n icon: 'fa-code',\n contentType: 'code',\n language: 'typescript',\n content: () => BuildComponentCompleteCode(resolvedComponent)\n });\n }\n\n // Spec tab - Shows fully resolved component spec in JSON format (rightmost)\n tabs.push({\n label: 'Spec',\n icon: 'fa-file-code',\n contentType: 'json',\n content: () => JSON.stringify(resolvedComponent, null, 2),\n language: 'json'\n });\n\n return tabs;\n }\n\n /**\n * Remove standard JSON tab since we provide \"Resolved JSON\" custom tab\n * The custom tab shows the fully resolved component spec instead of raw artifact JSON\n */\n public GetStandardTabRemovals(): string[] {\n return ['JSON'];\n }\n\n private extractComponentParts(): void {\n if (this.resolvedComponentSpec?.name) {\n this.componentName = this.resolvedComponentSpec.name;\n }\n if (this.resolvedComponentSpec?.code) {\n this.componentCode = BuildComponentCompleteCode(this.resolvedComponentSpec);\n }\n }\n\n /**\n * Called when MJReactComponent finishes loading the full component spec from the registry.\n * The full spec may contain Functional, Technical, and Data tabs not in the stripped spec.\n * Caches the resolved spec so it survives DOM destruction (e.g., if the component fails to\n * render and <mj-react-component> is removed by the @if/else block).\n * Emits tabsChanged so the parent panel re-evaluates allTabs and renders the new tab labels.\n */\n onReactComponentInitialized(): void {\n if (this.reactComponent?.resolvedComponentSpec &&\n this.reactComponent.resolvedComponentSpec !== this.component) {\n // Cache the resolved spec so it's available even after the React component is destroyed\n this._cachedResolvedSpec = this.reactComponent.resolvedComponentSpec;\n this.tabsChanged.emit();\n }\n }\n\n onComponentEvent(event: unknown): void {\n console.log('Component event:', event);\n\n // Handle error events from React component\n if (event && typeof event === 'object' && 'type' in event && event.type === 'error') {\n const errorEvent = event as { type: 'error'; payload: { error: string; source: string } };\n this.hasError = true;\n this.errorMessage = 'Component Failed to Load';\n this.errorDetails = errorEvent.payload.error || 'Unknown error occurred while loading the component';\n }\n }\n\n /**\n * Handle entity record open request from React component\n * Propagates the event up to parent components\n */\n onOpenEntityRecord(event: {entityName: string; key: CompositeKey}): void {\n // Transform to use 'compositeKey' name for consistency with Angular components\n this.openEntityRecord.emit({\n entityName: event.entityName,\n compositeKey: event.key\n });\n }\n\n /**\n * Component artifacts support feedback when a resolved spec is available.\n */\n public override get SupportsFeedback(): boolean {\n return !!this.resolvedComponentSpec;\n }\n\n /**\n * Toggle the feedback panel open. Called from the artifact viewer header button.\n */\n public override AskUserForFeedback(): void {\n this.ShowFeedbackPanel = !this.ShowFeedbackPanel;\n }\n}\n","<div class=\"component-artifact-viewer\" [ngClass]=\"cssClass\">\n <!-- Component Preview (full screen) -->\n <div class=\"component-preview\">\n @if (hasError) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>{{ errorMessage }}</h3>\n <p>This component could not be loaded. This usually happens when:</p>\n <ul style=\"text-align: left; max-width: 500px; color: var(--mj-text-muted); line-height: 1.6;\">\n <li>The component registry is unavailable or unreachable</li>\n <li>The component version does not exist in the registry</li>\n <li>There was a network error during component retrieval</li>\n </ul>\n @if (errorDetails) {\n <details style=\"margin-top: 20px;\">\n <summary>Technical Details</summary>\n <pre>{{ errorDetails }}</pre>\n </details>\n }\n </div>\n } @else {\n <!-- Only render React component if there's code to execute -->\n @if (component && (component.code || component.namespace)) {\n <mj-react-component\n #reactComponent\n [component]=\"component\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\"\n (initialized)=\"onReactComponentInitialized()\">\n </mj-react-component>\n } @else if (component) {\n <!-- Component spec exists but no code - show informational message -->\n <div class=\"no-code-state\">\n <i class=\"fa-solid fa-file-lines\"></i>\n <h3>Component Specification</h3>\n <p>This component has specifications but no executable code yet.</p>\n <p>View the Functional, Data, or Spec tabs for details.</p>\n </div>\n } @else {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n <h3>No Component Loaded</h3>\n <p>The component data is missing or invalid.</p>\n </div>\n }\n }\n </div>\n\n <!-- Feedback overlay panel (invoked from header button via AskUserForFeedback) -->\n @if (ShowFeedbackPanel && resolvedComponentSpec) {\n <mj-component-feedback-panel\n [ComponentSpec]=\"resolvedComponentSpec\"\n [ReactContainerElement]=\"reactComponent?.container?.nativeElement || null\"\n (Closed)=\"ShowFeedbackPanel = false\">\n </mj-component-feedback-panel>\n }\n</div>\n\n"]}
|
|
1
|
+
{"version":3,"file":"component-artifact-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/components/plugins/component-artifact-viewer.component.ts","../../../../src/lib/components/plugins/component-artifact-viewer.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, ViewChild, AfterViewInit, OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';\nimport { RegisterClass, SafeJSONParse } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent, ArtifactViewerTab } from '../base-artifact-viewer.component';\nimport { MJReactComponent, AngularAdapterService } from '@memberjunction/ng-react';\nimport { BuildComponentCompleteCode, ComponentSpec } from '@memberjunction/interactive-component-types';\nimport { CompositeKey, DataSnapshot } from '@memberjunction/core';\nimport { DataRequirementsViewerComponent } from './data-requirements-viewer/data-requirements-viewer.component';\nimport { ComponentFeedbackPanelComponent } from './component-feedback-panel/component-feedback-panel.component';\n\n/**\n * Viewer component for interactive Component artifacts (React-based UI components)\n *\n * Features:\n * - Live component preview with React rendering\n * - Dynamic tabs for component metadata (via GetAdditionalTabs)\n * - Provides tabs for: Code, Functional Requirements, Technical Design, Data Requirements\n */\n@Component({\n standalone: false,\n selector: 'mj-component-artifact-viewer',\n templateUrl: './component-artifact-viewer.component.html',\n styleUrls: ['./component-artifact-viewer.component.css']\n})\n@RegisterClass(BaseArtifactViewerPluginComponent, 'ComponentArtifactViewerPlugin')\nexport class ComponentArtifactViewerComponent extends BaseArtifactViewerPluginComponent implements OnInit, AfterViewInit, OnChanges {\n @ViewChild('reactComponent') reactComponent?: MJReactComponent;\n @Output() tabsChanged = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{entityName: string; compositeKey: CompositeKey}>();\n\n // Component data\n public component: ComponentSpec | null = null;\n public componentCode: string = \"\";\n public componentName: string = '';\n\n /**\n * Cached resolved spec from the registry, preserved even after the React component\n * is destroyed (e.g., when a render error removes <mj-react-component> from the DOM).\n */\n private _cachedResolvedSpec: ComponentSpec | null = null;\n\n public get resolvedComponentSpec(): ComponentSpec | null {\n // Prefer the live React component's resolved spec (most up-to-date),\n // then fall back to our cached copy (survives DOM destruction),\n // then fall back to the stripped local spec as last resort.\n return this.reactComponent?.resolvedComponentSpec || this._cachedResolvedSpec || this.component;\n }\n\n // Feedback panel\n public ShowFeedbackPanel = false;\n\n // Error state\n public hasError = false;\n public errorMessage = '';\n public errorDetails = '';\n\n /**\n * Whether this plugin has content to display in the Display tab.\n * Returns true only if the component has code that can be rendered.\n *\n * IMPORTANT: Uses this.component (synchronously loaded from artifact JSON)\n * instead of resolvedComponentSpec (which depends on async React loading).\n * This ensures hasDisplayContent returns correct value immediately when\n * pluginLoaded fires, before React component finishes loading.\n */\n public override get hasDisplayContent(): boolean {\n // Use this.component directly - it's available synchronously after loadComponentSpec()\n return !!this.component?.namespace || !!this.component?.code\n }\n\n constructor(private adapter: AngularAdapterService) {\n super();\n }\n\n async ngOnChanges(changes: SimpleChanges): Promise<void> {\n // When artifactVersion input changes, reload the component spec\n if (changes['artifactVersion']) {\n this.loadComponentSpec();\n // Notify parent that tabs may have changed (on subsequent changes)\n if (!changes['artifactVersion'].firstChange) {\n this.tabsChanged.emit();\n }\n }\n }\n\n /**\n * Synchronously load the component spec from artifact content.\n * This is intentionally synchronous so that tabs are available immediately\n * when the parent queries GetAdditionalTabs() after pluginLoaded fires.\n */\n private loadComponentSpec(): void {\n try {\n // Clear cached resolved spec from previous version so stale data doesn't persist\n this._cachedResolvedSpec = null;\n\n if (this.artifactVersion?.Content) {\n this.component = SafeJSONParse(this.artifactVersion.Content) as ComponentSpec;\n this.extractComponentParts();\n } else {\n throw new Error('Artifact content is empty');\n }\n } catch (error) {\n console.error('Failed to load component spec:', error);\n this.hasError = true;\n this.errorMessage = 'Failed to load component';\n this.errorDetails = error instanceof Error ? error.message : String(error);\n }\n }\n\n /**\n * Component initialization.\n * Note: loadComponentSpec() is called in ngOnChanges which runs before ngOnInit,\n * ensuring tabs are available when pluginLoaded fires.\n * The async adapter initialization happens here and doesn't block tab availability.\n */\n async ngOnInit(): Promise<void> {\n // Initialize Angular adapter for React components (async operation)\n try {\n await this.adapter.initialize();\n } catch (error) {\n console.error('Failed to initialize Angular adapter:', error);\n this.hasError = true;\n this.errorMessage = 'Failed to initialize component runtime';\n this.errorDetails = error instanceof Error ? error.message : String(error);\n }\n }\n\n async ngAfterViewInit(): Promise<void> {\n // Component initialization happens automatically via mj-react-component\n }\n\n /**\n * Provide additional tabs for viewing component metadata\n */\n public GetAdditionalTabs(): ArtifactViewerTab[] {\n const tabs: ArtifactViewerTab[] = [];\n\n const resolvedComponent = this.resolvedComponentSpec;\n\n if (!resolvedComponent) {\n return tabs;\n }\n\n // Functional Requirements tab\n if (resolvedComponent.functionalRequirements) {\n tabs.push({\n label: 'Functional',\n icon: 'fa-clipboard-list',\n contentType: 'markdown',\n content: resolvedComponent.functionalRequirements\n });\n }\n\n // Technical Design tab\n if (resolvedComponent.technicalDesign) {\n tabs.push({\n label: 'Technical',\n icon: 'fa-wrench',\n contentType: 'markdown',\n content: resolvedComponent.technicalDesign\n });\n }\n\n // Data Requirements tab - uses custom component for rich visualization\n if (resolvedComponent.dataRequirements) {\n tabs.push({\n label: 'Data',\n icon: 'fa-database',\n contentType: 'component',\n component: DataRequirementsViewerComponent,\n componentInputs: { dataRequirements: resolvedComponent.dataRequirements }\n });\n }\n\n // Code tab (lazy-loaded) - only show if there's actual code\n if (resolvedComponent.code && resolvedComponent.code.trim()) {\n tabs.push({\n label: 'Code',\n icon: 'fa-code',\n contentType: 'code',\n language: 'typescript',\n content: () => BuildComponentCompleteCode(resolvedComponent)\n });\n }\n\n // Spec tab - Shows fully resolved component spec in JSON format (rightmost)\n tabs.push({\n label: 'Spec',\n icon: 'fa-file-code',\n contentType: 'json',\n content: () => JSON.stringify(resolvedComponent, null, 2),\n language: 'json'\n });\n\n return tabs;\n }\n\n /**\n * Remove standard JSON tab since we provide \"Resolved JSON\" custom tab\n * The custom tab shows the fully resolved component spec instead of raw artifact JSON\n */\n public GetStandardTabRemovals(): string[] {\n return ['JSON'];\n }\n\n private extractComponentParts(): void {\n if (this.resolvedComponentSpec?.name) {\n this.componentName = this.resolvedComponentSpec.name;\n }\n if (this.resolvedComponentSpec?.code) {\n this.componentCode = BuildComponentCompleteCode(this.resolvedComponentSpec);\n }\n }\n\n /**\n * Called when MJReactComponent finishes loading the full component spec from the registry.\n * The full spec may contain Functional, Technical, and Data tabs not in the stripped spec.\n * Caches the resolved spec so it survives DOM destruction (e.g., if the component fails to\n * render and <mj-react-component> is removed by the @if/else block).\n * Emits tabsChanged so the parent panel re-evaluates allTabs and renders the new tab labels.\n */\n onReactComponentInitialized(): void {\n if (this.reactComponent?.resolvedComponentSpec &&\n this.reactComponent.resolvedComponentSpec !== this.component) {\n // Cache the resolved spec so it's available even after the React component is destroyed\n this._cachedResolvedSpec = this.reactComponent.resolvedComponentSpec;\n this.tabsChanged.emit();\n }\n }\n\n onComponentEvent(event: unknown): void {\n console.log('Component event:', event);\n\n // Handle error events from React component\n if (event && typeof event === 'object' && 'type' in event && event.type === 'error') {\n const errorEvent = event as { type: 'error'; payload: { error: string; source: string } };\n this.hasError = true;\n this.errorMessage = 'Component Failed to Load';\n this.errorDetails = errorEvent.payload.error || 'Unknown error occurred while loading the component';\n }\n }\n\n /**\n * Handle entity record open request from React component\n * Propagates the event up to parent components\n */\n onOpenEntityRecord(event: {entityName: string; key: CompositeKey}): void {\n // Transform to use 'compositeKey' name for consistency with Angular components\n this.openEntityRecord.emit({\n entityName: event.entityName,\n compositeKey: event.key\n });\n }\n\n public override GetCurrentStateSnapshot(): DataSnapshot | null {\n // First try the component's explicit or auto-captured data state.\n // MJReactComponent.getCurrentDataState() already includes the fallback\n // to intercepted RunView/RunQuery results when the React component\n // doesn't register getCurrentDataState() via callbacks.RegisterMethod.\n const dataState = this.reactComponent?.getCurrentDataState?.();\n if (dataState && typeof dataState === 'object') {\n return dataState as DataSnapshot;\n }\n\n // Fallback for components with no captured data — static mockups,\n // pure-display components, or components whose data hooks haven't fired.\n // Rather than short-circuit Analyze with \"No data available\", emit a\n // minimal snapshot so the user can still open an agent conversation about\n // the component. The artifact itself is attached to the conversation as an\n // Input junction, so the agent can reason from the spec + any static data\n // baked into the component code.\n const spec = this.resolvedComponentSpec;\n if (!spec) return null;\n\n const snap = new DataSnapshot();\n snap.title = spec.title || spec.name || this.getDisplayTitle() || undefined;\n snap.interpretation =\n `Interactive component artifact${spec.name ? ` \"${spec.name}\"` : ''}. ` +\n `No live data was captured — the component either has no data-fetching ` +\n `hooks or has not yet run its queries. The component specification is ` +\n `attached to this conversation; the agent should inspect it directly.`;\n return snap;\n }\n\n /**\n * Component artifacts support feedback when a resolved spec is available.\n */\n public override get SupportsFeedback(): boolean {\n return !!this.resolvedComponentSpec;\n }\n\n /**\n * Toggle the feedback panel open. Called from the artifact viewer header button.\n */\n public override AskUserForFeedback(): void {\n this.ShowFeedbackPanel = !this.ShowFeedbackPanel;\n }\n}\n","<div class=\"component-artifact-viewer\" [ngClass]=\"cssClass\">\n <!-- Component Preview (full screen) -->\n <div class=\"component-preview\">\n @if (hasError) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>{{ errorMessage }}</h3>\n <p>This component could not be loaded. This usually happens when:</p>\n <ul style=\"text-align: left; max-width: 500px; color: var(--mj-text-muted); line-height: 1.6;\">\n <li>The component registry is unavailable or unreachable</li>\n <li>The component version does not exist in the registry</li>\n <li>There was a network error during component retrieval</li>\n </ul>\n @if (errorDetails) {\n <details style=\"margin-top: 20px;\">\n <summary>Technical Details</summary>\n <pre>{{ errorDetails }}</pre>\n </details>\n }\n </div>\n } @else {\n <!-- Only render React component if there's code to execute -->\n @if (component && (component.code || component.namespace)) {\n <mj-react-component\n #reactComponent\n [component]=\"component\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\"\n (initialized)=\"onReactComponentInitialized()\">\n </mj-react-component>\n } @else if (component) {\n <!-- Component spec exists but no code - show informational message -->\n <div class=\"no-code-state\">\n <i class=\"fa-solid fa-file-lines\"></i>\n <h3>Component Specification</h3>\n <p>This component has specifications but no executable code yet.</p>\n <p>View the Functional, Data, or Spec tabs for details.</p>\n </div>\n } @else {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n <h3>No Component Loaded</h3>\n <p>The component data is missing or invalid.</p>\n </div>\n }\n }\n </div>\n\n <!-- Feedback overlay panel (invoked from header button via AskUserForFeedback) -->\n @if (ShowFeedbackPanel && resolvedComponentSpec) {\n <mj-component-feedback-panel\n [ComponentSpec]=\"resolvedComponentSpec\"\n [ReactContainerElement]=\"reactComponent?.container?.nativeElement || null\"\n (Closed)=\"ShowFeedbackPanel = false\">\n </mj-component-feedback-panel>\n }\n</div>\n\n"]}
|
|
@@ -1,61 +1,44 @@
|
|
|
1
1
|
import { OnInit, ChangeDetectorRef, EventEmitter } from '@angular/core';
|
|
2
|
-
import { CompositeKey } from '@memberjunction/core';
|
|
2
|
+
import { DataSnapshot, DataTable, DataComputation, MJColumnDescriptor, CompositeKey } from '@memberjunction/core';
|
|
3
3
|
import { QueryGridColumnConfig, QueryEntityLinkClickEvent } from '@memberjunction/ng-query-viewer';
|
|
4
4
|
import { PageChangeEvent } from '@memberjunction/ng-pagination';
|
|
5
5
|
import { BaseArtifactViewerPluginComponent, ArtifactViewerTab, NavigationRequest } from '../base-artifact-viewer.component';
|
|
6
6
|
import { SaveQueryResult } from './save-query-dialog.component';
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Data artifact content shape as parsed from JSON.
|
|
10
|
+
*
|
|
11
|
+
* Core tabular data fields (source, columns, rows, tables, metadata, etc.)
|
|
12
|
+
* are handled by NormalizeToTables() from @memberjunction/core.
|
|
13
|
+
* This interface adds viewer-specific fields for query sync and display.
|
|
14
|
+
*
|
|
15
|
+
* Columns may use either `displayName` (new) or `headerName` (legacy).
|
|
16
|
+
* BuildColumnConfigsForTable handles both.
|
|
11
17
|
*/
|
|
12
18
|
interface DataArtifactSpec {
|
|
13
|
-
|
|
14
|
-
source: 'query' | 'view';
|
|
15
|
-
/** Display title for the data */
|
|
19
|
+
source?: 'query' | 'view';
|
|
16
20
|
title?: string;
|
|
17
|
-
/** For query source: the query ID to render via mj-query-viewer */
|
|
18
21
|
queryId?: string;
|
|
19
|
-
/** For query source: parameter values to pass */
|
|
20
22
|
parameters?: Record<string, string | number | boolean>;
|
|
21
|
-
/** For view source: the entity name */
|
|
22
23
|
entityName?: string;
|
|
23
|
-
/** For view source: extra WHERE filter */
|
|
24
24
|
extraFilter?: string;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
columns?: Array<MJColumnDescriptor & {
|
|
26
|
+
headerName?: string;
|
|
27
|
+
}>;
|
|
28
28
|
rows?: Record<string, unknown>[];
|
|
29
|
-
|
|
29
|
+
tables?: DataTable[];
|
|
30
30
|
plan?: string;
|
|
31
|
-
|
|
31
|
+
interpretation?: string;
|
|
32
|
+
computations?: DataComputation[];
|
|
32
33
|
metadata?: {
|
|
33
34
|
sql?: string;
|
|
34
35
|
rowCount?: number;
|
|
35
36
|
executionTimeMs?: number;
|
|
36
37
|
};
|
|
37
|
-
/** ID of saved query (set after user saves from artifact) */
|
|
38
38
|
savedQueryId?: string;
|
|
39
|
-
/** Name of saved query (for display) */
|
|
40
39
|
savedQueryName?: string;
|
|
41
|
-
/** Version number this query was saved/updated from */
|
|
42
40
|
savedAtVersionNumber?: number;
|
|
43
41
|
}
|
|
44
|
-
interface DataArtifactColumn {
|
|
45
|
-
field: string;
|
|
46
|
-
headerName?: string;
|
|
47
|
-
width?: number;
|
|
48
|
-
/** MJ entity name this column originates from (e.g., "Members") */
|
|
49
|
-
sourceEntity?: string;
|
|
50
|
-
/** Field name in that entity (e.g., "ID", "FirstName") */
|
|
51
|
-
sourceFieldName?: string;
|
|
52
|
-
/** True for calculated expressions (CASE, ROUND, CONCAT, etc.) */
|
|
53
|
-
isComputed?: boolean;
|
|
54
|
-
/** True for aggregate functions (SUM, COUNT, AVG, etc.) */
|
|
55
|
-
isSummary?: boolean;
|
|
56
|
-
/** SQL data type: int, nvarchar, uniqueidentifier, datetime, decimal, bit, money, etc. */
|
|
57
|
-
sqlBaseType?: string;
|
|
58
|
-
}
|
|
59
42
|
/**
|
|
60
43
|
* Describes the relationship between the current artifact version's SQL
|
|
61
44
|
* and the saved query record. Drives the toolbar UI.
|
|
@@ -94,6 +77,20 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
|
|
|
94
77
|
PagerTotalRowCount: number;
|
|
95
78
|
PagerPageNumber: number;
|
|
96
79
|
PagerPageSize: number;
|
|
80
|
+
/** All resolved tables (from multi-table or wrapped single-table) */
|
|
81
|
+
ResolvedTables: DataTable[];
|
|
82
|
+
/** Index of the currently active table tab */
|
|
83
|
+
ActiveTableIndex: number;
|
|
84
|
+
/** Per-table paging state */
|
|
85
|
+
private tablePageState;
|
|
86
|
+
/** Per-table live data cache (loaded lazily on tab switch) */
|
|
87
|
+
private tableDataCache;
|
|
88
|
+
/** Per-table column configs cache */
|
|
89
|
+
private tableColumnConfigsCache;
|
|
90
|
+
/** Whether we're in multi-table mode */
|
|
91
|
+
get IsMultiTable(): boolean;
|
|
92
|
+
/** The currently active table */
|
|
93
|
+
get ActiveTable(): DataTable | null;
|
|
97
94
|
/** Query sync state — drives the toolbar UI for saved query actions */
|
|
98
95
|
QuerySyncState: QuerySyncState;
|
|
99
96
|
/** Latest version number for this artifact (from cache) */
|
|
@@ -128,7 +125,7 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
|
|
|
128
125
|
get SavedQueryDisplayName(): string;
|
|
129
126
|
ngOnInit(): Promise<void>;
|
|
130
127
|
/**
|
|
131
|
-
* Re-execute the live SQL query
|
|
128
|
+
* Re-execute the live SQL query for the active table
|
|
132
129
|
*/
|
|
133
130
|
OnRefresh(): Promise<void>;
|
|
134
131
|
/**
|
|
@@ -138,23 +135,28 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
|
|
|
138
135
|
OnEntityLinkClick(event: QueryEntityLinkClickEvent): void;
|
|
139
136
|
/**
|
|
140
137
|
* Handle page change from the data grid's embedded pager.
|
|
141
|
-
* Re-executes the
|
|
138
|
+
* Re-executes the query for the active table with new page parameters.
|
|
142
139
|
*/
|
|
143
140
|
OnPageChange(event: PageChangeEvent): Promise<void>;
|
|
144
141
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
142
|
+
* Switch to a different table tab.
|
|
143
|
+
* Loads data lazily if not already cached.
|
|
147
144
|
*/
|
|
148
|
-
|
|
145
|
+
OnTableTabClick(index: number): Promise<void>;
|
|
149
146
|
/**
|
|
150
|
-
*
|
|
147
|
+
* Load data for a specific table.
|
|
148
|
+
* Handles live SQL execution, inline rows, and caching.
|
|
149
|
+
*/
|
|
150
|
+
private LoadTableData;
|
|
151
|
+
/**
|
|
152
|
+
* Build QueryGridColumnConfig[] from a DataTable's column metadata.
|
|
151
153
|
* Returns null if columns have no entity metadata (grid falls back to auto-inference).
|
|
152
154
|
*/
|
|
153
|
-
private
|
|
155
|
+
private BuildColumnConfigsForTable;
|
|
154
156
|
/**
|
|
155
|
-
* Handle a
|
|
157
|
+
* Handle a table load error by setting error state and falling back to inline data
|
|
156
158
|
*/
|
|
157
|
-
private
|
|
159
|
+
private HandleTableError;
|
|
158
160
|
/**
|
|
159
161
|
* Initialize query sync state by loading cached metadata.
|
|
160
162
|
* Resolves the latest version number and compares saved query SQL.
|
|
@@ -207,7 +209,12 @@ export declare class DataArtifactViewerComponent extends BaseArtifactViewerPlugi
|
|
|
207
209
|
/** Persist updated spec back to the artifact version entity */
|
|
208
210
|
private PersistArtifactContent;
|
|
209
211
|
/**
|
|
210
|
-
*
|
|
212
|
+
* Returns a DataSnapshot with live grid data, current page state,
|
|
213
|
+
* and query sync state.
|
|
214
|
+
*/
|
|
215
|
+
GetCurrentStateSnapshot(): DataSnapshot | null;
|
|
216
|
+
/**
|
|
217
|
+
* Provide Plan tab (markdown), SQL tab (code), and Interpretation tab when available
|
|
211
218
|
*/
|
|
212
219
|
GetAdditionalTabs(): ArtifactViewerTab[];
|
|
213
220
|
static ɵfac: i0.ɵɵFactoryDeclaration<DataArtifactViewerComponent, never>;
|
|
@@ -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":"AAAA,OAAO,EAAa,MAAM,EAAE,iBAAiB,EAAU,YAAY,EAAE,MAAM,eAAe,CAAC;AAE3F,OAAO,
|
|
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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"}
|