@memberjunction/ng-explorer-core 2.121.0 → 2.122.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +0 -1
  2. package/dist/app-routing.module.d.ts +6 -5
  3. package/dist/app-routing.module.d.ts.map +1 -1
  4. package/dist/app-routing.module.js +266 -132
  5. package/dist/app-routing.module.js.map +1 -1
  6. package/dist/lib/app-view/application-view.component.js +10 -10
  7. package/dist/lib/app-view/application-view.component.js.map +1 -1
  8. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +11 -12
  9. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
  10. package/dist/lib/data-browser-component/data-browser.component.js +8 -8
  11. package/dist/lib/data-browser-component/data-browser.component.js.map +1 -1
  12. package/dist/lib/generic-browse-list/generic-browse-list.component.js +10 -7
  13. package/dist/lib/generic-browse-list/generic-browse-list.component.js.map +1 -1
  14. package/dist/lib/generic-browser-list/generic-browser-list.component.js +14 -11
  15. package/dist/lib/generic-browser-list/generic-browser-list.component.js.map +1 -1
  16. package/dist/lib/list-view/list-view.component.js +24 -21
  17. package/dist/lib/list-view/list-view.component.js.map +1 -1
  18. package/dist/lib/navigation/navigation.component.d.ts +0 -1
  19. package/dist/lib/navigation/navigation.component.d.ts.map +1 -1
  20. package/dist/lib/navigation/navigation.component.js +11 -19
  21. package/dist/lib/navigation/navigation.component.js.map +1 -1
  22. package/dist/lib/resource-browser/resource-browser.component.js +14 -11
  23. package/dist/lib/resource-browser/resource-browser.component.js.map +1 -1
  24. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +20 -0
  25. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -0
  26. package/dist/lib/resource-wrappers/artifact-resource.component.js +92 -0
  27. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -0
  28. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +119 -0
  29. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -0
  30. package/dist/lib/resource-wrappers/chat-collections-resource.component.js +500 -0
  31. package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -0
  32. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +87 -0
  33. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -0
  34. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +345 -0
  35. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -0
  36. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +67 -0
  37. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -0
  38. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +244 -0
  39. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -0
  40. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +46 -3
  41. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  42. package/dist/lib/resource-wrappers/dashboard-resource.component.js +298 -21
  43. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  44. package/dist/lib/resource-wrappers/list-detail-resource.component.js +1 -1
  45. package/dist/lib/resource-wrappers/list-detail-resource.component.js.map +1 -1
  46. package/dist/lib/resource-wrappers/query-resource.component.js +1 -1
  47. package/dist/lib/resource-wrappers/query-resource.component.js.map +1 -1
  48. package/dist/lib/resource-wrappers/record-resource.component.d.ts.map +1 -1
  49. package/dist/lib/resource-wrappers/record-resource.component.js +22 -5
  50. package/dist/lib/resource-wrappers/record-resource.component.js.map +1 -1
  51. package/dist/lib/resource-wrappers/report-resource.component.js +1 -1
  52. package/dist/lib/resource-wrappers/report-resource.component.js.map +1 -1
  53. package/dist/lib/resource-wrappers/resource-wrappers-loader.d.ts.map +1 -1
  54. package/dist/lib/resource-wrappers/resource-wrappers-loader.js +15 -0
  55. package/dist/lib/resource-wrappers/resource-wrappers-loader.js.map +1 -1
  56. package/dist/lib/resource-wrappers/search-results-resource.component.js +1 -1
  57. package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
  58. package/dist/lib/resource-wrappers/view-resource.component.js +1 -1
  59. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  60. package/dist/lib/shell/components/header/app-nav.component.d.ts +45 -0
  61. package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -0
  62. package/dist/lib/shell/components/header/app-nav.component.js +127 -0
  63. package/dist/lib/shell/components/header/app-nav.component.js.map +1 -0
  64. package/dist/lib/shell/components/header/app-switcher.component.d.ts +53 -0
  65. package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -0
  66. package/dist/lib/shell/components/header/app-switcher.component.js +190 -0
  67. package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -0
  68. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +83 -0
  69. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -0
  70. package/dist/lib/shell/components/tabs/component-cache-manager.js +175 -0
  71. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -0
  72. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +138 -0
  73. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -0
  74. package/dist/lib/shell/components/tabs/tab-container.component.js +920 -0
  75. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -0
  76. package/dist/lib/shell/services/settings-dialog.service.d.ts +28 -0
  77. package/dist/lib/shell/services/settings-dialog.service.d.ts.map +1 -0
  78. package/dist/lib/shell/services/settings-dialog.service.js +67 -0
  79. package/dist/lib/shell/services/settings-dialog.service.js.map +1 -0
  80. package/dist/lib/shell/shell.component.d.ts +166 -0
  81. package/dist/lib/shell/shell.component.d.ts.map +1 -0
  82. package/dist/lib/shell/shell.component.js +1173 -0
  83. package/dist/lib/shell/shell.component.js.map +1 -0
  84. package/dist/lib/shell/shell.module.d.ts +14 -0
  85. package/dist/lib/shell/shell.module.d.ts.map +1 -0
  86. package/dist/lib/shell/shell.module.js +42 -0
  87. package/dist/lib/shell/shell.module.js.map +1 -0
  88. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +17 -13
  89. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
  90. package/dist/lib/single-dashboard/single-dashboard.component.d.ts +2 -1
  91. package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
  92. package/dist/lib/single-dashboard/single-dashboard.component.js +6 -1
  93. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  94. package/dist/lib/single-entity/single-entity.component.js +21 -17
  95. package/dist/lib/single-entity/single-entity.component.js.map +1 -1
  96. package/dist/lib/single-list-detail/single-list-detail.component.js +36 -30
  97. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  98. package/dist/lib/single-record/single-record.component.d.ts +1 -0
  99. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  100. package/dist/lib/single-record/single-record.component.js +16 -9
  101. package/dist/lib/single-record/single-record.component.js.map +1 -1
  102. package/dist/lib/single-report/single-report.component.d.ts +1 -7
  103. package/dist/lib/single-report/single-report.component.d.ts.map +1 -1
  104. package/dist/lib/single-report/single-report.component.js +16 -37
  105. package/dist/lib/single-report/single-report.component.js.map +1 -1
  106. package/dist/lib/single-view/single-view.component.d.ts +1 -2
  107. package/dist/lib/single-view/single-view.component.d.ts.map +1 -1
  108. package/dist/lib/single-view/single-view.component.js +35 -43
  109. package/dist/lib/single-view/single-view.component.js.map +1 -1
  110. package/dist/lib/style-guide-test/style-guide-test.component.js +20 -13
  111. package/dist/lib/style-guide-test/style-guide-test.component.js.map +1 -1
  112. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts +1 -1
  113. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.d.ts.map +1 -1
  114. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js +8 -11
  115. package/dist/lib/tabbed-dashboard/tabbed-dashboard.component.js.map +1 -1
  116. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  117. package/dist/lib/user-notifications/user-notifications.component.js +0 -5
  118. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  119. package/dist/module.d.ts +50 -46
  120. package/dist/module.d.ts.map +1 -1
  121. package/dist/module.js +23 -11
  122. package/dist/module.js.map +1 -1
  123. package/dist/public-api.d.ts +4 -0
  124. package/dist/public-api.d.ts.map +1 -1
  125. package/dist/public-api.js +5 -0
  126. package/dist/public-api.js.map +1 -1
  127. package/package.json +44 -35
@@ -0,0 +1,244 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
8
+ import { NavigationEnd } from '@angular/router';
9
+ import { Metadata } from '@memberjunction/core';
10
+ import { RegisterClass } from '@memberjunction/global';
11
+ import { BaseResourceComponent } from '@memberjunction/ng-shared';
12
+ import { EnvironmentEntityExtended } from '@memberjunction/core-entities';
13
+ import { Subject, takeUntil, filter } from 'rxjs';
14
+ import * as i0 from "@angular/core";
15
+ import * as i1 from "@angular/router";
16
+ import * as i2 from "@angular/common";
17
+ import * as i3 from "@memberjunction/ng-conversations";
18
+ const _c0 = ["tasksView"];
19
+ function ChatTasksResource_mj_tasks_full_view_1_Template(rf, ctx) { if (rf & 1) {
20
+ const _r1 = i0.ɵɵgetCurrentView();
21
+ i0.ɵɵelementStart(0, "mj-tasks-full-view", 3, 0);
22
+ i0.ɵɵlistener("taskSelected", function ChatTasksResource_mj_tasks_full_view_1_Template_mj_tasks_full_view_taskSelected_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onTaskSelected($event)); });
23
+ i0.ɵɵelementEnd();
24
+ } if (rf & 2) {
25
+ const ctx_r1 = i0.ɵɵnextContext();
26
+ i0.ɵɵproperty("environmentId", ctx_r1.environmentId)("currentUser", ctx_r1.currentUser)("baseFilter", "1=1")("activeTaskId", ctx_r1.activeTaskId);
27
+ } }
28
+ export function LoadChatTasksResource() {
29
+ const test = new ChatTasksResource(null); // Force inclusion in production builds (tree shaking workaround)
30
+ }
31
+ /**
32
+ * Chat Tasks Resource - displays the tasks full view for tab-based display
33
+ * Extends BaseResourceComponent to work with the resource type system
34
+ * Shows all tasks associated with conversations and artifacts
35
+ * Supports URL deep-linking via taskId query parameter
36
+ */
37
+ let ChatTasksResource = class ChatTasksResource extends BaseResourceComponent {
38
+ router;
39
+ tasksView;
40
+ currentUser = null;
41
+ activeTaskId;
42
+ skipUrlUpdate = true;
43
+ destroy$ = new Subject();
44
+ lastNavigatedUrl = ''; // Track URL to avoid reacting to our own navigation
45
+ constructor(router) {
46
+ super();
47
+ this.router = router;
48
+ }
49
+ ngOnInit() {
50
+ const md = new Metadata();
51
+ this.currentUser = md.CurrentUser;
52
+ // Parse URL first and apply state
53
+ const urlState = this.parseUrlState();
54
+ if (urlState?.taskId) {
55
+ this.activeTaskId = urlState.taskId;
56
+ }
57
+ else {
58
+ // Check for navigation params from config
59
+ this.applyNavigationParams();
60
+ }
61
+ // Subscribe to router NavigationEnd events for back/forward button support
62
+ this.router.events
63
+ .pipe(filter((event) => event instanceof NavigationEnd), takeUntil(this.destroy$))
64
+ .subscribe(event => {
65
+ const currentUrl = event.urlAfterRedirects || event.url;
66
+ if (currentUrl !== this.lastNavigatedUrl) {
67
+ this.onExternalNavigation(currentUrl);
68
+ }
69
+ });
70
+ // Enable URL updates after initialization
71
+ this.skipUrlUpdate = false;
72
+ // Update URL to reflect current state
73
+ this.updateUrl();
74
+ // Notify load complete after user is set
75
+ setTimeout(() => {
76
+ this.NotifyLoadComplete();
77
+ }, 100);
78
+ }
79
+ ngOnDestroy() {
80
+ this.destroy$.next();
81
+ this.destroy$.complete();
82
+ }
83
+ /**
84
+ * Parse URL query string for task state.
85
+ * Query params: taskId
86
+ */
87
+ parseUrlState() {
88
+ const url = this.router.url;
89
+ const queryIndex = url.indexOf('?');
90
+ if (queryIndex === -1)
91
+ return null;
92
+ const queryString = url.substring(queryIndex + 1);
93
+ const params = new URLSearchParams(queryString);
94
+ const taskId = params.get('taskId');
95
+ if (!taskId)
96
+ return null;
97
+ return { taskId };
98
+ }
99
+ /**
100
+ * Apply navigation parameters from configuration.
101
+ */
102
+ applyNavigationParams() {
103
+ const config = this.Data?.Configuration;
104
+ if (!config)
105
+ return;
106
+ if (config.taskId) {
107
+ this.activeTaskId = config.taskId;
108
+ }
109
+ }
110
+ /**
111
+ * Handle task selection from the tasks view.
112
+ */
113
+ onTaskSelected(taskId) {
114
+ this.activeTaskId = taskId || undefined;
115
+ if (!this.skipUrlUpdate) {
116
+ this.updateUrl();
117
+ }
118
+ }
119
+ /**
120
+ * Update URL query string to reflect current state.
121
+ * Uses Angular Router for proper browser history integration.
122
+ */
123
+ updateUrl() {
124
+ const params = new URLSearchParams();
125
+ if (this.activeTaskId) {
126
+ params.set('taskId', this.activeTaskId);
127
+ }
128
+ // Get current path without query string
129
+ const currentUrl = this.router.url;
130
+ const currentPath = currentUrl.split('?')[0];
131
+ const queryString = params.toString();
132
+ const newUrl = queryString ? `${currentPath}?${queryString}` : currentPath;
133
+ // Track this URL so we don't react to our own navigation
134
+ this.lastNavigatedUrl = newUrl;
135
+ // Use Angular Router for proper browser history integration
136
+ this.router.navigateByUrl(newUrl, { replaceUrl: false });
137
+ }
138
+ /**
139
+ * Handle external navigation (back/forward buttons).
140
+ * Parses the URL and applies the state without triggering a new navigation.
141
+ */
142
+ onExternalNavigation(url) {
143
+ // Check if this URL is for our component (contains our base path)
144
+ const currentPath = this.router.url.split('?')[0];
145
+ const newPath = url.split('?')[0];
146
+ // Only handle if we're still on the same base path (same component instance)
147
+ if (currentPath !== newPath) {
148
+ return; // Different route entirely, shell will handle it
149
+ }
150
+ // Parse the new URL state
151
+ const urlState = this.parseUrlFromString(url);
152
+ // Apply the state without triggering URL updates
153
+ this.skipUrlUpdate = true;
154
+ if (urlState?.taskId) {
155
+ this.activeTaskId = urlState.taskId;
156
+ // Notify the tasks view component if it exists
157
+ if (this.tasksView) {
158
+ this.tasksView.activeTaskId = urlState.taskId;
159
+ }
160
+ }
161
+ else {
162
+ // No params means clear state
163
+ this.activeTaskId = undefined;
164
+ if (this.tasksView) {
165
+ this.tasksView.activeTaskId = undefined;
166
+ }
167
+ }
168
+ this.skipUrlUpdate = false;
169
+ // Update the tracked URL
170
+ this.lastNavigatedUrl = url;
171
+ }
172
+ /**
173
+ * Parse URL state from a URL string (used for external navigation).
174
+ */
175
+ parseUrlFromString(url) {
176
+ const queryIndex = url.indexOf('?');
177
+ if (queryIndex === -1)
178
+ return null;
179
+ const queryString = url.substring(queryIndex + 1);
180
+ const params = new URLSearchParams(queryString);
181
+ const taskId = params.get('taskId');
182
+ if (!taskId)
183
+ return null;
184
+ return { taskId };
185
+ }
186
+ /**
187
+ * Get the environment ID from configuration or use default
188
+ */
189
+ get environmentId() {
190
+ return this.Data?.Configuration?.environmentId || EnvironmentEntityExtended.DefaultEnvironmentID;
191
+ }
192
+ /**
193
+ * Get the display name for chat tasks
194
+ */
195
+ async GetResourceDisplayName(data) {
196
+ return 'Tasks';
197
+ }
198
+ /**
199
+ * Get the icon class for chat tasks
200
+ */
201
+ async GetResourceIconClass(data) {
202
+ return 'fa-solid fa-tasks';
203
+ }
204
+ static ɵfac = function ChatTasksResource_Factory(t) { return new (t || ChatTasksResource)(i0.ɵɵdirectiveInject(i1.Router)); };
205
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatTasksResource, selectors: [["mj-chat-tasks-resource"]], viewQuery: function ChatTasksResource_Query(rf, ctx) { if (rf & 1) {
206
+ i0.ɵɵviewQuery(_c0, 5);
207
+ } if (rf & 2) {
208
+ let _t;
209
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.tasksView = _t.first);
210
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [["tasksView", ""], [1, "chat-tasks-container"], ["style", "height: 100%;", 3, "environmentId", "currentUser", "baseFilter", "activeTaskId", "taskSelected", 4, "ngIf"], [2, "height", "100%", 3, "taskSelected", "environmentId", "currentUser", "baseFilter", "activeTaskId"]], template: function ChatTasksResource_Template(rf, ctx) { if (rf & 1) {
211
+ i0.ɵɵelementStart(0, "div", 1);
212
+ i0.ɵɵtemplate(1, ChatTasksResource_mj_tasks_full_view_1_Template, 2, 4, "mj-tasks-full-view", 2);
213
+ i0.ɵɵelementEnd();
214
+ } if (rf & 2) {
215
+ i0.ɵɵadvance();
216
+ i0.ɵɵproperty("ngIf", ctx.currentUser);
217
+ } }, dependencies: [i2.NgIf, i3.TasksFullViewComponent], styles: ["\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .chat-tasks-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n flex: 1;\n overflow: hidden;\n }\n "], encapsulation: 2 });
218
+ };
219
+ ChatTasksResource = __decorate([
220
+ RegisterClass(BaseResourceComponent, 'ChatTasksResource')
221
+ ], ChatTasksResource);
222
+ export { ChatTasksResource };
223
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ChatTasksResource, [{
224
+ type: Component,
225
+ args: [{ selector: 'mj-chat-tasks-resource', template: `
226
+ <div class="chat-tasks-container">
227
+ <mj-tasks-full-view
228
+ #tasksView
229
+ *ngIf="currentUser"
230
+ [environmentId]="environmentId"
231
+ [currentUser]="currentUser"
232
+ [baseFilter]="'1=1'"
233
+ [activeTaskId]="activeTaskId"
234
+ (taskSelected)="onTaskSelected($any($event))"
235
+ style="height: 100%;">
236
+ </mj-tasks-full-view>
237
+ </div>
238
+ `, encapsulation: ViewEncapsulation.None, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .chat-tasks-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n flex: 1;\n overflow: hidden;\n }\n "] }]
239
+ }], () => [{ type: i1.Router }], { tasksView: [{
240
+ type: ViewChild,
241
+ args: ['tasksView']
242
+ }] }); })();
243
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ChatTasksResource, { className: "ChatTasksResource", filePath: "src/lib/resource-wrappers/chat-tasks-resource.component.ts", lineNumber: 57 }); })();
244
+ //# sourceMappingURL=chat-tasks-resource.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-tasks-resource.component.js","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/chat-tasks-resource.component.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,54 @@
1
- import { BaseResourceComponent } from '@memberjunction/ng-shared';
2
- import { ResourceData } from '@memberjunction/core-entities';
1
+ import { ViewContainerRef, ElementRef } from '@angular/core';
2
+ import { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';
3
+ import { ResourceData, DashboardUserStateEntity } from '@memberjunction/core-entities';
3
4
  import * as i0 from "@angular/core";
4
5
  export declare function LoadDashboardResource(): void;
6
+ /**
7
+ * Dashboard Resource Wrapper - displays a single dashboard in a tab
8
+ * Extends BaseResourceComponent to work with the resource type system
9
+ * Dynamically routes between code-based and config-based dashboards based on dashboard type
10
+ */
5
11
  export declare class DashboardResource extends BaseResourceComponent {
12
+ private viewContainer;
13
+ private navigationService;
14
+ private componentRef;
15
+ private dataLoaded;
16
+ containerElement: ElementRef<HTMLDivElement>;
17
+ constructor(viewContainer: ViewContainerRef, navigationService: NavigationService);
18
+ set Data(value: ResourceData);
19
+ get Data(): ResourceData;
20
+ ngOnDestroy(): void;
21
+ /**
22
+ * Load the appropriate dashboard component based on dashboard type
23
+ * Routes between code-based dashboards (registered classes) and config-based dashboards
24
+ */
25
+ private loadDashboard;
26
+ /**
27
+ * Load the Data Explorer dashboard component with optional entity filter and context info
28
+ * @param entityFilter Optional filter to constrain which entities are shown
29
+ * @param contextName Optional name to display in the header (e.g., "CRM", "Association Demo")
30
+ * @param contextIcon Optional Font Awesome icon class for the header
31
+ */
32
+ private loadDataExplorer;
33
+ /**
34
+ * Load a code-based dashboard by looking up the registered class
35
+ */
36
+ private loadCodeBasedDashboard;
37
+ protected loadDashboardUserState(dashboardId: string): Promise<DashboardUserStateEntity>;
38
+ /**
39
+ * Load a config-based dashboard using the generic SingleDashboardComponent
40
+ */
41
+ private loadConfigBasedDashboard;
42
+ /**
43
+ * Get the display name for a dashboard resource
44
+ * Loads the actual dashboard name from the database if available
45
+ */
6
46
  GetResourceDisplayName(data: ResourceData): Promise<string>;
47
+ /**
48
+ * Get the icon class for dashboard resources
49
+ */
7
50
  GetResourceIconClass(data: ResourceData): Promise<string>;
8
51
  static ɵfac: i0.ɵɵFactoryDeclaration<DashboardResource, never>;
9
- static ɵcmp: i0.ɵɵComponentDeclaration<DashboardResource, "mj-single-dashboard-resource", never, {}, {}, never, never, false, never>;
52
+ static ɵcmp: i0.ɵɵComponentDeclaration<DashboardResource, "mj-dashboard-resource", never, {}, {}, never, never, false, never>;
10
53
  }
11
54
  //# sourceMappingURL=dashboard-resource.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-resource.component.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-resource.component.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;;AAG7D,wBAAgB,qBAAqB,SAEpC;AAED,qBAKa,iBAAkB,SAAQ,qBAAqB;IACzC,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAGpE,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCAJtD,iBAAiB;2CAAjB,iBAAiB;CAO7B"}
1
+ {"version":3,"file":"dashboard-resource.component.d.ts","sourceRoot":"","sources":["../../../src/lib/resource-wrappers/dashboard-resource.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,gBAAgB,EAA2B,UAAU,EAAE,MAAM,eAAe,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAkC,MAAM,2BAA2B,CAAC;AACrH,OAAO,EAAE,YAAY,EAAoC,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;;AAMzH,wBAAgB,qBAAqB,SACpC;AAED;;;;GAIG;AACH,qBAsBa,iBAAkB,SAAQ,qBAAqB;IAMpD,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,iBAAiB;IAN7B,OAAO,CAAC,YAAY,CAAsC;IAC1D,OAAO,CAAC,UAAU,CAAS;IACe,gBAAgB,EAAG,UAAU,CAAC,cAAc,CAAC,CAAC;gBAG5E,aAAa,EAAE,gBAAgB,EAC/B,iBAAiB,EAAE,iBAAiB;IAKhD,IAAa,IAAI,CAAC,KAAK,EAAE,YAAY,EAMpC;IAGD,IAAa,IAAI,IAAI,YAAY,CAEhC;IAED,WAAW,IAAI,IAAI;IAMnB;;;OAGG;YACW,aAAa;IAiD3B;;;;;OAKG;YACW,gBAAgB;IAwD9B;;OAEG;YACW,sBAAsB;cAyEpB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAsB9F;;OAEG;YACW,wBAAwB;IA0CtC;;;OAGG;IACY,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB1E;;OAEG;IACG,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCA3TtD,iBAAiB;2CAAjB,iBAAiB;CA8T7B"}
@@ -4,40 +4,317 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component } from '@angular/core';
8
- import { BaseResourceComponent } from '@memberjunction/ng-shared';
9
- import { RegisterClass } from '@memberjunction/global';
7
+ import { Component, ViewChild } from '@angular/core';
8
+ import { BaseResourceComponent, BaseDashboard } from '@memberjunction/ng-shared';
9
+ import { ResourceData, DashboardEngine } from '@memberjunction/core-entities';
10
+ import { RegisterClass, MJGlobal, SafeJSONParse } from '@memberjunction/global';
11
+ import { Metadata, CompositeKey, RunView, LogError } from '@memberjunction/core';
12
+ import { SingleDashboardComponent } from '../single-dashboard/single-dashboard.component';
13
+ import { DataExplorerDashboardComponent } from '@memberjunction/ng-dashboards';
10
14
  import * as i0 from "@angular/core";
11
- import * as i1 from "../single-dashboard/single-dashboard.component";
15
+ import * as i1 from "@memberjunction/ng-shared";
16
+ const _c0 = ["container"];
12
17
  export function LoadDashboardResource() {
13
- const test = new DashboardResource(); // this looks really dumb. Thing is, in production builds, tree shaking causes the class below to not be included in the bundle. This is a hack to force it to be included.
14
18
  }
19
+ /**
20
+ * Dashboard Resource Wrapper - displays a single dashboard in a tab
21
+ * Extends BaseResourceComponent to work with the resource type system
22
+ * Dynamically routes between code-based and config-based dashboards based on dashboard type
23
+ */
15
24
  let DashboardResource = class DashboardResource extends BaseResourceComponent {
25
+ viewContainer;
26
+ navigationService;
27
+ componentRef = null;
28
+ dataLoaded = false;
29
+ containerElement;
30
+ constructor(viewContainer, navigationService) {
31
+ super();
32
+ this.viewContainer = viewContainer;
33
+ this.navigationService = navigationService;
34
+ }
35
+ set Data(value) {
36
+ super.Data = value;
37
+ if (!this.dataLoaded) {
38
+ this.dataLoaded = true;
39
+ this.loadDashboard();
40
+ }
41
+ }
42
+ // Need to override the getter too in TS otherwise the override to the setter alone above would break things
43
+ get Data() {
44
+ return super.Data;
45
+ }
46
+ ngOnDestroy() {
47
+ if (this.componentRef) {
48
+ this.componentRef.destroy();
49
+ }
50
+ }
51
+ /**
52
+ * Load the appropriate dashboard component based on dashboard type
53
+ * Routes between code-based dashboards (registered classes) and config-based dashboards
54
+ */
55
+ async loadDashboard() {
56
+ const data = this.Data;
57
+ console.log('[DashboardResource] loadDashboard called with:', data);
58
+ if (!data?.ResourceRecordID) {
59
+ console.log('[DashboardResource] No ResourceRecordID, exiting');
60
+ this.NotifyLoadStarted();
61
+ this.NotifyLoadComplete();
62
+ return;
63
+ }
64
+ this.NotifyLoadStarted();
65
+ try {
66
+ // Check if this is a special dashboard type (not a database record)
67
+ const config = data.Configuration || {};
68
+ console.log('[DashboardResource] Config:', config, 'ResourceRecordID:', data.ResourceRecordID);
69
+ if (config['dashboardType'] === 'DataExplorer' || data.ResourceRecordID === 'DataExplorer') {
70
+ console.log('[DashboardResource] Loading DataExplorer with filter:', config['entityFilter']);
71
+ // Special case: Data Explorer dashboard with optional entity filter
72
+ await this.loadDataExplorer(config['entityFilter'], config['appName'], config['appIcon']);
73
+ return;
74
+ }
75
+ await DashboardEngine.Instance.Config(false); // make sure it is configured, if already configured does nothing
76
+ const dashboard = DashboardEngine.Instance.Dashboards.find(d => d.ID === data.ResourceRecordID);
77
+ if (!dashboard) {
78
+ throw new Error(`Dashboard with ID ${data.ResourceRecordID} not found.`);
79
+ }
80
+ // Determine which dashboard component to load based on dashboard type
81
+ if (dashboard.Type === 'Code') {
82
+ // CODE-BASED DASHBOARD: Use registered class via DriverClass
83
+ await this.loadCodeBasedDashboard(dashboard);
84
+ }
85
+ else {
86
+ // CONFIG-BASED DASHBOARD: Use the generic metadata-driven renderer
87
+ await this.loadConfigBasedDashboard(dashboard);
88
+ }
89
+ }
90
+ catch (error) {
91
+ console.error('Error loading dashboard:', error);
92
+ this.NotifyLoadComplete();
93
+ }
94
+ }
95
+ /**
96
+ * Load the Data Explorer dashboard component with optional entity filter and context info
97
+ * @param entityFilter Optional filter to constrain which entities are shown
98
+ * @param contextName Optional name to display in the header (e.g., "CRM", "Association Demo")
99
+ * @param contextIcon Optional Font Awesome icon class for the header
100
+ */
101
+ async loadDataExplorer(entityFilter, contextName, contextIcon) {
102
+ try {
103
+ // Create the Data Explorer component directly (it's already registered)
104
+ this.containerElement.nativeElement.innerHTML = '';
105
+ const componentRef = this.viewContainer.createComponent(DataExplorerDashboardComponent);
106
+ this.componentRef = componentRef;
107
+ const instance = componentRef.instance;
108
+ // Set the entity filter - ngOnInit will use this when it runs
109
+ if (entityFilter) {
110
+ instance.entityFilter = entityFilter;
111
+ }
112
+ // Set context name and icon for customized header display
113
+ if (contextName) {
114
+ instance.contextName = contextName;
115
+ }
116
+ if (contextIcon) {
117
+ instance.contextIcon = contextIcon;
118
+ }
119
+ // Manually append the component's native element inside the div
120
+ const nativeElement = componentRef.hostView.rootNodes[0];
121
+ nativeElement.style.width = '100%';
122
+ nativeElement.style.height = '100%';
123
+ this.containerElement.nativeElement.appendChild(nativeElement);
124
+ // Handle open entity record events
125
+ instance.OpenEntityRecord.subscribe((eventData) => {
126
+ if (eventData && eventData.EntityName && eventData.RecordPKey) {
127
+ this.navigationService.OpenEntityRecord(eventData.EntityName, eventData.RecordPKey);
128
+ }
129
+ });
130
+ // Initialize dashboard (no database config needed for DataExplorer)
131
+ const config = {
132
+ dashboard: null, // No database record
133
+ userState: {}
134
+ };
135
+ instance.Config = config;
136
+ instance.Refresh();
137
+ // Trigger change detection to ensure the component updates
138
+ componentRef.changeDetectorRef.detectChanges();
139
+ this.NotifyLoadComplete();
140
+ }
141
+ catch (error) {
142
+ console.error('Error loading Data Explorer:', error);
143
+ this.NotifyLoadComplete();
144
+ }
145
+ }
146
+ /**
147
+ * Load a code-based dashboard by looking up the registered class
148
+ */
149
+ async loadCodeBasedDashboard(dashboard) {
150
+ try {
151
+ if (!dashboard.DriverClass) {
152
+ throw new Error(`Dashboard '${dashboard.Name}' is marked as Code type but has no DriverClass specified`);
153
+ }
154
+ // Look up the registered class using the DriverClass name
155
+ const classReg = MJGlobal.Instance.ClassFactory.GetRegistration(BaseDashboard, dashboard.DriverClass);
156
+ if (!classReg?.SubClass) {
157
+ throw new Error(`Dashboard class '${dashboard.DriverClass}' is not registered. Please check the class registration.`);
158
+ }
159
+ // Create the component instance
160
+ this.containerElement.nativeElement.innerHTML = '';
161
+ this.componentRef = this.viewContainer.createComponent(classReg.SubClass);
162
+ const instance = this.componentRef.instance;
163
+ // Manually append the component's native element inside the div
164
+ const nativeElement = this.componentRef.hostView.rootNodes[0];
165
+ nativeElement.style.width = '100%';
166
+ nativeElement.style.height = '100%';
167
+ this.containerElement.nativeElement.appendChild(nativeElement);
168
+ // Initialize with dashboard data
169
+ const baseData = this.Data;
170
+ const userStateEntity = await this.loadDashboardUserState(dashboard.ID);
171
+ const config = {
172
+ dashboard,
173
+ userState: userStateEntity.UserState ? SafeJSONParse(userStateEntity.UserState) : {}
174
+ };
175
+ // handle open entity record events in MJ Explorer with routing
176
+ instance.OpenEntityRecord.subscribe((data) => {
177
+ console.log('DashboardResource OpenEntityRecord event received:', data);
178
+ // check to see if the data has entityname/pkey
179
+ if (data && data.EntityName && data.RecordPKey) {
180
+ console.log('DashboardResource calling NavigationService.OpenEntityRecord:', data.EntityName, data.RecordPKey);
181
+ // Use NavigationService to open entity record in new tab
182
+ this.navigationService.OpenEntityRecord(data.EntityName, data.RecordPKey);
183
+ }
184
+ else {
185
+ console.log('DashboardResource - invalid data, missing EntityName or RecordPKey:', data);
186
+ }
187
+ });
188
+ instance.UserStateChanged.subscribe(async (userState) => {
189
+ if (!userState) {
190
+ // if the user state is null, we need to remove it from the user state
191
+ userState = {};
192
+ }
193
+ // save the user state to the dashboard user state entity
194
+ userStateEntity.UserState = JSON.stringify(userState);
195
+ if (!await userStateEntity.Save()) {
196
+ LogError('Error saving user state', null, userStateEntity.LatestResult.Error);
197
+ }
198
+ });
199
+ instance.Config = config;
200
+ instance.Refresh();
201
+ this.NotifyLoadComplete();
202
+ }
203
+ catch (error) {
204
+ console.error('Error loading code-based dashboard:', error);
205
+ this.NotifyLoadComplete();
206
+ }
207
+ }
208
+ async loadDashboardUserState(dashboardId) {
209
+ // handle user state changes for the dashboard
210
+ const rv = new RunView();
211
+ const md = new Metadata();
212
+ const stateResult = await rv.RunView({
213
+ EntityName: 'MJ: Dashboard User States',
214
+ ExtraFilter: `DashboardID='${dashboardId}' AND UserID='${md.CurrentUser.ID}'`,
215
+ ResultType: 'entity_object',
216
+ });
217
+ let stateObject;
218
+ if (stateResult && stateResult.Success && stateResult.Results.length > 0) {
219
+ stateObject = stateResult.Results[0];
220
+ }
221
+ else {
222
+ stateObject = await md.GetEntityObject('MJ: Dashboard User States');
223
+ stateObject.DashboardID = dashboardId;
224
+ stateObject.UserID = md.CurrentUser.ID;
225
+ // don't save becuase we don't care about the state until something changes
226
+ }
227
+ return stateObject;
228
+ }
229
+ /**
230
+ * Load a config-based dashboard using the generic SingleDashboardComponent
231
+ */
232
+ async loadConfigBasedDashboard(dashboard) {
233
+ try {
234
+ this.containerElement.nativeElement.innerHTML = '';
235
+ this.componentRef = this.viewContainer.createComponent(SingleDashboardComponent);
236
+ const instance = this.componentRef.instance;
237
+ // Manually append the component's native element inside the div
238
+ const nativeElement = this.componentRef.hostView.rootNodes[0];
239
+ nativeElement.style.width = '100%';
240
+ nativeElement.style.height = '100%';
241
+ this.containerElement.nativeElement.appendChild(nativeElement);
242
+ // Initialize with dashboard data
243
+ const baseData = this.Data;
244
+ const resourceData = new ResourceData({
245
+ ResourceRecordID: baseData.ResourceRecordID,
246
+ Configuration: baseData.Configuration || {}
247
+ });
248
+ instance.ResourceData = resourceData;
249
+ // Wire up events if they exist
250
+ if (instance.loadComplete) {
251
+ instance.loadComplete.subscribe(() => {
252
+ this.NotifyLoadComplete();
253
+ });
254
+ }
255
+ else {
256
+ // Fallback if event emitter not available
257
+ setTimeout(() => this.NotifyLoadComplete(), 100);
258
+ }
259
+ if (instance.dashboardSaved) {
260
+ instance.dashboardSaved.subscribe((entity) => {
261
+ this.ResourceRecordSaved(entity);
262
+ });
263
+ }
264
+ }
265
+ catch (error) {
266
+ console.error('Error loading config-based dashboard:', error);
267
+ this.NotifyLoadComplete();
268
+ }
269
+ }
270
+ /**
271
+ * Get the display name for a dashboard resource
272
+ * Loads the actual dashboard name from the database if available
273
+ */
16
274
  async GetResourceDisplayName(data) {
17
- return data.Name ? data.Name : 'Dashboard ID: ' + data.ResourceRecordID;
275
+ try {
276
+ // Try to load dashboard metadata if we have the record ID
277
+ if (data.ResourceRecordID && data.ResourceRecordID.length > 0) {
278
+ const md = new Metadata();
279
+ const compositeKey = new CompositeKey([{ FieldName: 'ID', Value: data.ResourceRecordID }]);
280
+ const name = await md.GetEntityRecordName('Dashboards', compositeKey);
281
+ if (name) {
282
+ return name;
283
+ }
284
+ }
285
+ }
286
+ catch (error) {
287
+ // Silently fail and use fallback
288
+ }
289
+ // Fallback: use provided name or generic label
290
+ return data.Name || 'Dashboard';
18
291
  }
292
+ /**
293
+ * Get the icon class for dashboard resources
294
+ */
19
295
  async GetResourceIconClass(data) {
20
- return '';
296
+ return 'fa-solid fa-table-columns';
21
297
  }
22
- static ɵfac = /*@__PURE__*/ (() => { let ɵDashboardResource_BaseFactory; return function DashboardResource_Factory(t) { return (ɵDashboardResource_BaseFactory || (ɵDashboardResource_BaseFactory = i0.ɵɵgetInheritedFactory(DashboardResource)))(t || DashboardResource); }; })();
23
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DashboardResource, selectors: [["mj-single-dashboard-resource"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 1, vars: 1, consts: [[3, "dashboardSaved", "loadComplete", "loadStarted", "ResourceData"]], template: function DashboardResource_Template(rf, ctx) { if (rf & 1) {
24
- i0.ɵɵelementStart(0, "mj-single-dashboard", 0);
25
- i0.ɵɵlistener("dashboardSaved", function DashboardResource_Template_mj_single_dashboard_dashboardSaved_0_listener($event) { return ctx.ResourceRecordSaved($event); })("loadComplete", function DashboardResource_Template_mj_single_dashboard_loadComplete_0_listener() { return ctx.NotifyLoadComplete(); })("loadStarted", function DashboardResource_Template_mj_single_dashboard_loadStarted_0_listener() { return ctx.NotifyLoadStarted(); });
26
- i0.ɵɵelementEnd();
298
+ static ɵfac = function DashboardResource_Factory(t) { return new (t || DashboardResource)(i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i1.NavigationService)); };
299
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DashboardResource, selectors: [["mj-dashboard-resource"]], viewQuery: function DashboardResource_Query(rf, ctx) { if (rf & 1) {
300
+ i0.ɵɵviewQuery(_c0, 7);
27
301
  } if (rf & 2) {
28
- i0.ɵɵproperty("ResourceData", ctx.Data);
29
- } }, dependencies: [i1.SingleDashboardComponent], encapsulation: 2 });
302
+ let _t;
303
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.containerElement = _t.first);
304
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 0, consts: [["container", ""], [1, "dashboard-resource-container"]], template: function DashboardResource_Template(rf, ctx) { if (rf & 1) {
305
+ i0.ɵɵelement(0, "div", 1, 0);
306
+ } }, styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .dashboard-resource-container[_ngcontent-%COMP%] {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n overflow: auto;\n }"] });
30
307
  };
31
308
  DashboardResource = __decorate([
32
- RegisterClass(BaseResourceComponent, 'Dashboards')
309
+ RegisterClass(BaseResourceComponent, 'DashboardResource')
33
310
  ], DashboardResource);
34
311
  export { DashboardResource };
35
312
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DashboardResource, [{
36
313
  type: Component,
37
- args: [{
38
- selector: 'mj-single-dashboard-resource',
39
- template: `<mj-single-dashboard [ResourceData]="Data" (dashboardSaved)="ResourceRecordSaved($event)" (loadComplete)="NotifyLoadComplete()" (loadStarted)="NotifyLoadStarted()" ></mj-single-dashboard>`
40
- }]
41
- }], null, null); })();
42
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DashboardResource, { className: "DashboardResource", filePath: "src/lib/resource-wrappers/dashboard-resource.component.ts", lineNumber: 15 }); })();
314
+ args: [{ selector: 'mj-dashboard-resource', template: `<div #container class="dashboard-resource-container"></div>`, styles: ["\n :host {\n display: block;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n }\n .dashboard-resource-container {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n overflow: auto;\n }\n "] }]
315
+ }], () => [{ type: i0.ViewContainerRef }, { type: i1.NavigationService }], { containerElement: [{
316
+ type: ViewChild,
317
+ args: ['container', { static: true }]
318
+ }] }); })();
319
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DashboardResource, { className: "DashboardResource", filePath: "src/lib/resource-wrappers/dashboard-resource.component.ts", lineNumber: 39 }); })();
43
320
  //# sourceMappingURL=dashboard-resource.component.js.map