@memberjunction/ng-dashboard-viewer 5.30.1 → 5.32.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/config-panels/artifact-config-panel.component.d.ts.map +1 -1
- package/dist/lib/config-panels/artifact-config-panel.component.js +3 -4
- package/dist/lib/config-panels/artifact-config-panel.component.js.map +1 -1
- package/dist/lib/config-panels/base-config-panel.d.ts +2 -1
- package/dist/lib/config-panels/base-config-panel.d.ts.map +1 -1
- package/dist/lib/config-panels/base-config-panel.js +4 -2
- package/dist/lib/config-panels/base-config-panel.js.map +1 -1
- package/dist/lib/dashboard-viewer/dashboard-viewer.component.d.ts +2 -1
- package/dist/lib/dashboard-viewer/dashboard-viewer.component.d.ts.map +1 -1
- package/dist/lib/dashboard-viewer/dashboard-viewer.component.js +7 -6
- package/dist/lib/dashboard-viewer/dashboard-viewer.component.js.map +1 -1
- package/dist/lib/parts/artifact-part.component.d.ts.map +1 -1
- package/dist/lib/parts/artifact-part.component.js +1 -2
- package/dist/lib/parts/artifact-part.component.js.map +1 -1
- package/dist/lib/parts/base-dashboard-part.d.ts +2 -1
- package/dist/lib/parts/base-dashboard-part.d.ts.map +1 -1
- package/dist/lib/parts/base-dashboard-part.js +4 -2
- package/dist/lib/parts/base-dashboard-part.js.map +1 -1
- package/dist/lib/parts/query-part.component.d.ts.map +1 -1
- package/dist/lib/parts/query-part.component.js +4 -5
- package/dist/lib/parts/query-part.component.js.map +1 -1
- package/dist/lib/parts/view-part.component.d.ts.map +1 -1
- package/dist/lib/parts/view-part.component.js +5 -6
- package/dist/lib/parts/view-part.component.js.map +1 -1
- package/package.json +11 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-dashboard-part.js","sourceRoot":"","sources":["../../../src/lib/parts/base-dashboard-part.ts"],"names":[],"mappings":"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","sourcesContent":["import { Input, Output, EventEmitter, ChangeDetectorRef, Directive, OnInit, OnDestroy } from '@angular/core';\nimport { MJDashboardPartTypeEntity } from '@memberjunction/core-entities';\nimport {\n PanelConfig,\n DashboardPanel,\n DashboardNavRequest,\n DashboardNavRequestEvent,\n OpenEntityRecordNavRequest,\n OpenDashboardNavRequest,\n OpenQueryNavRequest,\n OpenApplicationNavRequest,\n OpenNavItemNavRequest\n} from '../models/dashboard-types';\n\n/**\n * Event emitted when a part requests configuration\n */\nexport interface PartConfigureEvent {\n /** The panel requesting configuration */\n Panel: DashboardPanel;\n /** The part type */\n PartType: MJDashboardPartTypeEntity;\n}\n\n/**\n * Event emitted when a part requests removal\n */\nexport interface PartRemoveEvent {\n /** The panel to remove */\n Panel: DashboardPanel;\n}\n\n/**\n * Event emitted when a part's data changes\n */\nexport interface PartDataChangeEvent {\n /** The panel whose data changed */\n Panel: DashboardPanel;\n /** The new data (type depends on part type) */\n Data: unknown;\n}\n\n/**\n * Base class for dashboard part renderers.\n *\n * Each part type (View, Query, Artifact, WebURL, etc.) has a renderer component\n * that extends this class. The renderer is responsible for:\n * 1. Displaying the part's content based on its configuration\n * 2. Handling edit mode UI (configure/remove buttons)\n * 3. Emitting events for user interactions\n *\n * Subclasses are registered with @RegisterClass(BaseDashboardPart, 'PartTypeName')\n * and instantiated via ClassFactory using the DashboardPartType.DriverClass field.\n *\n * This allows new part types to be added by:\n * 1. Creating a new component that extends BaseDashboardPart\n * 2. Registering it with @RegisterClass\n * 3. Adding a DashboardPartType record with the DriverClass set to the registered name\n */\n@Directive()\nexport abstract class BaseDashboardPart implements OnInit, OnDestroy {\n /**\n * The panel data including ID, title, icon, and configuration\n */\n @Input()\n set Panel(value: DashboardPanel | null) {\n const previous = this._panel;\n this._panel = value;\n if (value !== previous) {\n this.onPanelChanged(value, previous);\n }\n }\n get Panel(): DashboardPanel | null {\n return this._panel;\n }\n private _panel: DashboardPanel | null = null;\n\n /**\n * The part type metadata\n */\n @Input() PartType: MJDashboardPartTypeEntity | null = null;\n\n /**\n * Whether the dashboard is in edit mode\n */\n @Input()\n set IsEditing(value: boolean) {\n const previous = this._isEditing;\n this._isEditing = value;\n if (value !== previous) {\n this.onEditModeChanged(value);\n }\n }\n get IsEditing(): boolean {\n return this._isEditing;\n }\n private _isEditing = false;\n\n /**\n * Emitted when user clicks configure button\n */\n @Output() ConfigureRequested = new EventEmitter<PartConfigureEvent>();\n\n /**\n * Emitted when user clicks remove button\n */\n @Output() RemoveRequested = new EventEmitter<PartRemoveEvent>();\n\n /**\n * Emitted when the part's data changes (e.g., selection in a grid)\n */\n @Output() DataChanged = new EventEmitter<PartDataChangeEvent>();\n\n /**\n * Emitted when the part requests navigation to another resource.\n * Parent component handles actual routing based on the request type.\n */\n @Output() NavigationRequested = new EventEmitter<DashboardNavRequestEvent>();\n\n /**\n * Whether the part is currently loading\n */\n public IsLoading = false;\n\n /**\n * Error message if the part failed to load\n */\n public ErrorMessage: string | null = null;\n\n constructor(protected cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n this.initialize();\n }\n\n ngOnDestroy(): void {\n this.cleanup();\n }\n\n /**\n * Initialize the part. Called in ngOnInit.\n * Override to perform async initialization like loading data.\n */\n protected initialize(): void {\n // Default implementation does nothing\n }\n\n /**\n * Cleanup resources. Called in ngOnDestroy.\n * Override to unsubscribe from observables, etc.\n */\n protected cleanup(): void {\n // Default implementation does nothing\n }\n\n /**\n * Called when the panel input changes.\n * Override to react to configuration changes.\n */\n protected onPanelChanged(newPanel: DashboardPanel | null, oldPanel: DashboardPanel | null): void {\n // Default implementation triggers reload\n if (newPanel) {\n this.loadContent();\n }\n }\n\n /**\n * Called when edit mode changes.\n * Override to adjust UI for edit mode.\n */\n protected onEditModeChanged(isEditing: boolean): void {\n this.cdr.detectChanges();\n }\n\n /**\n * Load or reload the part's content based on current configuration.\n * Override to implement actual data loading.\n */\n public abstract loadContent(): Promise<void>;\n\n /**\n * Get the typed configuration for this part.\n * Subclasses should override to return the specific config type.\n */\n public getConfig<T extends PanelConfig>(): T | null {\n return this.Panel?.config as T | null;\n }\n\n /**\n * Request configuration (edit the part settings)\n */\n public requestConfigure(): void {\n if (this.Panel && this.PartType) {\n this.ConfigureRequested.emit({\n Panel: this.Panel,\n PartType: this.PartType\n });\n }\n }\n\n /**\n * Request removal of this part\n */\n public requestRemove(): void {\n if (this.Panel) {\n this.RemoveRequested.emit({\n Panel: this.Panel\n });\n }\n }\n\n /**\n * Emit a data change event\n */\n protected emitDataChanged(data: unknown): void {\n if (this.Panel) {\n this.DataChanged.emit({\n Panel: this.Panel,\n Data: data\n });\n }\n }\n\n /**\n * Set loading state\n */\n protected setLoading(loading: boolean): void {\n this.IsLoading = loading;\n this.cdr.detectChanges();\n }\n\n /**\n * Set error state\n */\n protected setError(message: string | null): void {\n this.ErrorMessage = message;\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n\n // ========================================\n // Navigation Request Methods\n // ========================================\n\n /**\n * Request navigation to open a specific entity record\n */\n public RequestOpenEntityRecord(\n entityName: string,\n recordId: string,\n mode: 'view' | 'edit' = 'view',\n openInNewTab = false\n ): void {\n const request: OpenEntityRecordNavRequest = {\n type: 'OpenEntityRecord',\n sourcePanelId: this.Panel?.id ?? '',\n entityName,\n recordId,\n mode,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to another dashboard\n */\n public RequestOpenDashboard(\n dashboardId: string,\n categoryId?: string,\n openInNewTab = false\n ): void {\n const request: OpenDashboardNavRequest = {\n type: 'OpenDashboard',\n sourcePanelId: this.Panel?.id ?? '',\n dashboardId,\n categoryId,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to a query\n */\n public RequestOpenQuery(\n queryId: string,\n parameters?: Record<string, unknown>,\n autoExecute = true,\n openInNewTab = false\n ): void {\n const request: OpenQueryNavRequest = {\n type: 'OpenQuery',\n sourcePanelId: this.Panel?.id ?? '',\n queryId,\n parameters,\n autoExecute,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to another application\n */\n public RequestOpenApplication(\n applicationId: string,\n resourceName?: string,\n openInNewTab = false\n ): void {\n const request: OpenApplicationNavRequest = {\n type: 'OpenApplication',\n sourcePanelId: this.Panel?.id ?? '',\n applicationId,\n resourceName,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to a specific nav item within an application.\n * Supports setting URL query parameters after navigation.\n */\n public RequestOpenNavItem(\n navItemName: string,\n appName?: string,\n queryParams?: Record<string, string>,\n openInNewTab = false\n ): void {\n const request: OpenNavItemNavRequest = {\n type: 'OpenNavItem',\n sourcePanelId: this.Panel?.id ?? '',\n appName,\n navItemName,\n queryParams,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Emit a navigation request event\n */\n protected emitNavigationRequest(request: DashboardNavRequest): void {\n if (this.Panel) {\n this.NavigationRequested.emit({\n request,\n panel: this.Panel\n });\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base-dashboard-part.js","sourceRoot":"","sources":["../../../src/lib/parts/base-dashboard-part.ts"],"names":[],"mappings":"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","sourcesContent":["import { Input, Output, EventEmitter, ChangeDetectorRef, Directive, OnInit, OnDestroy } from '@angular/core';\nimport { MJDashboardPartTypeEntity } from '@memberjunction/core-entities';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport {\n PanelConfig,\n DashboardPanel,\n DashboardNavRequest,\n DashboardNavRequestEvent,\n OpenEntityRecordNavRequest,\n OpenDashboardNavRequest,\n OpenQueryNavRequest,\n OpenApplicationNavRequest,\n OpenNavItemNavRequest\n} from '../models/dashboard-types';\n\n/**\n * Event emitted when a part requests configuration\n */\nexport interface PartConfigureEvent {\n /** The panel requesting configuration */\n Panel: DashboardPanel;\n /** The part type */\n PartType: MJDashboardPartTypeEntity;\n}\n\n/**\n * Event emitted when a part requests removal\n */\nexport interface PartRemoveEvent {\n /** The panel to remove */\n Panel: DashboardPanel;\n}\n\n/**\n * Event emitted when a part's data changes\n */\nexport interface PartDataChangeEvent {\n /** The panel whose data changed */\n Panel: DashboardPanel;\n /** The new data (type depends on part type) */\n Data: unknown;\n}\n\n/**\n * Base class for dashboard part renderers.\n *\n * Each part type (View, Query, Artifact, WebURL, etc.) has a renderer component\n * that extends this class. The renderer is responsible for:\n * 1. Displaying the part's content based on its configuration\n * 2. Handling edit mode UI (configure/remove buttons)\n * 3. Emitting events for user interactions\n *\n * Subclasses are registered with @RegisterClass(BaseDashboardPart, 'PartTypeName')\n * and instantiated via ClassFactory using the DashboardPartType.DriverClass field.\n *\n * This allows new part types to be added by:\n * 1. Creating a new component that extends BaseDashboardPart\n * 2. Registering it with @RegisterClass\n * 3. Adding a DashboardPartType record with the DriverClass set to the registered name\n */\n@Directive()\nexport abstract class BaseDashboardPart extends BaseAngularComponent implements OnInit, OnDestroy {\n /**\n * The panel data including ID, title, icon, and configuration\n */\n @Input()\n set Panel(value: DashboardPanel | null) {\n const previous = this._panel;\n this._panel = value;\n if (value !== previous) {\n this.onPanelChanged(value, previous);\n }\n }\n get Panel(): DashboardPanel | null {\n return this._panel;\n }\n private _panel: DashboardPanel | null = null;\n\n /**\n * The part type metadata\n */\n @Input() PartType: MJDashboardPartTypeEntity | null = null;\n\n /**\n * Whether the dashboard is in edit mode\n */\n @Input()\n set IsEditing(value: boolean) {\n const previous = this._isEditing;\n this._isEditing = value;\n if (value !== previous) {\n this.onEditModeChanged(value);\n }\n }\n get IsEditing(): boolean {\n return this._isEditing;\n }\n private _isEditing = false;\n\n /**\n * Emitted when user clicks configure button\n */\n @Output() ConfigureRequested = new EventEmitter<PartConfigureEvent>();\n\n /**\n * Emitted when user clicks remove button\n */\n @Output() RemoveRequested = new EventEmitter<PartRemoveEvent>();\n\n /**\n * Emitted when the part's data changes (e.g., selection in a grid)\n */\n @Output() DataChanged = new EventEmitter<PartDataChangeEvent>();\n\n /**\n * Emitted when the part requests navigation to another resource.\n * Parent component handles actual routing based on the request type.\n */\n @Output() NavigationRequested = new EventEmitter<DashboardNavRequestEvent>();\n\n /**\n * Whether the part is currently loading\n */\n public IsLoading = false;\n\n /**\n * Error message if the part failed to load\n */\n public ErrorMessage: string | null = null;\n\n constructor(protected cdr: ChangeDetectorRef) {\n super();\n }\n\n ngOnInit(): void {\n this.initialize();\n }\n\n ngOnDestroy(): void {\n this.cleanup();\n }\n\n /**\n * Initialize the part. Called in ngOnInit.\n * Override to perform async initialization like loading data.\n */\n protected initialize(): void {\n // Default implementation does nothing\n }\n\n /**\n * Cleanup resources. Called in ngOnDestroy.\n * Override to unsubscribe from observables, etc.\n */\n protected cleanup(): void {\n // Default implementation does nothing\n }\n\n /**\n * Called when the panel input changes.\n * Override to react to configuration changes.\n */\n protected onPanelChanged(newPanel: DashboardPanel | null, oldPanel: DashboardPanel | null): void {\n // Default implementation triggers reload\n if (newPanel) {\n this.loadContent();\n }\n }\n\n /**\n * Called when edit mode changes.\n * Override to adjust UI for edit mode.\n */\n protected onEditModeChanged(isEditing: boolean): void {\n this.cdr.detectChanges();\n }\n\n /**\n * Load or reload the part's content based on current configuration.\n * Override to implement actual data loading.\n */\n public abstract loadContent(): Promise<void>;\n\n /**\n * Get the typed configuration for this part.\n * Subclasses should override to return the specific config type.\n */\n public getConfig<T extends PanelConfig>(): T | null {\n return this.Panel?.config as T | null;\n }\n\n /**\n * Request configuration (edit the part settings)\n */\n public requestConfigure(): void {\n if (this.Panel && this.PartType) {\n this.ConfigureRequested.emit({\n Panel: this.Panel,\n PartType: this.PartType\n });\n }\n }\n\n /**\n * Request removal of this part\n */\n public requestRemove(): void {\n if (this.Panel) {\n this.RemoveRequested.emit({\n Panel: this.Panel\n });\n }\n }\n\n /**\n * Emit a data change event\n */\n protected emitDataChanged(data: unknown): void {\n if (this.Panel) {\n this.DataChanged.emit({\n Panel: this.Panel,\n Data: data\n });\n }\n }\n\n /**\n * Set loading state\n */\n protected setLoading(loading: boolean): void {\n this.IsLoading = loading;\n this.cdr.detectChanges();\n }\n\n /**\n * Set error state\n */\n protected setError(message: string | null): void {\n this.ErrorMessage = message;\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n\n // ========================================\n // Navigation Request Methods\n // ========================================\n\n /**\n * Request navigation to open a specific entity record\n */\n public RequestOpenEntityRecord(\n entityName: string,\n recordId: string,\n mode: 'view' | 'edit' = 'view',\n openInNewTab = false\n ): void {\n const request: OpenEntityRecordNavRequest = {\n type: 'OpenEntityRecord',\n sourcePanelId: this.Panel?.id ?? '',\n entityName,\n recordId,\n mode,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to another dashboard\n */\n public RequestOpenDashboard(\n dashboardId: string,\n categoryId?: string,\n openInNewTab = false\n ): void {\n const request: OpenDashboardNavRequest = {\n type: 'OpenDashboard',\n sourcePanelId: this.Panel?.id ?? '',\n dashboardId,\n categoryId,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to a query\n */\n public RequestOpenQuery(\n queryId: string,\n parameters?: Record<string, unknown>,\n autoExecute = true,\n openInNewTab = false\n ): void {\n const request: OpenQueryNavRequest = {\n type: 'OpenQuery',\n sourcePanelId: this.Panel?.id ?? '',\n queryId,\n parameters,\n autoExecute,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to another application\n */\n public RequestOpenApplication(\n applicationId: string,\n resourceName?: string,\n openInNewTab = false\n ): void {\n const request: OpenApplicationNavRequest = {\n type: 'OpenApplication',\n sourcePanelId: this.Panel?.id ?? '',\n applicationId,\n resourceName,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Request navigation to a specific nav item within an application.\n * Supports setting URL query parameters after navigation.\n */\n public RequestOpenNavItem(\n navItemName: string,\n appName?: string,\n queryParams?: Record<string, string>,\n openInNewTab = false\n ): void {\n const request: OpenNavItemNavRequest = {\n type: 'OpenNavItem',\n sourcePanelId: this.Panel?.id ?? '',\n appName,\n navItemName,\n queryParams,\n openInNewTab\n };\n this.emitNavigationRequest(request);\n }\n\n /**\n * Emit a navigation request event\n */\n protected emitNavigationRequest(request: DashboardNavRequest): void {\n if (this.Panel) {\n this.NavigationRequested.emit({\n request,\n panel: this.Panel\n });\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-part.component.d.ts","sourceRoot":"","sources":["../../../src/lib/parts/query-part.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAa,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAElG,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"query-part.component.d.ts","sourceRoot":"","sources":["../../../src/lib/parts/query-part.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAa,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAElG,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG1D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;;AAElG;;;GAGG;AACH,qBA6Ga,kBAAmB,SAAQ,iBAAkB,YAAW,aAAa,EAAE,SAAS;IAC/D,WAAW,EAAG,oBAAoB,CAAC;IAEtD,QAAQ,UAAS;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9B,WAAW,UAAQ;IAE1B,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,gBAAgB,CAA+C;gBAE3D,GAAG,EAAE,iBAAiB;IAIlC,eAAe,IAAI,IAAI;IAMV,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAoDlC,iBAAiB,CAAC,KAAK,EAAE,yBAAyB,GAAG,IAAI;IAmBzD,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIhC,YAAY,IAAI,IAAI;IAM3B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,eAAe;cAOJ,OAAO,IAAI,IAAI;yCArHzB,kBAAkB;2CAAlB,kBAAkB;CA0H9B"}
|
|
@@ -7,7 +7,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { Component, ViewChild } from '@angular/core';
|
|
8
8
|
import { RegisterClass } from '@memberjunction/global';
|
|
9
9
|
import { BaseDashboardPart } from './base-dashboard-part';
|
|
10
|
-
import { Metadata } from '@memberjunction/core';
|
|
11
10
|
import * as i0 from "@angular/core";
|
|
12
11
|
import * as i1 from "@memberjunction/ng-shared-generic";
|
|
13
12
|
import * as i2 from "@memberjunction/ng-query-viewer";
|
|
@@ -79,10 +78,10 @@ let QueryPartComponent = class QueryPartComponent extends BaseDashboardPart {
|
|
|
79
78
|
this.setLoading(true);
|
|
80
79
|
this.stopAutoRefresh();
|
|
81
80
|
try {
|
|
82
|
-
const
|
|
81
|
+
const p = this.ProviderToUse;
|
|
83
82
|
if (queryId) {
|
|
84
83
|
// Load query by ID to verify it exists
|
|
85
|
-
this.queryEntity = await
|
|
84
|
+
this.queryEntity = await p.GetEntityObject('MJ: Queries', p.CurrentUser);
|
|
86
85
|
const loaded = await this.queryEntity.Load(queryId);
|
|
87
86
|
if (!loaded) {
|
|
88
87
|
throw new Error('Query not found');
|
|
@@ -91,7 +90,7 @@ let QueryPartComponent = class QueryPartComponent extends BaseDashboardPart {
|
|
|
91
90
|
}
|
|
92
91
|
else if (queryName) {
|
|
93
92
|
// Query by name - find the query ID from metadata
|
|
94
|
-
const queryInfo =
|
|
93
|
+
const queryInfo = p.Queries.find(q => q.Name === queryName);
|
|
95
94
|
if (queryInfo) {
|
|
96
95
|
this.queryId = queryInfo.ID;
|
|
97
96
|
}
|
|
@@ -229,5 +228,5 @@ export { QueryPartComponent };
|
|
|
229
228
|
type: ViewChild,
|
|
230
229
|
args: ['queryViewer']
|
|
231
230
|
}] }); })();
|
|
232
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryPartComponent, { className: "QueryPartComponent", filePath: "src/lib/parts/query-part.component.ts", lineNumber:
|
|
231
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(QueryPartComponent, { className: "QueryPartComponent", filePath: "src/lib/parts/query-part.component.ts", lineNumber: 121 }); })();
|
|
233
232
|
//# sourceMappingURL=query-part.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-part.component.js","sourceRoot":"","sources":["../../../src/lib/parts/query-part.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseDashboardPart } from './base-dashboard-part';\nimport { PanelConfig } from '../models/dashboard-types';\nimport { Metadata } from '@memberjunction/core';\nimport { MJQueryEntity } from '@memberjunction/core-entities';\nimport { QueryViewerComponent, QueryEntityLinkClickEvent } from '@memberjunction/ng-query-viewer';\n\n/**\n * Runtime renderer for Query dashboard parts.\n * Displays query results using mj-query-viewer with parameter controls and auto-refresh support.\n */\n@RegisterClass(BaseDashboardPart, 'QueryPanelRenderer')\n@Component({\n standalone: false,\n selector: 'mj-query-part',\n template: `\n <div class=\"query-part\" [class.loading]=\"IsLoading\" [class.error]=\"ErrorMessage\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading query...\"></mj-loading>\n </div>\n }\n \n <!-- Error state -->\n @if (ErrorMessage && !IsLoading) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n \n <!-- No query configured -->\n @if (!IsLoading && !ErrorMessage && !hasQuery) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-flask\"></i>\n <h4>No Query Selected</h4>\n <p>Click the configure button to select a query for this part.</p>\n </div>\n }\n \n <!-- Query Viewer -->\n @if (!IsLoading && !ErrorMessage && hasQuery && queryId) {\n <div class=\"query-content\">\n <mj-query-viewer\n #queryViewer\n [QueryId]=\"queryId\"\n [AutoRun]=\"true\"\n [ShowToolbar]=\"showToolbar\"\n [PersistState]=\"true\"\n [PersistParameters]=\"true\"\n (EntityLinkClick)=\"onEntityLinkClick($event)\"\n (QueryError)=\"onQueryError($event)\">\n </mj-query-viewer>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .query-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n .query-content {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n\n mj-query-viewer {\n display: block;\n width: 100%;\n height: 100%;\n }\n `]\n})\nexport class QueryPartComponent extends BaseDashboardPart implements AfterViewInit, OnDestroy {\n @ViewChild('queryViewer') queryViewer!: QueryViewerComponent;\n\n public hasQuery = false;\n public queryId: string | null = null;\n public showToolbar = true;\n\n private queryEntity: MJQueryEntity | null = null;\n private autoRefreshTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(cdr: ChangeDetectorRef) {\n super(cdr);\n }\n\n ngAfterViewInit(): void {\n if (this.Panel) {\n this.loadContent();\n }\n }\n\n public async loadContent(): Promise<void> {\n const config = this.getConfig<PanelConfig>();\n const queryId = config?.['queryId'] as string | undefined;\n const queryName = config?.['queryName'] as string | undefined;\n\n if (!queryId && !queryName) {\n this.hasQuery = false;\n this.cdr.detectChanges();\n return;\n }\n\n this.setLoading(true);\n this.stopAutoRefresh();\n\n try {\n const md = new Metadata();\n\n if (queryId) {\n // Load query by ID to verify it exists\n this.queryEntity = await md.GetEntityObject<MJQueryEntity>('MJ: Queries');\n const loaded = await this.queryEntity.Load(queryId);\n\n if (!loaded) {\n throw new Error('Query not found');\n }\n\n this.queryId = queryId;\n } else if (queryName) {\n // Query by name - find the query ID from metadata\n const queryInfo = md.Queries.find(q => q.Name === queryName);\n if (queryInfo) {\n this.queryId = queryInfo.ID;\n } else {\n throw new Error(`Query \"${queryName}\" not found`);\n }\n }\n\n this.hasQuery = true;\n this.showToolbar = (config?.['showParameterControls'] as boolean) !== false;\n\n // Set auto-refresh if configured\n const autoRefreshSeconds = (config?.['autoRefreshSeconds'] as number) || 0;\n if (autoRefreshSeconds > 0) {\n this.startAutoRefresh(autoRefreshSeconds);\n }\n\n this.setLoading(false);\n } catch (error) {\n this.setError(error instanceof Error ? error.message : 'Failed to load query');\n }\n }\n\n public onEntityLinkClick(event: QueryEntityLinkClickEvent): void {\n // Emit data change event with clicked entity info (for any listeners that need it)\n this.emitDataChanged({\n type: 'entity-link-click',\n entityName: event.entityName,\n recordId: event.recordId\n });\n\n // Request navigation to open the record\n if (event.entityName && event.recordId) {\n this.RequestOpenEntityRecord(\n event.entityName,\n event.recordId,\n 'view',\n false\n );\n }\n }\n\n public onQueryError(error: Error): void {\n console.error('[QueryPart] Query error:', error.message);\n }\n\n public refreshQuery(): void {\n if (this.queryViewer) {\n this.queryViewer.Refresh();\n }\n }\n\n private startAutoRefresh(seconds: number): void {\n this.stopAutoRefresh();\n if (seconds > 0) {\n this.autoRefreshTimer = setInterval(() => {\n this.refreshQuery();\n }, seconds * 1000);\n }\n }\n\n private stopAutoRefresh(): void {\n if (this.autoRefreshTimer) {\n clearInterval(this.autoRefreshTimer);\n this.autoRefreshTimer = null;\n }\n }\n\n protected override cleanup(): void {\n this.stopAutoRefresh();\n this.queryEntity = null;\n this.queryId = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"query-part.component.js","sourceRoot":"","sources":["../../../src/lib/parts/query-part.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseDashboardPart } from './base-dashboard-part';\nimport { PanelConfig } from '../models/dashboard-types';\nimport { MJQueryEntity } from '@memberjunction/core-entities';\nimport { QueryViewerComponent, QueryEntityLinkClickEvent } from '@memberjunction/ng-query-viewer';\n\n/**\n * Runtime renderer for Query dashboard parts.\n * Displays query results using mj-query-viewer with parameter controls and auto-refresh support.\n */\n@RegisterClass(BaseDashboardPart, 'QueryPanelRenderer')\n@Component({\n standalone: false,\n selector: 'mj-query-part',\n template: `\n <div class=\"query-part\" [class.loading]=\"IsLoading\" [class.error]=\"ErrorMessage\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading query...\"></mj-loading>\n </div>\n }\n \n <!-- Error state -->\n @if (ErrorMessage && !IsLoading) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n \n <!-- No query configured -->\n @if (!IsLoading && !ErrorMessage && !hasQuery) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-flask\"></i>\n <h4>No Query Selected</h4>\n <p>Click the configure button to select a query for this part.</p>\n </div>\n }\n \n <!-- Query Viewer -->\n @if (!IsLoading && !ErrorMessage && hasQuery && queryId) {\n <div class=\"query-content\">\n <mj-query-viewer\n #queryViewer\n [QueryId]=\"queryId\"\n [AutoRun]=\"true\"\n [ShowToolbar]=\"showToolbar\"\n [PersistState]=\"true\"\n [PersistParameters]=\"true\"\n (EntityLinkClick)=\"onEntityLinkClick($event)\"\n (QueryError)=\"onQueryError($event)\">\n </mj-query-viewer>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .query-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n .query-content {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n }\n\n mj-query-viewer {\n display: block;\n width: 100%;\n height: 100%;\n }\n `]\n})\nexport class QueryPartComponent extends BaseDashboardPart implements AfterViewInit, OnDestroy {\n @ViewChild('queryViewer') queryViewer!: QueryViewerComponent;\n\n public hasQuery = false;\n public queryId: string | null = null;\n public showToolbar = true;\n\n private queryEntity: MJQueryEntity | null = null;\n private autoRefreshTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(cdr: ChangeDetectorRef) {\n super(cdr);\n }\n\n ngAfterViewInit(): void {\n if (this.Panel) {\n this.loadContent();\n }\n }\n\n public async loadContent(): Promise<void> {\n const config = this.getConfig<PanelConfig>();\n const queryId = config?.['queryId'] as string | undefined;\n const queryName = config?.['queryName'] as string | undefined;\n\n if (!queryId && !queryName) {\n this.hasQuery = false;\n this.cdr.detectChanges();\n return;\n }\n\n this.setLoading(true);\n this.stopAutoRefresh();\n\n try {\n const p = this.ProviderToUse;\n\n if (queryId) {\n // Load query by ID to verify it exists\n this.queryEntity = await p.GetEntityObject<MJQueryEntity>('MJ: Queries', p.CurrentUser);\n const loaded = await this.queryEntity.Load(queryId);\n\n if (!loaded) {\n throw new Error('Query not found');\n }\n\n this.queryId = queryId;\n } else if (queryName) {\n // Query by name - find the query ID from metadata\n const queryInfo = p.Queries.find(q => q.Name === queryName);\n if (queryInfo) {\n this.queryId = queryInfo.ID;\n } else {\n throw new Error(`Query \"${queryName}\" not found`);\n }\n }\n\n this.hasQuery = true;\n this.showToolbar = (config?.['showParameterControls'] as boolean) !== false;\n\n // Set auto-refresh if configured\n const autoRefreshSeconds = (config?.['autoRefreshSeconds'] as number) || 0;\n if (autoRefreshSeconds > 0) {\n this.startAutoRefresh(autoRefreshSeconds);\n }\n\n this.setLoading(false);\n } catch (error) {\n this.setError(error instanceof Error ? error.message : 'Failed to load query');\n }\n }\n\n public onEntityLinkClick(event: QueryEntityLinkClickEvent): void {\n // Emit data change event with clicked entity info (for any listeners that need it)\n this.emitDataChanged({\n type: 'entity-link-click',\n entityName: event.entityName,\n recordId: event.recordId\n });\n\n // Request navigation to open the record\n if (event.entityName && event.recordId) {\n this.RequestOpenEntityRecord(\n event.entityName,\n event.recordId,\n 'view',\n false\n );\n }\n }\n\n public onQueryError(error: Error): void {\n console.error('[QueryPart] Query error:', error.message);\n }\n\n public refreshQuery(): void {\n if (this.queryViewer) {\n this.queryViewer.Refresh();\n }\n }\n\n private startAutoRefresh(seconds: number): void {\n this.stopAutoRefresh();\n if (seconds > 0) {\n this.autoRefreshTimer = setInterval(() => {\n this.refreshQuery();\n }, seconds * 1000);\n }\n }\n\n private stopAutoRefresh(): void {\n if (this.autoRefreshTimer) {\n clearInterval(this.autoRefreshTimer);\n this.autoRefreshTimer = null;\n }\n }\n\n protected override cleanup(): void {\n this.stopAutoRefresh();\n this.queryEntity = null;\n this.queryId = null;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-part.component.d.ts","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,
|
|
1
|
+
{"version":3,"file":"view-part.component.d.ts","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;;AAE5D;;;GAGG;AACH,qBAoGa,iBAAkB,SAAQ,iBAAkB,YAAW,aAAa,EAAE,SAAS;IACjF,OAAO,UAAS;IAChB,UAAU,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IACnD,UAAU,EAAE,UAAU,GAAG,IAAI,CAAQ;IACrC,QAAQ,EAAE,cAAc,CAAU;IAClC,aAAa,EAAE,aAAa,CAAW;IACvC,aAAa,EAAE,QAAQ,GAAG,UAAU,CAAY;gBAE3C,GAAG,EAAE,iBAAiB;IAIlC,eAAe,IAAI,IAAI;IAMV,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAgElC,gBAAgB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IASlD,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;cAmBlC,OAAO,IAAI,IAAI;yCA9GzB,iBAAiB;2CAAjB,iBAAiB;CAmH7B"}
|
|
@@ -7,7 +7,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { Component } from '@angular/core';
|
|
8
8
|
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
9
9
|
import { BaseDashboardPart } from './base-dashboard-part';
|
|
10
|
-
import { Metadata } from '@memberjunction/core';
|
|
11
10
|
import * as i0 from "@angular/core";
|
|
12
11
|
import * as i1 from "@memberjunction/ng-shared-generic";
|
|
13
12
|
import * as i2 from "@memberjunction/ng-entity-viewer";
|
|
@@ -79,14 +78,14 @@ let ViewPartComponent = class ViewPartComponent extends BaseDashboardPart {
|
|
|
79
78
|
}
|
|
80
79
|
this.setLoading(true);
|
|
81
80
|
try {
|
|
82
|
-
const
|
|
81
|
+
const p = this.ProviderToUse;
|
|
83
82
|
// Set view mode from config
|
|
84
83
|
this.viewMode = config?.['displayMode'] || 'grid';
|
|
85
84
|
this.mapRenderMode = config?.['mapRenderMode'] || 'point';
|
|
86
85
|
this.selectionMode = config?.['selectionMode'] === 'multiple' ? 'multiple' : 'single';
|
|
87
86
|
if (viewId) {
|
|
88
87
|
// Load saved view by ID
|
|
89
|
-
const viewEntity = await
|
|
88
|
+
const viewEntity = await p.GetEntityObject('MJ: User Views', p.CurrentUser);
|
|
90
89
|
const loaded = await viewEntity.Load(viewId);
|
|
91
90
|
this.viewEntity = viewEntity; // IMPORTANT - only set this.viewEntity AFTER we have it loaded in the above
|
|
92
91
|
if (!loaded) {
|
|
@@ -98,11 +97,11 @@ let ViewPartComponent = class ViewPartComponent extends BaseDashboardPart {
|
|
|
98
97
|
this.entityInfo = viewEntity.ViewEntityInfo;
|
|
99
98
|
}
|
|
100
99
|
else if (viewEntity.Entity) {
|
|
101
|
-
this.entityInfo =
|
|
100
|
+
this.entityInfo = p.EntityByName(viewEntity.Entity) || null;
|
|
102
101
|
}
|
|
103
102
|
else if (viewEntity.EntityID) {
|
|
104
103
|
// Last resort: look up by EntityID
|
|
105
|
-
this.entityInfo =
|
|
104
|
+
this.entityInfo = p.Entities.find(e => UUIDsEqual(e.ID, viewEntity.EntityID)) || null;
|
|
106
105
|
}
|
|
107
106
|
if (!this.entityInfo) {
|
|
108
107
|
throw new Error(`Could not determine entity for view "${this.viewEntity.Name}" (ID: ${viewId})`);
|
|
@@ -110,7 +109,7 @@ let ViewPartComponent = class ViewPartComponent extends BaseDashboardPart {
|
|
|
110
109
|
}
|
|
111
110
|
else if (entityName) {
|
|
112
111
|
// Create dynamic view for entity (no saved view)
|
|
113
|
-
this.entityInfo =
|
|
112
|
+
this.entityInfo = p.EntityByName(entityName) || null;
|
|
114
113
|
if (!this.entityInfo) {
|
|
115
114
|
throw new Error(`Entity "${entityName}" not found`);
|
|
116
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-part.component.js","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, AfterViewInit, OnDestroy } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { BaseDashboardPart } from './base-dashboard-part';\nimport { PanelConfig } from '../models/dashboard-types';\nimport { Metadata, EntityInfo } from '@memberjunction/core';\nimport { MJUserViewEntityExtended } from '@memberjunction/core-entities';\nimport { EntityViewMode, RecordSelectedEvent, RecordOpenedEvent } from '@memberjunction/ng-entity-viewer';\nimport { MapRenderMode } from '@memberjunction/ng-map-view';\n\n/**\n * Runtime renderer for View dashboard parts.\n * Displays entity data using mj-entity-viewer with grid, cards, or timeline layout.\n */\n@RegisterClass(BaseDashboardPart, 'ViewPanelRenderer')\n@Component({\n standalone: false,\n selector: 'mj-view-part',\n template: `\n <div class=\"view-part\" [class.loading]=\"IsLoading\" [class.error]=\"ErrorMessage\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading view...\"></mj-loading>\n </div>\n }\n \n <!-- Error state -->\n @if (ErrorMessage && !IsLoading) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n \n <!-- No view configured -->\n @if (!IsLoading && !ErrorMessage && !hasView) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-table\"></i>\n <h4>No View Selected</h4>\n <p>Click the configure button to select a view for this part.</p>\n </div>\n }\n \n <!-- Entity Viewer -->\n @if (!IsLoading && !ErrorMessage && hasView && entityInfo) {\n <mj-entity-viewer\n [entity]=\"entityInfo\"\n [viewEntity]=\"viewEntity\"\n [(viewMode)]=\"viewMode\"\n [mapRenderMode]=\"mapRenderMode\"\n [gridSelectionMode]=\"selectionMode\"\n [showGridToolbar]=\"false\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\">\n </mj-entity-viewer>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .view-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n `]\n})\nexport class ViewPartComponent extends BaseDashboardPart implements AfterViewInit, OnDestroy {\n public hasView = false;\n public viewEntity: MJUserViewEntityExtended | null = null;\n public entityInfo: EntityInfo | null = null;\n public viewMode: EntityViewMode = 'grid';\n public mapRenderMode: MapRenderMode = 'point';\n public selectionMode: 'single' | 'multiple' = 'single';\n\n constructor(cdr: ChangeDetectorRef) {\n super(cdr);\n }\n\n ngAfterViewInit(): void {\n if (this.Panel) {\n this.loadContent();\n }\n }\n\n public async loadContent(): Promise<void> {\n const config = this.getConfig<PanelConfig>();\n const viewId = config?.['viewId'] as string | undefined;\n const entityName = config?.['entityName'] as string | undefined;\n\n if (!viewId && !entityName) {\n this.hasView = false;\n this.cdr.detectChanges();\n return;\n }\n\n this.setLoading(true);\n\n try {\n const md = new Metadata();\n\n // Set view mode from config\n this.viewMode = (config?.['displayMode'] as EntityViewMode) || 'grid';\n this.mapRenderMode = (config?.['mapRenderMode'] as MapRenderMode) || 'point';\n this.selectionMode = config?.['selectionMode'] === 'multiple' ? 'multiple' : 'single';\n\n if (viewId) {\n // Load saved view by ID\n const viewEntity = await md.GetEntityObject<MJUserViewEntityExtended>('MJ: User Views');\n const loaded = await viewEntity.Load(viewId);\n this.viewEntity = viewEntity; // IMPORTANT - only set this.viewEntity AFTER we have it loaded in the above\n\n if (!loaded) {\n throw new Error('View not found');\n }\n\n // Get entity info from the view - prefer ViewEntityInfo if available (set by MJUserViewEntityExtended.Load)\n // Fall back to looking up by Entity name (virtual field) or EntityID\n if (viewEntity.ViewEntityInfo) {\n this.entityInfo = viewEntity.ViewEntityInfo;\n } else if (viewEntity.Entity) {\n this.entityInfo = md.Entities.find(e => e.Name === viewEntity!.Entity) || null;\n } else if (viewEntity.EntityID) {\n // Last resort: look up by EntityID\n this.entityInfo = md.Entities.find(e => UUIDsEqual(e.ID, viewEntity!.EntityID)) || null;\n }\n\n if (!this.entityInfo) {\n throw new Error(`Could not determine entity for view \"${this.viewEntity.Name}\" (ID: ${viewId})`);\n }\n } else if (entityName) {\n // Create dynamic view for entity (no saved view)\n this.entityInfo = md.Entities.find(e => e.Name === entityName) || null;\n\n if (!this.entityInfo) {\n throw new Error(`Entity \"${entityName}\" not found`);\n }\n\n // No viewEntity means the entity-viewer will show all records\n this.viewEntity = null;\n }\n\n this.hasView = true;\n this.setLoading(false);\n } catch (error) {\n this.setError(error instanceof Error ? error.message : 'Failed to load view');\n }\n }\n\n public onRecordSelected(event: RecordSelectedEvent): void {\n // Emit data change event with selected record\n this.emitDataChanged({\n type: 'record-selected',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n }\n\n public onRecordOpened(event: RecordOpenedEvent): void {\n // Emit data change event for record open (for any listeners that need it)\n this.emitDataChanged({\n type: 'record-opened',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n\n // Request navigation to open the record\n if (event.entity && event.compositeKey) {\n this.RequestOpenEntityRecord(\n event.entity.Name,\n event.compositeKey.ToURLSegment(),\n 'view',\n false\n );\n }\n }\n\n protected override cleanup(): void {\n // EntityViewer handles its own cleanup\n this.viewEntity = null;\n this.entityInfo = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"view-part.component.js","sourceRoot":"","sources":["../../../src/lib/parts/view-part.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, AfterViewInit, OnDestroy } from '@angular/core';\nimport { RegisterClass, UUIDsEqual } from '@memberjunction/global';\nimport { BaseDashboardPart } from './base-dashboard-part';\nimport { PanelConfig } from '../models/dashboard-types';\nimport { EntityInfo } from '@memberjunction/core';\nimport { MJUserViewEntityExtended } from '@memberjunction/core-entities';\nimport { EntityViewMode, RecordSelectedEvent, RecordOpenedEvent } from '@memberjunction/ng-entity-viewer';\nimport { MapRenderMode } from '@memberjunction/ng-map-view';\n\n/**\n * Runtime renderer for View dashboard parts.\n * Displays entity data using mj-entity-viewer with grid, cards, or timeline layout.\n */\n@RegisterClass(BaseDashboardPart, 'ViewPanelRenderer')\n@Component({\n standalone: false,\n selector: 'mj-view-part',\n template: `\n <div class=\"view-part\" [class.loading]=\"IsLoading\" [class.error]=\"ErrorMessage\">\n <!-- Loading state -->\n @if (IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading view...\"></mj-loading>\n </div>\n }\n \n <!-- Error state -->\n @if (ErrorMessage && !IsLoading) {\n <div class=\"error-state\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ ErrorMessage }}</span>\n </div>\n }\n \n <!-- No view configured -->\n @if (!IsLoading && !ErrorMessage && !hasView) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-table\"></i>\n <h4>No View Selected</h4>\n <p>Click the configure button to select a view for this part.</p>\n </div>\n }\n \n <!-- Entity Viewer -->\n @if (!IsLoading && !ErrorMessage && hasView && entityInfo) {\n <mj-entity-viewer\n [entity]=\"entityInfo\"\n [viewEntity]=\"viewEntity\"\n [(viewMode)]=\"viewMode\"\n [mapRenderMode]=\"mapRenderMode\"\n [gridSelectionMode]=\"selectionMode\"\n [showGridToolbar]=\"false\"\n (recordSelected)=\"onRecordSelected($event)\"\n (recordOpened)=\"onRecordOpened($event)\">\n </mj-entity-viewer>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .view-part {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n }\n\n .loading-state,\n .error-state,\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--mj-text-secondary);\n text-align: center;\n padding: 24px;\n }\n\n .error-state i,\n .empty-state i {\n font-size: 48px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n }\n\n .error-state i {\n color: var(--mj-status-error);\n }\n\n .empty-state h4 {\n margin: 0 0 8px 0;\n color: var(--mj-text-primary);\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n }\n\n mj-entity-viewer {\n flex: 1;\n min-height: 0;\n }\n `]\n})\nexport class ViewPartComponent extends BaseDashboardPart implements AfterViewInit, OnDestroy {\n public hasView = false;\n public viewEntity: MJUserViewEntityExtended | null = null;\n public entityInfo: EntityInfo | null = null;\n public viewMode: EntityViewMode = 'grid';\n public mapRenderMode: MapRenderMode = 'point';\n public selectionMode: 'single' | 'multiple' = 'single';\n\n constructor(cdr: ChangeDetectorRef) {\n super(cdr);\n }\n\n ngAfterViewInit(): void {\n if (this.Panel) {\n this.loadContent();\n }\n }\n\n public async loadContent(): Promise<void> {\n const config = this.getConfig<PanelConfig>();\n const viewId = config?.['viewId'] as string | undefined;\n const entityName = config?.['entityName'] as string | undefined;\n\n if (!viewId && !entityName) {\n this.hasView = false;\n this.cdr.detectChanges();\n return;\n }\n\n this.setLoading(true);\n\n try {\n const p = this.ProviderToUse;\n\n // Set view mode from config\n this.viewMode = (config?.['displayMode'] as EntityViewMode) || 'grid';\n this.mapRenderMode = (config?.['mapRenderMode'] as MapRenderMode) || 'point';\n this.selectionMode = config?.['selectionMode'] === 'multiple' ? 'multiple' : 'single';\n\n if (viewId) {\n // Load saved view by ID\n const viewEntity = await p.GetEntityObject<MJUserViewEntityExtended>('MJ: User Views', p.CurrentUser);\n const loaded = await viewEntity.Load(viewId);\n this.viewEntity = viewEntity; // IMPORTANT - only set this.viewEntity AFTER we have it loaded in the above\n\n if (!loaded) {\n throw new Error('View not found');\n }\n\n // Get entity info from the view - prefer ViewEntityInfo if available (set by MJUserViewEntityExtended.Load)\n // Fall back to looking up by Entity name (virtual field) or EntityID\n if (viewEntity.ViewEntityInfo) {\n this.entityInfo = viewEntity.ViewEntityInfo;\n } else if (viewEntity.Entity) {\n this.entityInfo = p.EntityByName(viewEntity!.Entity) || null;\n } else if (viewEntity.EntityID) {\n // Last resort: look up by EntityID\n this.entityInfo = p.Entities.find(e => UUIDsEqual(e.ID, viewEntity!.EntityID)) || null;\n }\n\n if (!this.entityInfo) {\n throw new Error(`Could not determine entity for view \"${this.viewEntity.Name}\" (ID: ${viewId})`);\n }\n } else if (entityName) {\n // Create dynamic view for entity (no saved view)\n this.entityInfo = p.EntityByName(entityName) || null;\n\n if (!this.entityInfo) {\n throw new Error(`Entity \"${entityName}\" not found`);\n }\n\n // No viewEntity means the entity-viewer will show all records\n this.viewEntity = null;\n }\n\n this.hasView = true;\n this.setLoading(false);\n } catch (error) {\n this.setError(error instanceof Error ? error.message : 'Failed to load view');\n }\n }\n\n public onRecordSelected(event: RecordSelectedEvent): void {\n // Emit data change event with selected record\n this.emitDataChanged({\n type: 'record-selected',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n }\n\n public onRecordOpened(event: RecordOpenedEvent): void {\n // Emit data change event for record open (for any listeners that need it)\n this.emitDataChanged({\n type: 'record-opened',\n record: event.record,\n primaryKey: event.record?.PrimaryKey\n });\n\n // Request navigation to open the record\n if (event.entity && event.compositeKey) {\n this.RequestOpenEntityRecord(\n event.entity.Name,\n event.compositeKey.ToURLSegment(),\n 'view',\n false\n );\n }\n }\n\n protected override cleanup(): void {\n // EntityViewer handles its own cleanup\n this.viewEntity = null;\n this.entityInfo = null;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-dashboard-viewer",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.32.0",
|
|
4
4
|
"description": "MemberJunction: Angular components for metadata-driven dashboards with Golden Layout panels, supporting views, queries, artifacts, and custom content",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -37,15 +37,16 @@
|
|
|
37
37
|
"golden-layout": "^2.6.0"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@memberjunction/core": "5.
|
|
41
|
-
"@memberjunction/core-entities": "5.
|
|
42
|
-
"@memberjunction/global": "5.
|
|
43
|
-
"@memberjunction/ng-artifacts": "5.
|
|
44
|
-
"@memberjunction/ng-
|
|
45
|
-
"@memberjunction/ng-
|
|
46
|
-
"@memberjunction/ng-
|
|
47
|
-
"@memberjunction/ng-
|
|
48
|
-
"@memberjunction/ng-
|
|
40
|
+
"@memberjunction/core": "5.32.0",
|
|
41
|
+
"@memberjunction/core-entities": "5.32.0",
|
|
42
|
+
"@memberjunction/global": "5.32.0",
|
|
43
|
+
"@memberjunction/ng-artifacts": "5.32.0",
|
|
44
|
+
"@memberjunction/ng-base-types": "5.32.0",
|
|
45
|
+
"@memberjunction/ng-entity-viewer": "5.32.0",
|
|
46
|
+
"@memberjunction/ng-map-view": "5.32.0",
|
|
47
|
+
"@memberjunction/ng-query-viewer": "5.32.0",
|
|
48
|
+
"@memberjunction/ng-shared-generic": "5.32.0",
|
|
49
|
+
"@memberjunction/ng-trees": "5.32.0",
|
|
49
50
|
"rxjs": "^7.8.2",
|
|
50
51
|
"tslib": "^2.8.1"
|
|
51
52
|
},
|