@memberjunction/ng-shared 5.46.0 → 5.48.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.
@@ -41,7 +41,7 @@ export declare abstract class BaseDashboard extends BaseResourceComponent implem
41
41
  /**
42
42
  * This method will result in the dashboard being reloaded.
43
43
  */
44
- Refresh(): void;
44
+ Refresh(): Promise<void>;
45
45
  private _visible;
46
46
  /**
47
47
  * This method can be used by a container to let the dashboard know that it is being opened/closed. Base class just sets a flag.
@@ -1 +1 @@
1
- {"version":3,"file":"base-dashboard.d.ts","sourceRoot":"","sources":["../../src/lib/base-dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAS,SAAS,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAElE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,yBAAyB,CAAC;IACrC,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAED;;GAEG;AACH,8BACsB,aAAc,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAC5F;;OAEG;IACH,IAAa,MAAM,CAAC,KAAK,EAAE,eAAe,EAEzC;IAED,IAAI,MAAM,IAAI,eAAe,GAAG,IAAI,CAEnC;IAED;;OAEG;IACO,KAAK,sBAA6B;IAE5C;;OAEG;IACO,gBAAgB,oBAA2B;IAErD;;OAEG;IACO,WAAW,oBAA2B;IAEhD;;OAEG;IACO,gBAAgB;oBAAiC,MAAM;oBAAc,YAAY;OAAK;IAEhG,SAAS,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAQ;IAE3C,QAAQ;IAOd,WAAW,IAAI,IAAI;IAInB;;OAEG;IACI,OAAO,IAAI,IAAI;IAItB,OAAO,CAAC,QAAQ,CAAkB;IAClC;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIzC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,IAAI,IAAI;IAExC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI;IAEnC;;;;OAIG;IACG,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCA3E3C,aAAa;2CAAb,aAAa;CA8ElC"}
1
+ {"version":3,"file":"base-dashboard.d.ts","sourceRoot":"","sources":["../../src/lib/base-dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAS,SAAS,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAElE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,yBAAyB,CAAC;IACrC,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAED;;GAEG;AACH,8BACsB,aAAc,SAAQ,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAC5F;;OAEG;IACH,IAAa,MAAM,CAAC,KAAK,EAAE,eAAe,EAEzC;IAED,IAAI,MAAM,IAAI,eAAe,GAAG,IAAI,CAEnC;IAED;;OAEG;IACO,KAAK,sBAA6B;IAE5C;;OAEG;IACO,gBAAgB,oBAA2B;IAErD;;OAEG;IACO,WAAW,oBAA2B;IAEhD;;OAEG;IACO,gBAAgB;oBAAiC,MAAM;oBAAc,YAAY;OAAK;IAEhG,SAAS,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAQ;IAE3C,QAAQ;IAOd,WAAW,IAAI,IAAI;IAInB;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrC,OAAO,CAAC,QAAQ,CAAkB;IAClC;;OAEG;IACI,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIzC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,IAAI,IAAI;IAExC;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI;IAEnC;;;;OAIG;IACG,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCA5E3C,aAAa;2CAAb,aAAa;CA+ElC"}
@@ -43,8 +43,9 @@ export class BaseDashboard extends BaseResourceComponent {
43
43
  /**
44
44
  * This method will result in the dashboard being reloaded.
45
45
  */
46
- Refresh() {
47
- this.loadData();
46
+ async Refresh() {
47
+ await this.loadData();
48
+ this.NotifyLoadComplete();
48
49
  }
49
50
  _visible = false;
50
51
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"base-dashboard.js","sourceRoot":"","sources":["../../src/lib/base-dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAqB,MAAM,EAAE,MAAM,eAAe,CAAC;AAG1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAOlE;;GAEG;AAEH,MAAM,OAAgB,aAAc,SAAQ,qBAAqB;IAC/D;;OAEG;IACH,IAAa,MAAM,CAAC,KAAsB;QACxC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACO,KAAK,GAAG,IAAI,YAAY,EAAS,CAAC;IAE5C;;OAEG;IACO,gBAAgB,GAAG,IAAI,YAAY,EAAO,CAAC;IAErD;;OAEG;IACO,WAAW,GAAG,IAAI,YAAY,EAAO,CAAC;IAEhD;;OAEG;IACO,gBAAgB,GAAG,IAAI,YAAY,EAAkD,CAAC;IAEtF,OAAO,GAA2B,IAAI,CAAC;IAEjD,KAAK,CAAC,QAAQ;QACZ,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,KAAK,CAAC,WAAW,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACI,OAAO;QACZ,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAEO,QAAQ,GAAY,KAAK,CAAC;IAClC;;OAEG;IACI,UAAU,CAAC,OAAgB;QAChC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAYD;;;;OAIG;IACH,KAAK,CAAC,oBAAoB,CAAC,IAAkB;QAC3C,OAAO,EAAE,CAAC;IACZ,CAAC;iOA7EmB,aAAa,yBAAb,aAAa;6DAAb,aAAa;;iFAAb,aAAa;cADlC,SAAS;;kBAKP,KAAK;;kBAWL,MAAM;;kBAKN,MAAM;;kBAKN,MAAM;;kBAKN,MAAM","sourcesContent":["import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';\nimport { CompositeKey } from '@memberjunction/core';\nimport { MJDashboardEntityExtended, ResourceData } from '@memberjunction/core-entities';\nimport { BaseResourceComponent } from './base-resource-component';\n\nexport interface DashboardConfig {\n dashboard: MJDashboardEntityExtended;\n userState?: any;\n}\n\n/**\n * Make the base class a directive so we can use Angular functionality and sub-classes can be @Component \n */\n@Directive()\nexport abstract class BaseDashboard extends BaseResourceComponent implements OnInit, OnDestroy {\n /**\n * Set or change the dashboard configuration. Changing this property will NOT cause the dashboard to reload. Call Refresh() to do that.\n */\n @Input() set Config(value: DashboardConfig) {\n this._config = value;\n }\n\n get Config(): DashboardConfig | null {\n return this._config;\n }\n\n /**\n * Subclasses can emit anytime an error occurs. \n */\n @Output() Error = new EventEmitter<Error>();\n\n /**\n * Subclasses should emit this event anytime their internal state changes in a way that they'd like to persist.\n */\n @Output() UserStateChanged = new EventEmitter<any>();\n\n /**\n * Subclasses can emit this event anytime they want to communicate with the container to let it know that something has happened of significance.\n */\n @Output() Interaction = new EventEmitter<any>();\n\n /**\n * Subclasses can emit this event anytime they want to open a record within a particular entity. The container should handle this event and open the record.\n */\n @Output() OpenEntityRecord = new EventEmitter<{EntityName: string, RecordPKey: CompositeKey}>();\n\n protected _config: DashboardConfig | null = null;\n\n async ngOnInit() {\n super.ngOnInit();\n this.initDashboard();\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n }\n\n /**\n * This method will result in the dashboard being reloaded.\n */\n public Refresh(): void {\n this.loadData();\n }\n\n private _visible: boolean = false;\n /**\n * This method can be used by a container to let the dashboard know that it is being opened/closed. Base class just sets a flag.\n */\n public SetVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n /**\n * Subclasses can override this method to perform any initialization they need. This method only runs once when the dashboard is created.\n */\n protected abstract initDashboard(): void;\n\n /**\n * Subclasses should override this method to load their data. This method is called when the dashboard is created and when Refresh() is called.\n */\n protected abstract loadData(): void;\n\n /**\n * Sub-classes can override this to provide a custom icon class\n * @param data \n * @returns \n */\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return \"\";\n }\n} "]}
1
+ {"version":3,"file":"base-dashboard.js","sourceRoot":"","sources":["../../src/lib/base-dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAqB,MAAM,EAAE,MAAM,eAAe,CAAC;AAG1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAOlE;;GAEG;AAEH,MAAM,OAAgB,aAAc,SAAQ,qBAAqB;IAC/D;;OAEG;IACH,IAAa,MAAM,CAAC,KAAsB;QACxC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;OAEG;IACO,KAAK,GAAG,IAAI,YAAY,EAAS,CAAC;IAE5C;;OAEG;IACO,gBAAgB,GAAG,IAAI,YAAY,EAAO,CAAC;IAErD;;OAEG;IACO,WAAW,GAAG,IAAI,YAAY,EAAO,CAAC;IAEhD;;OAEG;IACO,gBAAgB,GAAG,IAAI,YAAY,EAAkD,CAAC;IAEtF,OAAO,GAA2B,IAAI,CAAC;IAEjD,KAAK,CAAC,QAAQ;QACZ,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAED,WAAW;QACT,KAAK,CAAC,WAAW,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,OAAO;QAClB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAEO,QAAQ,GAAY,KAAK,CAAC;IAClC;;OAEG;IACI,UAAU,CAAC,OAAgB;QAChC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAYD;;;;OAIG;IACH,KAAK,CAAC,oBAAoB,CAAC,IAAkB;QAC3C,OAAO,EAAE,CAAC;IACZ,CAAC;iOA9EmB,aAAa,yBAAb,aAAa;6DAAb,aAAa;;iFAAb,aAAa;cADlC,SAAS;;kBAKP,KAAK;;kBAWL,MAAM;;kBAKN,MAAM;;kBAKN,MAAM;;kBAKN,MAAM","sourcesContent":["import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';\nimport { CompositeKey } from '@memberjunction/core';\nimport { MJDashboardEntityExtended, ResourceData } from '@memberjunction/core-entities';\nimport { BaseResourceComponent } from './base-resource-component';\n\nexport interface DashboardConfig {\n dashboard: MJDashboardEntityExtended;\n userState?: any;\n}\n\n/**\n * Make the base class a directive so we can use Angular functionality and sub-classes can be @Component \n */\n@Directive()\nexport abstract class BaseDashboard extends BaseResourceComponent implements OnInit, OnDestroy {\n /**\n * Set or change the dashboard configuration. Changing this property will NOT cause the dashboard to reload. Call Refresh() to do that.\n */\n @Input() set Config(value: DashboardConfig) {\n this._config = value;\n }\n\n get Config(): DashboardConfig | null {\n return this._config;\n }\n\n /**\n * Subclasses can emit anytime an error occurs. \n */\n @Output() Error = new EventEmitter<Error>();\n\n /**\n * Subclasses should emit this event anytime their internal state changes in a way that they'd like to persist.\n */\n @Output() UserStateChanged = new EventEmitter<any>();\n\n /**\n * Subclasses can emit this event anytime they want to communicate with the container to let it know that something has happened of significance.\n */\n @Output() Interaction = new EventEmitter<any>();\n\n /**\n * Subclasses can emit this event anytime they want to open a record within a particular entity. The container should handle this event and open the record.\n */\n @Output() OpenEntityRecord = new EventEmitter<{EntityName: string, RecordPKey: CompositeKey}>();\n\n protected _config: DashboardConfig | null = null;\n\n async ngOnInit() {\n super.ngOnInit();\n this.initDashboard();\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void {\n super.ngOnDestroy();\n }\n\n /**\n * This method will result in the dashboard being reloaded.\n */\n public async Refresh(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n private _visible: boolean = false;\n /**\n * This method can be used by a container to let the dashboard know that it is being opened/closed. Base class just sets a flag.\n */\n public SetVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n /**\n * Subclasses can override this method to perform any initialization they need. This method only runs once when the dashboard is created.\n */\n protected abstract initDashboard(): void;\n\n /**\n * Subclasses should override this method to load their data. This method is called when the dashboard is created and when Refresh() is called.\n */\n protected abstract loadData(): void;\n\n /**\n * Sub-classes can override this to provide a custom icon class\n * @param data \n * @returns \n */\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return \"\";\n }\n} "]}
@@ -13,6 +13,7 @@ export declare abstract class BaseResourceComponent extends BaseNavigationCompon
13
13
  private _lastDeliveredParamsKey;
14
14
  protected destroy$: Subject<void>;
15
15
  protected navigationService: NavigationService;
16
+ private changeDetectorRef;
16
17
  /**
17
18
  * Tab ID for query param notification scoping. Set by resource wrappers
18
19
  * that render child dashboards, so the child knows which tab it belongs to.
@@ -99,6 +100,24 @@ export declare abstract class BaseResourceComponent extends BaseNavigationCompon
99
100
  private getQueryParamUpdateGuard;
100
101
  protected NotifyLoadComplete(): void;
101
102
  protected NotifyLoadStarted(): void;
103
+ /**
104
+ * Marks this component's view (and its ancestors) as needing change detection and schedules
105
+ * a tick — the reliable way for a resource component to re-render after updating state from
106
+ * async work (RunView/RunQuery continuations, timers, websocket pushes, RxJS subscriptions).
107
+ *
108
+ * WHY THIS EXISTS: the Explorer shell hosts resource components dynamically — `createComponent()`
109
+ * + `ApplicationRef.attachView()` — because tab content mounts into Golden Layout / cached DOM
110
+ * containers, not into an Angular template. Since Angular 18's change-detection scheduler
111
+ * rework (Explorer is on Angular 21), `ApplicationRef.tick()` only refreshes attached views
112
+ * that are FLAGGED dirty; a root-level attached view whose component mutates plain fields from
113
+ * an async continuation is never flagged, so the view silently never re-renders — even though
114
+ * the component uses default (non-OnPush) change detection (issue #3106).
115
+ *
116
+ * The framework calls this automatically from NotifyLoadStarted() / NotifyLoadComplete(), so
117
+ * the standard load lifecycle re-renders without any subclass action. Call it yourself after
118
+ * any LATER async state change that must reach the DOM outside those signals.
119
+ */
120
+ protected RefreshView(): void;
102
121
  /**
103
122
  * Call this to notify the tab system that the resource's display name has changed.
104
123
  * The tab container will update the tab title and browser title accordingly.
@@ -1 +1 @@
1
- {"version":3,"file":"base-resource-component.d.ts","sourceRoot":"","sources":["../../src/lib/base-resource-component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-resource-component.d.ts","sourceRoot":"","sources":["../../src/lib/base-resource-component.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Directive, Input, inject } from "@angular/core";
1
+ import { ChangeDetectorRef, Directive, Input, inject } from "@angular/core";
2
2
  import { Subject } from "rxjs";
3
3
  import { filter, takeUntil } from "rxjs/operators";
4
4
  import { BaseNavigationComponent } from "./base-navigation-component";
@@ -13,6 +13,7 @@ export class BaseResourceComponent extends BaseNavigationComponent {
13
13
  _lastDeliveredParamsKey = null;
14
14
  destroy$ = new Subject();
15
15
  navigationService = inject(NavigationService);
16
+ changeDetectorRef = inject(ChangeDetectorRef);
16
17
  /**
17
18
  * Tab ID for query param notification scoping. Set by resource wrappers
18
19
  * that render child dashboards, so the child knows which tab it belongs to.
@@ -182,14 +183,19 @@ export class BaseResourceComponent extends BaseNavigationComponent {
182
183
  }
183
184
  this._lastDeliveredParamsKey = key;
184
185
  const source = isInitial ? 'deeplink' : 'popstate';
185
- // try/finally ensures the suppression flag is always cleared, even if
186
- // OnQueryParamsChanged throws.
186
+ // try/finally ensures the suppression flag is always cleared, and the view is always
187
+ // refreshed, even if OnQueryParamsChanged throws.
187
188
  this._suppressQueryParamSync = true;
188
189
  try {
189
190
  this.OnQueryParamsChanged(params, source);
190
191
  }
191
192
  finally {
192
193
  this._suppressQueryParamSync = false;
194
+ // Query params arrive via RxJS (workspace stream / popstate), not via a template event —
195
+ // state a subclass changed in OnQueryParamsChanged needs an explicit re-render request
196
+ // for dynamically-attached views (see RefreshView). Inside `finally` so a subclass
197
+ // override that throws still renders whatever partial state it applied before throwing.
198
+ this.RefreshView();
193
199
  }
194
200
  }
195
201
  /** Stable, order-independent string key for a query param record. */
@@ -225,12 +231,37 @@ export class BaseResourceComponent extends BaseNavigationComponent {
225
231
  if (this._loadCompleteEvent) {
226
232
  this._loadCompleteEvent();
227
233
  }
234
+ // Load completion almost always follows async work (RunView/fetch continuations) that
235
+ // Angular's tick will NOT pick up on its own for dynamically-attached views — re-render
236
+ // must be requested explicitly. See RefreshView() for the full explanation.
237
+ this.RefreshView();
228
238
  }
229
239
  NotifyLoadStarted() {
230
240
  this._loadStarted = true;
231
241
  if (this._loadStartedEvent) {
232
242
  this._loadStartedEvent();
233
243
  }
244
+ this.RefreshView();
245
+ }
246
+ /**
247
+ * Marks this component's view (and its ancestors) as needing change detection and schedules
248
+ * a tick — the reliable way for a resource component to re-render after updating state from
249
+ * async work (RunView/RunQuery continuations, timers, websocket pushes, RxJS subscriptions).
250
+ *
251
+ * WHY THIS EXISTS: the Explorer shell hosts resource components dynamically — `createComponent()`
252
+ * + `ApplicationRef.attachView()` — because tab content mounts into Golden Layout / cached DOM
253
+ * containers, not into an Angular template. Since Angular 18's change-detection scheduler
254
+ * rework (Explorer is on Angular 21), `ApplicationRef.tick()` only refreshes attached views
255
+ * that are FLAGGED dirty; a root-level attached view whose component mutates plain fields from
256
+ * an async continuation is never flagged, so the view silently never re-renders — even though
257
+ * the component uses default (non-OnPush) change detection (issue #3106).
258
+ *
259
+ * The framework calls this automatically from NotifyLoadStarted() / NotifyLoadComplete(), so
260
+ * the standard load lifecycle re-renders without any subclass action. Call it yourself after
261
+ * any LATER async state change that must reach the DOM outside those signals.
262
+ */
263
+ RefreshView() {
264
+ this.changeDetectorRef.markForCheck();
234
265
  }
235
266
  /**
236
267
  * Call this to notify the tab system that the resource's display name has changed.
@@ -1 +1 @@
1
- {"version":3,"file":"base-resource-component.js","sourceRoot":"","sources":["../../src/lib/base-resource-component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Directive, OnInit, OnDestroy, Input, inject } from \"@angular/core\";\nimport { Subject } from \"rxjs\";\nimport { filter, takeUntil } from \"rxjs/operators\";\nimport { BaseEntity } from \"@memberjunction/core\";\nimport { BaseNavigationComponent } from \"./base-navigation-component\";\nimport { ResourceData } from \"@memberjunction/core-entities\";\nimport { NavigationService, TabQueryParamUpdateGuard } from \"./navigation.service\";\n\n@Directive()\nexport abstract class BaseResourceComponent extends BaseNavigationComponent implements OnInit, OnDestroy {\n private _data: ResourceData = new ResourceData();\n private _suppressQueryParamSync = false;\n /** Stable key of the most recently delivered query params, used to de-duplicate\n * delivery across the reactive (initial/deep-link) and popstate paths. */\n private _lastDeliveredParamsKey: string | null = null;\n protected destroy$ = new Subject<void>();\n protected navigationService = inject(NavigationService);\n\n /**\n * Tab ID for query param notification scoping. Set by resource wrappers\n * that render child dashboards, so the child knows which tab it belongs to.\n * If not set, falls back to Data.Configuration.tabId.\n */\n @Input() ParentTabId: string | null = null;\n\n public get Data(): ResourceData {\n return this._data;\n }\n public set Data(value: ResourceData) {\n this._data = value;\n }\n\n private _loadComplete: boolean = false;\n public get LoadComplete(): boolean {\n return this._loadComplete;\n }\n\n /**\n * Watchdog window: if a resource component hasn't called {@link NotifyLoadComplete} within this\n * time, we log a warning naming the offending class. The app loading screen waits on\n * NotifyLoadComplete, so a resource that never calls it hangs the screen forever — this makes the\n * culprit obvious in the console instead of leaving a mystery \"stuck loading\" state.\n */\n private static readonly LOAD_COMPLETE_WATCHDOG_MS = 15_000;\n private _loadCompleteWatchdog: ReturnType<typeof setTimeout> | null = null;\n\n private _loadStarted: boolean = false;\n public get LoadStarted(): boolean {\n return this._loadStarted;\n }\n\n\n private _loadCompleteEvent: any = null;\n public get LoadCompleteEvent(): any {\n return this._loadCompleteEvent\n }\n public set LoadCompleteEvent(value: any) {\n this._loadCompleteEvent = value;\n }\n\n private _loadStartedEvent: any = null;\n public get LoadStartedEvent(): any {\n return this._loadStartedEvent\n }\n public set LoadStartedEvent(value: any) {\n this._loadStartedEvent = value;\n }\n\n private _resourceRecordSavedEvent: any = null;\n public get ResourceRecordSavedEvent(): any {\n return this._resourceRecordSavedEvent\n }\n public set ResourceRecordSavedEvent(value: any) {\n this._resourceRecordSavedEvent = value;\n }\n\n private _resourceCloseRequestedEvent: (() => void) | null = null;\n public get ResourceCloseRequestedEvent(): (() => void) | null {\n return this._resourceCloseRequestedEvent;\n }\n public set ResourceCloseRequestedEvent(value: (() => void) | null) {\n this._resourceCloseRequestedEvent = value;\n }\n\n private _displayNameChangedEvent: ((newName: string) => void) | null = null;\n public get DisplayNameChangedEvent(): ((newName: string) => void) | null {\n return this._displayNameChangedEvent;\n }\n public set DisplayNameChangedEvent(value: ((newName: string) => void) | null) {\n this._displayNameChangedEvent = value;\n }\n\n ngOnInit(): void {\n // Order matters: set up the popstate subscription first (a plain Subject — emits\n // nothing on subscribe), then the reactive initial-delivery subscription (backed by\n // a BehaviorSubject — emits the current params synchronously). This lets the initial\n // emission claim the 'deeplink' source before any later popstate event.\n this.setupQueryParamSubscription();\n this.setupInitialParamDelivery();\n\n // Start the NotifyLoadComplete watchdog (no-op once it fires or load completes).\n this._loadCompleteWatchdog = setTimeout(() => {\n if (!this._loadComplete) {\n // eslint-disable-next-line no-console\n console.warn(\n `[LoadComplete WATCHDOG] ${this.constructor.name} has NOT called NotifyLoadComplete() ` +\n `within ${BaseResourceComponent.LOAD_COMPLETE_WATCHDOG_MS / 1000}s. The app loading screen ` +\n `waits on this signal — if the screen is stuck, this resource is the likely cause. ` +\n `(tabId=${this.getTabId() || 'n/a'})`\n );\n }\n }, BaseResourceComponent.LOAD_COMPLETE_WATCHDOG_MS);\n }\n\n ngOnDestroy(): void {\n if (this._loadCompleteWatchdog) {\n clearTimeout(this._loadCompleteWatchdog);\n this._loadCompleteWatchdog = null;\n }\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * Called by the framework when query params change from an external source\n * (browser back/forward, deep link navigation).\n * Override in subclasses to react to query param changes.\n * @param params The new query params from the URL\n * @param source 'popstate' for back/forward, 'deeplink' for external URL entry\n */\n protected OnQueryParamsChanged(params: Record<string, string>, source: 'popstate' | 'deeplink'): void {\n // Default no-op — override in subclasses\n }\n\n /**\n * Push query param changes to the URL. Creates a browser history entry.\n * Safe to call during OnQueryParamsChanged — auto-suppressed to prevent loops.\n */\n protected UpdateQueryParams(params: Record<string, string | null>): void {\n if (this._suppressQueryParamSync) return;\n const tabId = this.getTabId();\n if (!tabId) {\n this.navigationService.UpdateActiveTabQueryParams(params);\n return;\n }\n\n this.navigationService.UpdateTabQueryParams(tabId, params, this.getQueryParamUpdateGuard());\n }\n\n /**\n * Read current query params from tab configuration.\n * Use in initDashboard() / ngOnInit() to get initial URL state.\n */\n protected GetQueryParams(): Record<string, string> {\n return (this.Data?.Configuration?.['queryParams'] as Record<string, string>) || {};\n }\n\n /**\n * Internal: subscribe to NavigationService query param notifications.\n * Filters to only this component's tab to prevent cross-tab leakage.\n * This is the explicit back/forward (popstate) path.\n */\n private setupQueryParamSubscription(): void {\n this.navigationService.QueryParamChanged$\n .pipe(\n filter(event => {\n const myTabId = this.getTabId();\n return !myTabId || event.TabId === myTabId;\n }),\n takeUntil(this.destroy$)\n )\n .subscribe(event => this.deliverQueryParams(event.Params));\n }\n\n /**\n * Internal: reactively deliver this tab's query params from the workspace\n * BehaviorSubject. Because the source replays the current value on subscribe and\n * emits future changes, this delivers initial deep-link params even when the\n * component mounts (e.g. from workspace restoration) before the URL params have\n * been merged into the tab configuration — closing the cold-load race that the\n * popstate-only path could not.\n */\n private setupInitialParamDelivery(): void {\n const tabId = this.getTabId();\n if (!tabId) {\n return; // No tab scope (e.g. embedded usage) — nothing to observe.\n }\n this.navigationService.ObserveTabQueryParams(tabId)\n .pipe(takeUntil(this.destroy$))\n .subscribe(params => this.deliverQueryParams(params));\n }\n\n /**\n * Internal: funnel point for both the reactive and popstate paths. De-duplicates\n * identical deliveries (the two paths overlap on back/forward) and labels the first\n * meaningful delivery as a 'deeplink', subsequent ones as 'popstate'.\n */\n private deliverQueryParams(params: Record<string, string>): void {\n const key = this.queryParamsKey(params);\n if (key === this._lastDeliveredParamsKey) {\n return; // Already delivered these exact params.\n }\n const isInitial = this._lastDeliveredParamsKey === null;\n // Don't fire an initial no-op: a component entered without deep-link params has\n // nothing to apply. Leave _lastDeliveredParamsKey null so the first real params\n // (whenever they arrive) are still treated as the deep-link entry.\n if (isInitial && Object.keys(params).length === 0) {\n return;\n }\n this._lastDeliveredParamsKey = key;\n const source: 'popstate' | 'deeplink' = isInitial ? 'deeplink' : 'popstate';\n // try/finally ensures the suppression flag is always cleared, even if\n // OnQueryParamsChanged throws.\n this._suppressQueryParamSync = true;\n try {\n this.OnQueryParamsChanged(params, source);\n } finally {\n this._suppressQueryParamSync = false;\n }\n }\n\n /** Stable, order-independent string key for a query param record. */\n private queryParamsKey(params: Record<string, string>): string {\n return Object.keys(params)\n .sort()\n .map(k => `${k}=${params[k]}`)\n .join('&');\n }\n\n /**\n * Get this component's tab ID. Checks ParentTabId input first (set by resource\n * wrappers for child dashboards), then falls back to Data.Configuration.tabId.\n */\n public getTabId(): string {\n return this.ParentTabId || this.Data?.Configuration?.['tabId'] as string || '';\n }\n\n private getQueryParamUpdateGuard(): TabQueryParamUpdateGuard {\n const config = this.Data?.Configuration || {};\n return {\n resourceType: config['resourceType'] as string | undefined,\n driverClass: (config['resourceTypeDriverClass'] || config['driverClass']) as string | undefined,\n recordId: (this.Data?.ResourceRecordID || config['recordId']) as string | undefined,\n navItemName: config['navItemName'] as string | undefined,\n entity: (config['Entity'] || config['entity']) as string | undefined\n };\n }\n\n protected NotifyLoadComplete() {\n this._loadComplete = true;\n if (this._loadCompleteWatchdog) {\n clearTimeout(this._loadCompleteWatchdog);\n this._loadCompleteWatchdog = null;\n }\n if (this._loadCompleteEvent) {\n this._loadCompleteEvent();\n }\n }\n\n protected NotifyLoadStarted() {\n this._loadStarted = true;\n if (this._loadStartedEvent) {\n this._loadStartedEvent();\n }\n }\n\n\n\n /**\n * Call this to notify the tab system that the resource's display name has changed.\n * The tab container will update the tab title and browser title accordingly.\n */\n protected NotifyDisplayNameChanged(newName: string): void {\n if (this._displayNameChangedEvent) {\n this._displayNameChangedEvent(newName);\n }\n }\n\n protected ResourceRecordSaved(resourceRecordEntity: BaseEntity) {\n // Use ToURLSegment, NOT ToString. ResourceRecordID is consumed by\n // EntityRecordResource.GetPrimaryKey → CompositeKey.LoadFromURLSegment, which\n // expects URL-segment format (e.g. \"ID|<uuid>\"). ToString produces \"ID=<uuid>\",\n // which LoadFromURLSegment treats as a raw value and double-prefixes —\n // breaking any code path that re-reads this field after save.\n this.Data.ResourceRecordID = resourceRecordEntity.PrimaryKey.ToURLSegment();\n if (this._resourceRecordSavedEvent) {\n this._resourceRecordSavedEvent(resourceRecordEntity);\n }\n }\n\n /**\n * Ask the host shell to close/dismiss this resource (typically: close the tab).\n * Called by subclasses that hosted a form that emitted a 'dismiss' navigation\n * event — most often, a brand-new record where the user clicked Discard. The\n * record was never saved, the form is empty, and leaving it open serves no\n * purpose. The tab-container listens for this and closes the workspace tab.\n */\n protected NotifyCloseRequested(): void {\n if (this._resourceCloseRequestedEvent) {\n this._resourceCloseRequestedEvent();\n }\n }\n\n abstract GetResourceDisplayName(data: ResourceData): Promise<string>\n\n abstract GetResourceIconClass(data: ResourceData): Promise<string>\n}\n"]}
1
+ {"version":3,"file":"base-resource-component.js","sourceRoot":"","sources":["../../src/lib/base-resource-component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectorRef, Directive, OnInit, OnDestroy, Input, inject } from \"@angular/core\";\nimport { Subject } from \"rxjs\";\nimport { filter, takeUntil } from \"rxjs/operators\";\nimport { BaseEntity } from \"@memberjunction/core\";\nimport { BaseNavigationComponent } from \"./base-navigation-component\";\nimport { ResourceData } from \"@memberjunction/core-entities\";\nimport { NavigationService, TabQueryParamUpdateGuard } from \"./navigation.service\";\n\n@Directive()\nexport abstract class BaseResourceComponent extends BaseNavigationComponent implements OnInit, OnDestroy {\n private _data: ResourceData = new ResourceData();\n private _suppressQueryParamSync = false;\n /** Stable key of the most recently delivered query params, used to de-duplicate\n * delivery across the reactive (initial/deep-link) and popstate paths. */\n private _lastDeliveredParamsKey: string | null = null;\n protected destroy$ = new Subject<void>();\n protected navigationService = inject(NavigationService);\n private changeDetectorRef = inject(ChangeDetectorRef);\n\n /**\n * Tab ID for query param notification scoping. Set by resource wrappers\n * that render child dashboards, so the child knows which tab it belongs to.\n * If not set, falls back to Data.Configuration.tabId.\n */\n @Input() ParentTabId: string | null = null;\n\n public get Data(): ResourceData {\n return this._data;\n }\n public set Data(value: ResourceData) {\n this._data = value;\n }\n\n private _loadComplete: boolean = false;\n public get LoadComplete(): boolean {\n return this._loadComplete;\n }\n\n /**\n * Watchdog window: if a resource component hasn't called {@link NotifyLoadComplete} within this\n * time, we log a warning naming the offending class. The app loading screen waits on\n * NotifyLoadComplete, so a resource that never calls it hangs the screen forever — this makes the\n * culprit obvious in the console instead of leaving a mystery \"stuck loading\" state.\n */\n private static readonly LOAD_COMPLETE_WATCHDOG_MS = 15_000;\n private _loadCompleteWatchdog: ReturnType<typeof setTimeout> | null = null;\n\n private _loadStarted: boolean = false;\n public get LoadStarted(): boolean {\n return this._loadStarted;\n }\n\n\n private _loadCompleteEvent: any = null;\n public get LoadCompleteEvent(): any {\n return this._loadCompleteEvent\n }\n public set LoadCompleteEvent(value: any) {\n this._loadCompleteEvent = value;\n }\n\n private _loadStartedEvent: any = null;\n public get LoadStartedEvent(): any {\n return this._loadStartedEvent\n }\n public set LoadStartedEvent(value: any) {\n this._loadStartedEvent = value;\n }\n\n private _resourceRecordSavedEvent: any = null;\n public get ResourceRecordSavedEvent(): any {\n return this._resourceRecordSavedEvent\n }\n public set ResourceRecordSavedEvent(value: any) {\n this._resourceRecordSavedEvent = value;\n }\n\n private _resourceCloseRequestedEvent: (() => void) | null = null;\n public get ResourceCloseRequestedEvent(): (() => void) | null {\n return this._resourceCloseRequestedEvent;\n }\n public set ResourceCloseRequestedEvent(value: (() => void) | null) {\n this._resourceCloseRequestedEvent = value;\n }\n\n private _displayNameChangedEvent: ((newName: string) => void) | null = null;\n public get DisplayNameChangedEvent(): ((newName: string) => void) | null {\n return this._displayNameChangedEvent;\n }\n public set DisplayNameChangedEvent(value: ((newName: string) => void) | null) {\n this._displayNameChangedEvent = value;\n }\n\n ngOnInit(): void {\n // Order matters: set up the popstate subscription first (a plain Subject — emits\n // nothing on subscribe), then the reactive initial-delivery subscription (backed by\n // a BehaviorSubject — emits the current params synchronously). This lets the initial\n // emission claim the 'deeplink' source before any later popstate event.\n this.setupQueryParamSubscription();\n this.setupInitialParamDelivery();\n\n // Start the NotifyLoadComplete watchdog (no-op once it fires or load completes).\n this._loadCompleteWatchdog = setTimeout(() => {\n if (!this._loadComplete) {\n // eslint-disable-next-line no-console\n console.warn(\n `[LoadComplete WATCHDOG] ${this.constructor.name} has NOT called NotifyLoadComplete() ` +\n `within ${BaseResourceComponent.LOAD_COMPLETE_WATCHDOG_MS / 1000}s. The app loading screen ` +\n `waits on this signal — if the screen is stuck, this resource is the likely cause. ` +\n `(tabId=${this.getTabId() || 'n/a'})`\n );\n }\n }, BaseResourceComponent.LOAD_COMPLETE_WATCHDOG_MS);\n }\n\n ngOnDestroy(): void {\n if (this._loadCompleteWatchdog) {\n clearTimeout(this._loadCompleteWatchdog);\n this._loadCompleteWatchdog = null;\n }\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n /**\n * Called by the framework when query params change from an external source\n * (browser back/forward, deep link navigation).\n * Override in subclasses to react to query param changes.\n * @param params The new query params from the URL\n * @param source 'popstate' for back/forward, 'deeplink' for external URL entry\n */\n protected OnQueryParamsChanged(params: Record<string, string>, source: 'popstate' | 'deeplink'): void {\n // Default no-op — override in subclasses\n }\n\n /**\n * Push query param changes to the URL. Creates a browser history entry.\n * Safe to call during OnQueryParamsChanged — auto-suppressed to prevent loops.\n */\n protected UpdateQueryParams(params: Record<string, string | null>): void {\n if (this._suppressQueryParamSync) return;\n const tabId = this.getTabId();\n if (!tabId) {\n this.navigationService.UpdateActiveTabQueryParams(params);\n return;\n }\n\n this.navigationService.UpdateTabQueryParams(tabId, params, this.getQueryParamUpdateGuard());\n }\n\n /**\n * Read current query params from tab configuration.\n * Use in initDashboard() / ngOnInit() to get initial URL state.\n */\n protected GetQueryParams(): Record<string, string> {\n return (this.Data?.Configuration?.['queryParams'] as Record<string, string>) || {};\n }\n\n /**\n * Internal: subscribe to NavigationService query param notifications.\n * Filters to only this component's tab to prevent cross-tab leakage.\n * This is the explicit back/forward (popstate) path.\n */\n private setupQueryParamSubscription(): void {\n this.navigationService.QueryParamChanged$\n .pipe(\n filter(event => {\n const myTabId = this.getTabId();\n return !myTabId || event.TabId === myTabId;\n }),\n takeUntil(this.destroy$)\n )\n .subscribe(event => this.deliverQueryParams(event.Params));\n }\n\n /**\n * Internal: reactively deliver this tab's query params from the workspace\n * BehaviorSubject. Because the source replays the current value on subscribe and\n * emits future changes, this delivers initial deep-link params even when the\n * component mounts (e.g. from workspace restoration) before the URL params have\n * been merged into the tab configuration — closing the cold-load race that the\n * popstate-only path could not.\n */\n private setupInitialParamDelivery(): void {\n const tabId = this.getTabId();\n if (!tabId) {\n return; // No tab scope (e.g. embedded usage) — nothing to observe.\n }\n this.navigationService.ObserveTabQueryParams(tabId)\n .pipe(takeUntil(this.destroy$))\n .subscribe(params => this.deliverQueryParams(params));\n }\n\n /**\n * Internal: funnel point for both the reactive and popstate paths. De-duplicates\n * identical deliveries (the two paths overlap on back/forward) and labels the first\n * meaningful delivery as a 'deeplink', subsequent ones as 'popstate'.\n */\n private deliverQueryParams(params: Record<string, string>): void {\n const key = this.queryParamsKey(params);\n if (key === this._lastDeliveredParamsKey) {\n return; // Already delivered these exact params.\n }\n const isInitial = this._lastDeliveredParamsKey === null;\n // Don't fire an initial no-op: a component entered without deep-link params has\n // nothing to apply. Leave _lastDeliveredParamsKey null so the first real params\n // (whenever they arrive) are still treated as the deep-link entry.\n if (isInitial && Object.keys(params).length === 0) {\n return;\n }\n this._lastDeliveredParamsKey = key;\n const source: 'popstate' | 'deeplink' = isInitial ? 'deeplink' : 'popstate';\n // try/finally ensures the suppression flag is always cleared, and the view is always\n // refreshed, even if OnQueryParamsChanged throws.\n this._suppressQueryParamSync = true;\n try {\n this.OnQueryParamsChanged(params, source);\n } finally {\n this._suppressQueryParamSync = false;\n // Query params arrive via RxJS (workspace stream / popstate), not via a template event —\n // state a subclass changed in OnQueryParamsChanged needs an explicit re-render request\n // for dynamically-attached views (see RefreshView). Inside `finally` so a subclass\n // override that throws still renders whatever partial state it applied before throwing.\n this.RefreshView();\n }\n }\n\n /** Stable, order-independent string key for a query param record. */\n private queryParamsKey(params: Record<string, string>): string {\n return Object.keys(params)\n .sort()\n .map(k => `${k}=${params[k]}`)\n .join('&');\n }\n\n /**\n * Get this component's tab ID. Checks ParentTabId input first (set by resource\n * wrappers for child dashboards), then falls back to Data.Configuration.tabId.\n */\n public getTabId(): string {\n return this.ParentTabId || this.Data?.Configuration?.['tabId'] as string || '';\n }\n\n private getQueryParamUpdateGuard(): TabQueryParamUpdateGuard {\n const config = this.Data?.Configuration || {};\n return {\n resourceType: config['resourceType'] as string | undefined,\n driverClass: (config['resourceTypeDriverClass'] || config['driverClass']) as string | undefined,\n recordId: (this.Data?.ResourceRecordID || config['recordId']) as string | undefined,\n navItemName: config['navItemName'] as string | undefined,\n entity: (config['Entity'] || config['entity']) as string | undefined\n };\n }\n\n protected NotifyLoadComplete() {\n this._loadComplete = true;\n if (this._loadCompleteWatchdog) {\n clearTimeout(this._loadCompleteWatchdog);\n this._loadCompleteWatchdog = null;\n }\n if (this._loadCompleteEvent) {\n this._loadCompleteEvent();\n }\n // Load completion almost always follows async work (RunView/fetch continuations) that\n // Angular's tick will NOT pick up on its own for dynamically-attached views — re-render\n // must be requested explicitly. See RefreshView() for the full explanation.\n this.RefreshView();\n }\n\n protected NotifyLoadStarted() {\n this._loadStarted = true;\n if (this._loadStartedEvent) {\n this._loadStartedEvent();\n }\n this.RefreshView();\n }\n\n /**\n * Marks this component's view (and its ancestors) as needing change detection and schedules\n * a tick — the reliable way for a resource component to re-render after updating state from\n * async work (RunView/RunQuery continuations, timers, websocket pushes, RxJS subscriptions).\n *\n * WHY THIS EXISTS: the Explorer shell hosts resource components dynamically — `createComponent()`\n * + `ApplicationRef.attachView()` — because tab content mounts into Golden Layout / cached DOM\n * containers, not into an Angular template. Since Angular 18's change-detection scheduler\n * rework (Explorer is on Angular 21), `ApplicationRef.tick()` only refreshes attached views\n * that are FLAGGED dirty; a root-level attached view whose component mutates plain fields from\n * an async continuation is never flagged, so the view silently never re-renders — even though\n * the component uses default (non-OnPush) change detection (issue #3106).\n *\n * The framework calls this automatically from NotifyLoadStarted() / NotifyLoadComplete(), so\n * the standard load lifecycle re-renders without any subclass action. Call it yourself after\n * any LATER async state change that must reach the DOM outside those signals.\n */\n protected RefreshView(): void {\n this.changeDetectorRef.markForCheck();\n }\n\n\n\n /**\n * Call this to notify the tab system that the resource's display name has changed.\n * The tab container will update the tab title and browser title accordingly.\n */\n protected NotifyDisplayNameChanged(newName: string): void {\n if (this._displayNameChangedEvent) {\n this._displayNameChangedEvent(newName);\n }\n }\n\n protected ResourceRecordSaved(resourceRecordEntity: BaseEntity) {\n // Use ToURLSegment, NOT ToString. ResourceRecordID is consumed by\n // EntityRecordResource.GetPrimaryKey → CompositeKey.LoadFromURLSegment, which\n // expects URL-segment format (e.g. \"ID|<uuid>\"). ToString produces \"ID=<uuid>\",\n // which LoadFromURLSegment treats as a raw value and double-prefixes —\n // breaking any code path that re-reads this field after save.\n this.Data.ResourceRecordID = resourceRecordEntity.PrimaryKey.ToURLSegment();\n if (this._resourceRecordSavedEvent) {\n this._resourceRecordSavedEvent(resourceRecordEntity);\n }\n }\n\n /**\n * Ask the host shell to close/dismiss this resource (typically: close the tab).\n * Called by subclasses that hosted a form that emitted a 'dismiss' navigation\n * event — most often, a brand-new record where the user clicked Discard. The\n * record was never saved, the form is empty, and leaving it open serves no\n * purpose. The tab-container listens for this and closes the workspace tab.\n */\n protected NotifyCloseRequested(): void {\n if (this._resourceCloseRequestedEvent) {\n this._resourceCloseRequestedEvent();\n }\n }\n\n abstract GetResourceDisplayName(data: ResourceData): Promise<string>\n\n abstract GetResourceIconClass(data: ResourceData): Promise<string>\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.service.d.ts","sourceRoot":"","sources":["../../src/lib/navigation.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,SAAS,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAA8B,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACrI,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAa,eAAe,EAAE,OAAO,EAAgB,UAAU,EAAE,MAAM,MAAM,CAAC;AACrF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAGvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;;AAElE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAC/B,sDAAsD;IACtD,MAAM,EAAE,qBAAqB,CAAC;IAC9B,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,KAAK,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAClE,CAAC,CAAC;CACN;AAED,MAAM,WAAW,wBAAwB;IACrC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,eAAe,CAAC;AAO1C;;;GAGG;AACH,qBAGa,iBAAkB,YAAW,SAAS;IAc/C,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,UAAU;IAdpB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,aAAa,CAAsB;IAE3C,OAAO,CAAC,kBAAkB,CAAwC;IAClE,yFAAyF;IAClF,kBAAkB,oCAA0C;IAEnE,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAAwC;IAC1D,4BAA4B;IAC5B,OAAO,CAAC,aAAa,CAAuB;gBAGlC,gBAAgB,EAAE,qBAAqB,EACvC,UAAU,EAAE,kBAAkB;IAKxC;;;;OAIG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED;;;;;;OAMG;IACH,OAAO,CAAC,uBAAuB;IAmC/B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;;OAGG;IACI,iBAAiB,IAAI,IAAI;IAShC;;;;OAIG;IACH,SAAgB,oBAAoB,8BAAqC;IAEzE,kGAAkG;IAClG,OAAO,CAAC,iBAAiB,CAA2D;IAEpF;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAyF;IAEtI;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAgB,mBAAmB,6CAAwD;IAE3F;;;;;;OAMG;IACI,yBAAyB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI;IAI3E;;;;;;;;;;OAUG;IACI,eAAe,CAAC,MAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI7F;;;;;;;;;OASG;IACI,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,KAAK,CAAC;QACrE,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAChE,CAAC,GAAG,IAAI;IAKT;;;;;;OAMG;IACI,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI;IASpE;;;;;;OAMG;IACI,sBAAsB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI;IAMlE;;;OAGG;IACI,cAAc,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI;IAI1D,WAAW,IAAI,IAAI;IAInB;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAcpC;;OAEG;IACH,OAAO,CAAC,cAAc;IAItB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,kCAAkC;IAI1C;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACI,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,MAAM;IAkD1G;;;OAGG;IACI,gBAAgB,CACrB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,YAAY,EACxB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IAgCT;;;OAGG;IACI,QAAQ,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA2BT;;;OAGG;IACI,aAAa,CAClB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA2BT;;;OAGG;IACI,UAAU,CACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA2BT;;;;OAIG;IACI,YAAY,CACjB,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA2BT;;;;OAIG;IACI,eAAe,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA8BT;;;OAGG;IACI,SAAS,CACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA2BT;;;;;OAKG;IACI,mBAAmB,CACxB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IA8BT;;;;;;;OAOG;IACI,UAAU,CACf,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,EAC9D,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM;IAoCT;;;;;;;;;;;OAWG;IACU,iBAAiB,CAC5B,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgCzB;;;;;;;;;;;OAWG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DlH;;;;;;;;;;;;;;;;OAgBG;IACH,0BAA0B,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAU5E;;;;;OAKG;IACH,oBAAoB,CAClB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EAC1C,KAAK,CAAC,EAAE,wBAAwB,GAC/B,OAAO;IA0BV;;;;OAIG;IACH,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAI7E;;;;;;;;;;;;;OAaG;IACI,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAU/E,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,yBAAyB;IA0BjC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;yCA/8BlB,iBAAiB;6CAAjB,iBAAiB;CAi/B7B"}
1
+ {"version":3,"file":"navigation.service.d.ts","sourceRoot":"","sources":["../../src/lib/navigation.service.ts"],"names":[],"mappings":"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"}
@@ -726,6 +726,15 @@ export class NavigationService {
726
726
  this.workspaceManager.SetActiveTab(appTabs[0].id);
727
727
  }
728
728
  }
729
+ // Apply requested query params on the DEFAULT path too (previously only the
730
+ // navItemName branch did) — e.g. the omnibar's '@agent' → Chat pre-addressing.
731
+ // Synchronous, so params are present before a cached resource component reattaches.
732
+ if (queryParams && Object.keys(queryParams).length > 0) {
733
+ const targetTabId = this.workspaceManager.GetActiveTabId();
734
+ if (targetTabId) {
735
+ this.applyQueryParamsToTab(targetTabId, queryParams);
736
+ }
737
+ }
729
738
  }
730
739
  /**
731
740
  * Update the query params for the currently active tab.
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.service.js","sourceRoot":"","sources":["../../src/lib/navigation.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, OnDestroy } from '@angular/core';\nimport { WorkspaceStateManager, NavItem, DynamicNavItem, TabRequest, ApplicationManager } from '@memberjunction/ng-base-application';\nimport { NavigationOptions } from './navigation.interfaces';\nimport { CompositeKey } from '@memberjunction/core';\nimport { fromEvent, BehaviorSubject, Subject, Subscription, Observable } from 'rxjs';\nimport type { AppContextSnapshot } from '@memberjunction/ai-core-plus';\nimport { map, distinctUntilChanged } from 'rxjs/operators';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent } from './base-resource-component';\n\n/**\n * Event emitted when query params change on a tab (e.g., from browser back/forward).\n * Includes the tab ID so that only the component in the affected tab reacts,\n * preventing cross-tab leakage in multi-tab scenarios.\n */\nexport interface QueryParamChangeEvent {\n TabId: string;\n Params: Record<string, string>;\n}\n\n/**\n * Event emitted when a resource component reports its agent context or tools.\n * The shell (which owns the ComponentCacheManager) subscribes to these events\n * and updates the cache + active AppContextSnapshot accordingly.\n */\nexport interface AgentContextUpdate {\n /** The component instance that reported the update */\n Caller: BaseResourceComponent;\n /** Dashboard-specific context for the agent (undefined = no change) */\n AgentContext?: Record<string, unknown>;\n /** Client tools available from this dashboard (undefined = no change) */\n AgentClientTools?: Array<{\n Name: string;\n Description: string;\n ParameterSchema: Record<string, unknown>;\n Handler: (params: Record<string, unknown>) => Promise<unknown>;\n }>;\n}\n\nexport interface TabQueryParamUpdateGuard {\n resourceType?: string | null;\n driverClass?: string | null;\n recordId?: string | null;\n navItemName?: string | null;\n entity?: string | null;\n}\n\n/**\n * System application ID for non-app-specific resources (fallback only)\n * Uses double underscore prefix to indicate system-level resource\n * @deprecated Prefer using NavigationService.getDefaultApplicationId() instead\n */\nexport const SYSTEM_APP_ID = '__explorer';\n\n/**\n * Neutral color for fallback when no app is available\n */\nconst NEUTRAL_APP_COLOR = '#9E9E9E'; // Material Design Gray 500\n\n/**\n * Centralized navigation service that handles all navigation operations\n * with automatic shift-key detection for power user workflows\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class NavigationService implements OnDestroy {\n private shiftKeyPressed = false;\n private subscriptions: Subscription[] = [];\n\n private queryParamChanged$ = new Subject<QueryParamChangeEvent>();\n /** Observable that emits when query params change on a tab (back/forward navigation). */\n public QueryParamChanged$ = this.queryParamChanged$.asObservable();\n\n /** Cached Home app ID (null means not found, undefined means not checked) */\n private _homeAppId: string | null | undefined = undefined;\n /** Cached Home app color */\n private _homeAppColor: string | null = null;\n\n constructor(\n private workspaceManager: WorkspaceStateManager,\n private appManager: ApplicationManager\n ) {\n this.setupGlobalShiftKeyDetection();\n }\n\n /**\n * Get the neutral color used for system-wide resources (entities, views, dashboards)\n * Returns a light neutral gray\n * @deprecated Use getDefaultAppColor() for better UX with Home app integration\n */\n get ExplorerAppColor(): string {\n return NEUTRAL_APP_COLOR;\n }\n\n /**\n * Gets the default application ID for orphan resources.\n * Priority: Home app > Active app > SYSTEM_APP_ID\n *\n * This ensures orphan resources (entity records, dashboards, views opened directly)\n * are grouped under the Home app instead of being orphaned in the tab system.\n */\n private getDefaultApplicationId(): string {\n // Check cache first\n if (this._homeAppId !== undefined) {\n if (this._homeAppId !== null) {\n return this._homeAppId;\n }\n // Home app not found, check active app\n const activeApp = this.appManager.GetActiveApp();\n if (activeApp) {\n return activeApp.ID;\n }\n return SYSTEM_APP_ID;\n }\n\n // First time - look for Home app\n const homeApp = this.appManager.GetAppByName('Home');\n if (homeApp) {\n this._homeAppId = homeApp.ID;\n this._homeAppColor = homeApp.GetColor();\n return homeApp.ID;\n }\n\n // Cache that Home app doesn't exist\n this._homeAppId = null;\n\n // Fall back to currently active app\n const activeApp = this.appManager.GetActiveApp();\n if (activeApp) {\n return activeApp.ID;\n }\n\n // Last resort - system app ID\n return SYSTEM_APP_ID;\n }\n\n /**\n * Gets the default app color for orphan resources.\n * Returns Home app color if available, otherwise neutral gray.\n */\n private getDefaultAppColor(): string {\n // Ensure cache is populated\n this.getDefaultApplicationId();\n\n // If Home app exists, use its color\n if (this._homeAppColor) {\n return this._homeAppColor;\n }\n\n // Check active app\n const activeApp = this.appManager.GetActiveApp();\n if (activeApp) {\n return activeApp.GetColor();\n }\n\n // Fall back to neutral color\n return NEUTRAL_APP_COLOR;\n }\n\n /**\n * Clears the cached Home app info.\n * Call this if apps are reloaded or user logs out.\n */\n public clearHomeAppCache(): void {\n this._homeAppId = undefined;\n this._homeAppColor = null;\n }\n\n // ════════════════════════════════════════════\n // Agent Context & Client Tools\n // ════════════════════════════════════════════\n\n /**\n * Observable stream of agent context updates from resource components.\n * The shell subscribes to this to update the ComponentCacheManager and\n * push changes to the chat overlay's AppContextSnapshot.DashboardContext.\n */\n public readonly AgentContextUpdated$ = new Subject<AgentContextUpdate>();\n\n /** The client tools currently surfaced to the agent (the most recent SetAgentClientTools set). */\n private currentAgentTools: NonNullable<AgentContextUpdate['AgentClientTools']> = [];\n\n /**\n * Tools captured for each cached resource component at the moment it was DETACHED, keyed by that\n * component (the one the cache manager tracks). Replayed on reattach. Captured at detach time (vs.\n * keyed by the registering component) so it works even when a resource WRAPPER component is what's\n * cached/reattached while an INNER child component is what actually called SetAgentClientTools\n * (e.g. Data Explorer's resource wrapper hosting its dashboard) — keying by the registerer would\n * miss on reattach. This keeps the agent's live tool set a function of the CURRENTLY attached\n * surface, fixing the staleness where a previous app's tools lingered after navigation.\n */\n private readonly agentToolsByDetachedResource = new Map<BaseResourceComponent, NonNullable<AgentContextUpdate['AgentClientTools']>>();\n\n /**\n * Latest `AppContextSnapshot` published by the Explorer app shell.\n *\n * Why: any embedded `<mj-conversation-chat-area>` instance outside the\n * floating chat overlay (Form Builder cockpit, future domain dashboards\n * that pop their own AI pane) needs to feed the SAME context the overlay\n * does so the agent sees what app + view + dashboard state the user is\n * looking at. Without this, the agent only sees the embedder's narrow\n * `AdditionalContext` slice and treats the user as if they have no app\n * context at all — which is the bug we just fixed.\n *\n * `MJExplorerAppComponent` is the canonical publisher (it owns the\n * snapshot construction); consumers SUBSCRIBE and bind the value to\n * their chat-area's `[appContext]`. Non-Explorer apps (custom MJ apps\n * that don't include explorer-app at all) build their own snapshot via\n * `BuildAppContextSnapshot()` in `@memberjunction/ai-core-plus`.\n *\n * Initial value is `null`; the publisher emits the first real snapshot\n * after the active app + nav state resolve on bootstrap.\n */\n public readonly AppContextSnapshot$ = new BehaviorSubject<AppContextSnapshot | null>(null);\n\n /**\n * Push a fresh AppContextSnapshot. Called by MJExplorerAppComponent\n * after each (a) app/tab change, (b) `handleAgentContextUpdate`\n * merging in `AdditionalContext` from a dashboard. Idempotent — no\n * de-duplication; embedders should treat the stream as \"the latest\n * value is canonical.\"\n */\n public PublishAppContextSnapshot(snapshot: AppContextSnapshot | null): void {\n this.AppContextSnapshot$.next(snapshot);\n }\n\n /**\n * Report the current agent-visible state from a resource component.\n * Call this whenever the dashboard's internal state changes (tab switch,\n * filter change, pipeline status change, drill-down, etc.).\n *\n * @param caller - Pass `this` from the calling component. Used to match\n * against the ComponentCacheManager to identify which cached component\n * this update belongs to.\n * @param context - Key-value pairs representing dashboard state the agent\n * should know about. Each dashboard defines its own shape.\n */\n public SetAgentContext(caller: BaseResourceComponent, context: Record<string, unknown>): void {\n this.AgentContextUpdated$.next({ Caller: caller, AgentContext: context });\n }\n\n /**\n * Register the client tools available from a resource component.\n * Call this on component init and whenever the available tools change.\n * Tools are automatically unregistered when the component becomes inactive\n * (tab switch) and re-registered when it becomes active again.\n *\n * @param caller - Pass `this` from the calling component.\n * @param tools - Array of tool definitions with Name, Description,\n * ParameterSchema (JSON Schema), and Handler function.\n */\n public SetAgentClientTools(caller: BaseResourceComponent, tools: Array<{\n Name: string;\n Description: string;\n ParameterSchema: Record<string, unknown>;\n Handler: (params: Record<string, unknown>) => Promise<unknown>;\n }>): void {\n this.currentAgentTools = tools;\n this.AgentContextUpdated$.next({ Caller: caller, AgentClientTools: tools });\n }\n\n /**\n * Re-publish a cached resource component's tools when its tab is re-focused. Cached components keep\n * their Angular instance but do NOT re-run `ngAfterViewInit`, so they never re-register on reattach\n * — the shell calls this so the just-reactivated surface's tools become the agent's active set\n * again. Replays the set captured for this component at its last detach; no-op (lets a fresh\n * component register itself) when none was captured (e.g. a component's very first attach).\n */\n public NotifyResourceReattached(caller: BaseResourceComponent): void {\n const tools = this.agentToolsByDetachedResource.get(caller);\n if (tools === undefined) {\n return;\n }\n this.currentAgentTools = tools;\n this.AgentContextUpdated$.next({ Caller: caller, AgentClientTools: tools });\n }\n\n /**\n * Capture + clear the active client tools when a resource component's tab is detached (navigated\n * away from), so the previous surface's tools aren't offered to the agent on the next surface. We\n * snapshot whatever tools are CURRENTLY active and key them by the detaching component, so\n * {@link NotifyResourceReattached} can replay them — robust to a wrapper component being the one\n * cached/reattached while an inner child actually registered the tools (e.g. Data Explorer).\n */\n public NotifyResourceDetached(caller: BaseResourceComponent): void {\n this.agentToolsByDetachedResource.set(caller, this.currentAgentTools);\n this.currentAgentTools = [];\n this.AgentContextUpdated$.next({ Caller: caller, AgentClientTools: [] });\n }\n\n /**\n * Drop a destroyed component's captured tools (e.g. on LRU eviction), so the map doesn't retain\n * references to dead component instances.\n */\n public ForgetResource(caller: BaseResourceComponent): void {\n this.agentToolsByDetachedResource.delete(caller);\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach(sub => sub.unsubscribe());\n }\n\n /**\n * Set up global keyboard event listeners to track shift key state\n */\n private setupGlobalShiftKeyDetection(): void {\n // Track shift key via mousedown events (capture phase) instead of keydown/keyup.\n // This is more reliable because:\n // 1. MouseEvent.shiftKey always reflects the actual modifier state at click time\n // 2. No risk of \"stuck\" state from missed keyup events (focus loss, tab switch, etc.)\n // 3. Navigation is always triggered by a click, so the shift state is read\n // at exactly the right moment\n this.subscriptions.push(\n fromEvent<MouseEvent>(document, 'mousedown', { capture: true }).subscribe(event => {\n this.shiftKeyPressed = event.shiftKey;\n })\n );\n }\n\n /**\n * Get current shift key state\n */\n private isShiftPressed(): boolean {\n return this.shiftKeyPressed;\n }\n\n /**\n * Determine if a new tab should be forced based on options and shift key state\n */\n private shouldForceNewTab(options?: NavigationOptions): boolean {\n // If forceNewTab is explicitly set, use that\n if (options?.forceNewTab !== undefined) {\n return options.forceNewTab;\n }\n\n // Otherwise, use global shift key detection\n return this.isShiftPressed();\n }\n\n /**\n * Returns whether the caller should use OpenTabForced (force-new path) or\n * OpenTab (replace-temp path).\n *\n * Rule: only honor an explicit force-new request — from the user via\n * shift+click, or from the caller via `options.forceNewTab`. We deliberately\n * do NOT apply heuristics that auto-switch the workspace out of\n * single-resource mode on cross-resource navigation. A previous version of\n * this method tried to do that (\"force new if single-resource + different\n * resource\") and it caused a regression: every plain hyperlink click on a\n * record opened a new tab and dropped the user into multi-tab mode, even\n * though they didn't ask for it. That violated the principle that mode\n * transitions are user-driven (shift) or explicitly requested (options).\n *\n * If a particular caller really needs the parent context preserved when\n * creating/navigating to a child resource (e.g. \"+New\" on a related-entity\n * grid inside an open record), the caller should pass `forceNewTab: true`\n * in `NavigationOptions`. That keeps intent explicit at the call site\n * instead of buried in a global heuristic.\n */\n private handleSingleResourceModeTransition(forceNew: boolean, _newRequest: TabRequest): boolean {\n return forceNew;\n }\n\n /**\n * Check if a tab request matches an existing tab's resource\n */\n private isSameResource(tab: any, request: TabRequest): boolean {\n // Different apps = different resources\n if (tab.applicationId !== request.ApplicationId) {\n return false;\n }\n\n // For resource-based tabs, compare resourceType and recordId\n if (request.Configuration?.resourceType) {\n const requestRecordId = request.ResourceRecordId || '';\n const tabRecordId = tab.resourceRecordId || '';\n return tab.configuration?.resourceType === request.Configuration.resourceType &&\n tabRecordId === requestRecordId;\n }\n\n // For app nav items, compare appName and navItemName\n if (request.Configuration?.appName && request.Configuration?.navItemName) {\n return tab.configuration?.appName === request.Configuration.appName &&\n tab.configuration?.navItemName === request.Configuration.navItemName;\n }\n\n // Fallback to basic comparison\n return false;\n }\n\n /**\n * Open a navigation item within an app\n */\n public OpenNavItem(appId: string, navItem: NavItem, appColor: string, options?: NavigationOptions): string {\n let forceNew = this.shouldForceNewTab(options);\n\n // Get the app to find its name\n const app = this.appManager.GetAppById(appId);\n const appName = app?.Name || '';\n\n // Dynamic nav items (e.g. orphan entity records) carry their original tab Configuration\n // and should NOT get navItemName stamped on them — that would cause buildResourceUrl\n // to produce a nav-item-style URL like /app/home/<label> instead of the correct\n // resource-type URL like /app/home/record/Entity/ID|...\n const isDynamic = (navItem as DynamicNavItem).isDynamic === true;\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: navItem.Label,\n ResourceRecordId: navItem.RecordID || '', // Also store at top level for consistent tab matching\n Configuration: {\n route: navItem.Route,\n resourceType: navItem.ResourceType,\n driverClass: navItem.DriverClass, // Pass through DriverClass for Custom resource type\n recordId: navItem.RecordID,\n appName: appName, // Store app name for URL building\n appId: appId,\n ...(isDynamic ? {} : { navItemName: navItem.Label }), // Only set for static nav items\n ...(navItem.Configuration || {})\n },\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n let tabId: string;\n if (forceNew) {\n // Always create a new tab\n tabId = this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n // Use existing OpenTab logic (may replace temporary tab)\n tabId = this.workspaceManager.OpenTab(request, appColor);\n }\n\n // Apply query params to the newly opened/activated tab if provided\n if (options?.queryParams) {\n this.applyQueryParamsToTab(tabId, options.queryParams);\n }\n\n return tabId;\n }\n\n /**\n * Open an entity record view\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenEntityRecord(\n entityName: string,\n recordPkey: CompositeKey,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n\n let forceNew = this.shouldForceNewTab(options);\n\n const recordId = recordPkey.ToURLSegment();\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `${entityName} - ${recordId}`,\n Configuration: {\n resourceType: 'Records',\n Entity: entityName, // Must use 'Entity' (capital E) - expected by record-resource.component\n recordId: recordId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: recordId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n let tabId: string;\n if (forceNew) {\n tabId = this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n tabId = this.workspaceManager.OpenTab(request, appColor);\n }\n\n return tabId;\n }\n\n /**\n * Open a view\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenView(\n viewId: string,\n viewName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: viewName,\n Configuration: {\n resourceType: 'MJ: User Views',\n viewId,\n recordId: viewId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: viewId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a dashboard\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenDashboard(\n dashboardId: string,\n dashboardName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: dashboardName,\n Configuration: {\n resourceType: 'Dashboards',\n dashboardId,\n recordId: dashboardId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: dashboardId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a report\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenReport(\n reportId: string,\n reportName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: reportName,\n Configuration: {\n resourceType: 'Reports',\n reportId,\n recordId: reportId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: reportId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open an artifact\n * Artifacts are versioned content containers (reports, dashboards, UI components, etc.)\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenArtifact(\n artifactId: string,\n artifactName?: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: artifactName || `Artifact - ${artifactId}`,\n Configuration: {\n resourceType: 'Artifacts',\n artifactId,\n recordId: artifactId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: artifactId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a dynamic view\n * Dynamic views are entity-based views with custom filters, not saved views\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenDynamicView(\n entityName: string,\n extraFilter?: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const filterSuffix = extraFilter ? ' (Filtered)' : '';\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `${entityName}${filterSuffix}`,\n Configuration: {\n resourceType: 'MJ: User Views',\n Entity: entityName,\n ExtraFilter: extraFilter,\n isDynamic: true,\n recordId: 'dynamic' // Special marker for dynamic views\n },\n ResourceRecordId: 'dynamic',\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a query\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenQuery(\n queryId: string,\n queryName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: queryName,\n Configuration: {\n resourceType: 'Queries',\n queryId,\n recordId: queryId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: queryId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a new entity record creation form\n * Uses Home app if available, otherwise falls back to active app or system app\n * @param entityName The name of the entity to create a new record for\n * @param options Navigation options including optional newRecordValues for pre-populating fields\n */\n public OpenNewEntityRecord(\n entityName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `New ${entityName}`,\n Configuration: {\n resourceType: 'Records',\n Entity: entityName, // Must use 'Entity' (capital E) - expected by record-resource.component\n recordId: '', // Empty recordId indicates new record\n isNew: true, // Flag to indicate this is a new record\n NewRecordValues: options?.newRecordValues // Pass through initial values if provided\n },\n ResourceRecordId: '', // Empty for new records\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a universal search results tab for the given query.\n * This is the primary way to open search results from anywhere in the application.\n *\n * @param query The search query text\n * @param searchOptions Optional search-specific options (e.g., minRelevance, scopeIDs)\n * @param options Navigation options\n */\n public OpenSearch(\n query: string,\n searchOptions?: { minRelevance?: number; scopeIDs?: string[] },\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const config: Record<string, unknown> = {\n resourceType: 'Search Results',\n Query: query,\n SearchInput: query,\n recordId: `search-${query}`\n };\n if (searchOptions?.minRelevance != null) {\n config['MinRelevance'] = searchOptions.minRelevance;\n }\n if (searchOptions?.scopeIDs && searchOptions.scopeIDs.length > 0) {\n config['ScopeIDs'] = searchOptions.scopeIDs;\n }\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `Search: ${query}`,\n Configuration: config,\n ResourceRecordId: `search-${query}`,\n IsPinned: false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Navigate to a nav item by name within the current or specified application.\n * Allows passing additional configuration parameters to merge with the nav item's config.\n * This is useful for cross-resource navigation where a component needs to navigate\n * to another nav item with specific parameters (e.g., navigate to Conversations with a specific conversationId).\n *\n * @param navItemName The label/name of the nav item to navigate to\n * @param configuration Additional configuration to merge (e.g., conversationId, artifactId)\n * @param appId Optional app ID (defaults to current active app)\n * @param options Navigation options\n * @returns The tab ID if successful, null if nav item not found\n */\n public async OpenNavItemByName(\n navItemName: string,\n configuration?: Record<string, unknown>,\n appId?: string,\n options?: NavigationOptions\n ): Promise<string | null> {\n // Get app (use provided or current active)\n const targetAppId = appId || this.appManager.GetActiveApp()?.ID;\n if (!targetAppId) {\n return null;\n }\n\n const app = this.appManager.GetAppById(targetAppId);\n if (!app) {\n return null;\n }\n\n // Find the nav item by name\n const navItems = await app.GetNavItems();\n const navItem = navItems.find(item => item.Label === navItemName);\n if (!navItem) {\n return null;\n }\n\n // Create a merged nav item with additional configuration\n const mergedNavItem: NavItem = {\n ...navItem,\n Configuration: {\n ...(navItem.Configuration || {}),\n ...(configuration || {})\n }\n };\n\n // Use existing OpenNavItem\n return this.OpenNavItem(targetAppId, mergedNavItem, app.GetColor(), options);\n }\n\n /**\n * Switch to an application by ID.\n * This sets the app as active and either opens a specific nav item or creates a default tab.\n * If the requested nav item already has an open tab, switches to that tab instead of creating a new one.\n * @param appId The application ID to switch to\n * @param navItemName Optional name of a nav item to open within the app. If provided, opens that nav item.\n * @param queryParams Optional query params to apply to the target tab. Applied SYNCHRONOUSLY once the\n * target tab is active — critical when navigating (e.g. from a Home pin) to an\n * app whose resource component is cached: the params must be in the tab config\n * BEFORE the tab-container reattaches the cached component, otherwise the cache\n * restores its own (stale) saved params and the navigation intent is lost.\n */\n async SwitchToApp(appId: string, navItemName?: string, queryParams?: Record<string, string | null>): Promise<void> {\n await this.appManager.SetActiveApp(appId);\n\n const app = this.appManager.GetAllApps().find(a => UUIDsEqual(a.ID, appId));\n if (!app) {\n return;\n }\n\n const appTabs = this.workspaceManager.GetAppTabs(appId);\n\n // If a specific nav item is requested\n if (navItemName) {\n const navItems = await app.GetNavItems();\n const navItem = navItems.find(item => item.Label === navItemName);\n if (navItem) {\n // Check if there's already a tab for this nav item\n const existingTab = appTabs.find(tab =>\n tab.title === navItem.Label ||\n (tab.configuration?.['route'] === navItem.Route && navItem.Route)\n );\n\n if (existingTab) {\n // Switch to existing tab\n this.workspaceManager.SetActiveTab(existingTab.id);\n } else {\n // Open new tab for this nav item\n this.OpenNavItem(appId, navItem, app.GetColor());\n }\n // Apply the requested query params to whichever tab is now active — synchronously,\n // so they're present before the (possibly cached) resource component reattaches.\n if (queryParams && Object.keys(queryParams).length > 0) {\n const targetTabId = this.workspaceManager.GetActiveTabId();\n if (targetTabId) {\n this.applyQueryParamsToTab(targetTabId, queryParams);\n }\n }\n return;\n }\n // Nav item not found, fall through to default behavior\n }\n\n // No specific nav item requested - check if app has any tabs\n if (appTabs.length === 0) {\n // Create default tab\n const tabRequest = await app.CreateDefaultTab();\n if (tabRequest) {\n this.workspaceManager.OpenTab(tabRequest, app.GetColor());\n }\n } else {\n // App has tabs - switch to the first one (or active one if exists)\n const config = this.workspaceManager.GetConfiguration();\n const activeAppTab = appTabs.find(t => t.id === config?.activeTabId);\n if (!activeAppTab) {\n // No active tab for this app, switch to first tab\n this.workspaceManager.SetActiveTab(appTabs[0].id);\n }\n }\n }\n\n /**\n * Update the query params for the currently active tab.\n * This updates the tab's configuration and triggers a URL sync via the shell's\n * workspace configuration subscription.\n *\n * Use this instead of directly calling router.navigate() to ensure proper\n * URL management that respects app-scoped routes.\n *\n * @param queryParams Object containing query param key-value pairs.\n * Use null values to remove a query param.\n * @example\n * // Add or update query params\n * navigationService.UpdateActiveTabQueryParams({ category: 'abc123', dashboard: 'xyz789' });\n *\n * // Remove a query param\n * navigationService.UpdateActiveTabQueryParams({ category: null });\n */\n UpdateActiveTabQueryParams(queryParams: Record<string, string | null>): void {\n const activeTabId = this.workspaceManager.GetActiveTabId();\n if (!activeTabId) {\n console.warn('NavigationService.UpdateActiveTabQueryParams: No active tab');\n return;\n }\n\n this.applyQueryParamsToTab(activeTabId, queryParams);\n }\n\n /**\n * Update query params for a specific tab, optionally only if the tab still hosts\n * the expected resource identity. This matters in single-resource mode where a\n * tab ID can be reused for a different resource while the previous component is\n * detached but still alive in the cache.\n */\n UpdateTabQueryParams(\n tabId: string,\n queryParams: Record<string, string | null>,\n guard?: TabQueryParamUpdateGuard\n ): boolean {\n const tab = this.workspaceManager.GetTab(tabId);\n if (!tab) {\n console.debug('NavigationService.UpdateTabQueryParams: Tab not found; ignoring stale query-param update:', tabId);\n return false;\n }\n\n if (guard && !this.tabMatchesQueryParamGuard(tab, guard)) {\n console.debug('NavigationService.UpdateTabQueryParams: Tab identity changed; ignoring stale query-param update:', {\n tabId,\n guard,\n current: {\n resourceType: tab.configuration?.['resourceType'],\n driverClass: tab.configuration?.['resourceTypeDriverClass'] || tab.configuration?.['driverClass'],\n recordId: tab.resourceRecordId || tab.configuration?.['recordId'],\n navItemName: tab.configuration?.['navItemName'],\n entity: tab.configuration?.['Entity'] || tab.configuration?.['entity']\n }\n });\n return false;\n }\n\n this.applyQueryParamsToTab(tabId, queryParams);\n return true;\n }\n\n /**\n * Notify subscribers that query params changed on a specific tab.\n * Called by the shell when back/forward navigation changes query params on the active tab.\n * The notification includes the tab ID so only the component in that tab reacts.\n */\n NotifyQueryParamsChanged(tabId: string, params: Record<string, string>): void {\n this.queryParamChanged$.next({ TabId: tabId, Params: params });\n }\n\n /**\n * Reactively observe the query params for a specific tab.\n *\n * Backed by the workspace BehaviorSubject, so a subscriber receives the current\n * params *immediately* on subscribe AND every subsequent change — including the\n * deep-link params that the ResourceResolver merges into the tab configuration on\n * a cold/direct URL load.\n *\n * This is the race-free counterpart to {@link NotifyQueryParamsChanged} (a plain\n * Subject that drops events fired before a component has subscribed). A resource\n * component that mounts from workspace restoration can subscribe here and still\n * pick up its initial deep-link state regardless of whether the params landed in\n * the tab config before or after it mounted.\n */\n public ObserveTabQueryParams(tabId: string): Observable<Record<string, string>> {\n return this.workspaceManager.Configuration.pipe(\n map(config => {\n const tab = config?.tabs?.find(t => t.id === tabId);\n return (tab?.configuration?.['queryParams'] || {}) as Record<string, string>;\n }),\n distinctUntilChanged((a, b) => this.shallowParamsEqual(a, b))\n );\n }\n\n private shallowParamsEqual(a: Record<string, string>, b: Record<string, string>): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) {\n return false;\n }\n return keysA.every(key => a[key] === b[key]);\n }\n\n private tabMatchesQueryParamGuard(tab: { resourceRecordId?: string; configuration?: Record<string, unknown> }, guard: TabQueryParamUpdateGuard): boolean {\n const config = tab.configuration || {};\n const matches = (expected: string | null | undefined, actual: unknown, normalize = false): boolean => {\n if (expected === undefined || expected === null) {\n return true;\n }\n const expectedText = String(expected);\n const actualText = actual == null ? '' : String(actual);\n return normalize\n ? expectedText.trim().toLowerCase() === actualText.trim().toLowerCase()\n : expectedText === actualText;\n };\n\n const currentDriverClass = (config['resourceTypeDriverClass'] || config['driverClass']) as string | undefined;\n const currentRecordId = tab.resourceRecordId || (config['recordId'] as string | undefined) || '';\n const currentEntity = (config['Entity'] || config['entity']) as string | undefined;\n\n // Resource type and entity names can vary by casing/metadata spelling; class names,\n // record IDs, and nav labels are canonical tab identity fields and stay exact-match.\n return matches(guard.resourceType, config['resourceType'], true) &&\n matches(guard.driverClass, currentDriverClass) &&\n matches(guard.recordId, currentRecordId) &&\n matches(guard.navItemName, config['navItemName']) &&\n matches(guard.entity, currentEntity, true);\n }\n\n /**\n * Apply query params to a specific tab by ID.\n * Merges with any existing query params on the tab. Use null values to remove params.\n */\n private applyQueryParamsToTab(tabId: string, queryParams: Record<string, string | null>): void {\n const tab = this.workspaceManager.GetTab(tabId);\n if (!tab) {\n console.warn('NavigationService.applyQueryParamsToTab: Tab not found:', tabId);\n return;\n }\n\n // Get existing queryParams from tab configuration\n const existingQueryParams = (tab.configuration?.['queryParams'] || {}) as Record<string, string | null>;\n\n // Merge with new query params\n const mergedQueryParams: Record<string, string> = {};\n\n // Start with existing params (excluding nulls)\n for (const [key, value] of Object.entries(existingQueryParams)) {\n if (value !== null) {\n mergedQueryParams[key] = value;\n }\n }\n\n // Apply new params (null means remove)\n for (const [key, value] of Object.entries(queryParams)) {\n if (value === null) {\n delete mergedQueryParams[key];\n } else {\n mergedQueryParams[key] = value;\n }\n }\n\n // Update the tab configuration\n this.workspaceManager.UpdateTabConfiguration(tabId, {\n queryParams: Object.keys(mergedQueryParams).length > 0 ? mergedQueryParams : undefined\n });\n }\n}\n"]}
1
+ {"version":3,"file":"navigation.service.js","sourceRoot":"","sources":["../../src/lib/navigation.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, OnDestroy } from '@angular/core';\nimport { WorkspaceStateManager, NavItem, DynamicNavItem, TabRequest, ApplicationManager } from '@memberjunction/ng-base-application';\nimport { NavigationOptions } from './navigation.interfaces';\nimport { CompositeKey } from '@memberjunction/core';\nimport { fromEvent, BehaviorSubject, Subject, Subscription, Observable } from 'rxjs';\nimport type { AppContextSnapshot } from '@memberjunction/ai-core-plus';\nimport { map, distinctUntilChanged } from 'rxjs/operators';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent } from './base-resource-component';\n\n/**\n * Event emitted when query params change on a tab (e.g., from browser back/forward).\n * Includes the tab ID so that only the component in the affected tab reacts,\n * preventing cross-tab leakage in multi-tab scenarios.\n */\nexport interface QueryParamChangeEvent {\n TabId: string;\n Params: Record<string, string>;\n}\n\n/**\n * Event emitted when a resource component reports its agent context or tools.\n * The shell (which owns the ComponentCacheManager) subscribes to these events\n * and updates the cache + active AppContextSnapshot accordingly.\n */\nexport interface AgentContextUpdate {\n /** The component instance that reported the update */\n Caller: BaseResourceComponent;\n /** Dashboard-specific context for the agent (undefined = no change) */\n AgentContext?: Record<string, unknown>;\n /** Client tools available from this dashboard (undefined = no change) */\n AgentClientTools?: Array<{\n Name: string;\n Description: string;\n ParameterSchema: Record<string, unknown>;\n Handler: (params: Record<string, unknown>) => Promise<unknown>;\n }>;\n}\n\nexport interface TabQueryParamUpdateGuard {\n resourceType?: string | null;\n driverClass?: string | null;\n recordId?: string | null;\n navItemName?: string | null;\n entity?: string | null;\n}\n\n/**\n * System application ID for non-app-specific resources (fallback only)\n * Uses double underscore prefix to indicate system-level resource\n * @deprecated Prefer using NavigationService.getDefaultApplicationId() instead\n */\nexport const SYSTEM_APP_ID = '__explorer';\n\n/**\n * Neutral color for fallback when no app is available\n */\nconst NEUTRAL_APP_COLOR = '#9E9E9E'; // Material Design Gray 500\n\n/**\n * Centralized navigation service that handles all navigation operations\n * with automatic shift-key detection for power user workflows\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class NavigationService implements OnDestroy {\n private shiftKeyPressed = false;\n private subscriptions: Subscription[] = [];\n\n private queryParamChanged$ = new Subject<QueryParamChangeEvent>();\n /** Observable that emits when query params change on a tab (back/forward navigation). */\n public QueryParamChanged$ = this.queryParamChanged$.asObservable();\n\n /** Cached Home app ID (null means not found, undefined means not checked) */\n private _homeAppId: string | null | undefined = undefined;\n /** Cached Home app color */\n private _homeAppColor: string | null = null;\n\n constructor(\n private workspaceManager: WorkspaceStateManager,\n private appManager: ApplicationManager\n ) {\n this.setupGlobalShiftKeyDetection();\n }\n\n /**\n * Get the neutral color used for system-wide resources (entities, views, dashboards)\n * Returns a light neutral gray\n * @deprecated Use getDefaultAppColor() for better UX with Home app integration\n */\n get ExplorerAppColor(): string {\n return NEUTRAL_APP_COLOR;\n }\n\n /**\n * Gets the default application ID for orphan resources.\n * Priority: Home app > Active app > SYSTEM_APP_ID\n *\n * This ensures orphan resources (entity records, dashboards, views opened directly)\n * are grouped under the Home app instead of being orphaned in the tab system.\n */\n private getDefaultApplicationId(): string {\n // Check cache first\n if (this._homeAppId !== undefined) {\n if (this._homeAppId !== null) {\n return this._homeAppId;\n }\n // Home app not found, check active app\n const activeApp = this.appManager.GetActiveApp();\n if (activeApp) {\n return activeApp.ID;\n }\n return SYSTEM_APP_ID;\n }\n\n // First time - look for Home app\n const homeApp = this.appManager.GetAppByName('Home');\n if (homeApp) {\n this._homeAppId = homeApp.ID;\n this._homeAppColor = homeApp.GetColor();\n return homeApp.ID;\n }\n\n // Cache that Home app doesn't exist\n this._homeAppId = null;\n\n // Fall back to currently active app\n const activeApp = this.appManager.GetActiveApp();\n if (activeApp) {\n return activeApp.ID;\n }\n\n // Last resort - system app ID\n return SYSTEM_APP_ID;\n }\n\n /**\n * Gets the default app color for orphan resources.\n * Returns Home app color if available, otherwise neutral gray.\n */\n private getDefaultAppColor(): string {\n // Ensure cache is populated\n this.getDefaultApplicationId();\n\n // If Home app exists, use its color\n if (this._homeAppColor) {\n return this._homeAppColor;\n }\n\n // Check active app\n const activeApp = this.appManager.GetActiveApp();\n if (activeApp) {\n return activeApp.GetColor();\n }\n\n // Fall back to neutral color\n return NEUTRAL_APP_COLOR;\n }\n\n /**\n * Clears the cached Home app info.\n * Call this if apps are reloaded or user logs out.\n */\n public clearHomeAppCache(): void {\n this._homeAppId = undefined;\n this._homeAppColor = null;\n }\n\n // ════════════════════════════════════════════\n // Agent Context & Client Tools\n // ════════════════════════════════════════════\n\n /**\n * Observable stream of agent context updates from resource components.\n * The shell subscribes to this to update the ComponentCacheManager and\n * push changes to the chat overlay's AppContextSnapshot.DashboardContext.\n */\n public readonly AgentContextUpdated$ = new Subject<AgentContextUpdate>();\n\n /** The client tools currently surfaced to the agent (the most recent SetAgentClientTools set). */\n private currentAgentTools: NonNullable<AgentContextUpdate['AgentClientTools']> = [];\n\n /**\n * Tools captured for each cached resource component at the moment it was DETACHED, keyed by that\n * component (the one the cache manager tracks). Replayed on reattach. Captured at detach time (vs.\n * keyed by the registering component) so it works even when a resource WRAPPER component is what's\n * cached/reattached while an INNER child component is what actually called SetAgentClientTools\n * (e.g. Data Explorer's resource wrapper hosting its dashboard) — keying by the registerer would\n * miss on reattach. This keeps the agent's live tool set a function of the CURRENTLY attached\n * surface, fixing the staleness where a previous app's tools lingered after navigation.\n */\n private readonly agentToolsByDetachedResource = new Map<BaseResourceComponent, NonNullable<AgentContextUpdate['AgentClientTools']>>();\n\n /**\n * Latest `AppContextSnapshot` published by the Explorer app shell.\n *\n * Why: any embedded `<mj-conversation-chat-area>` instance outside the\n * floating chat overlay (Form Builder cockpit, future domain dashboards\n * that pop their own AI pane) needs to feed the SAME context the overlay\n * does so the agent sees what app + view + dashboard state the user is\n * looking at. Without this, the agent only sees the embedder's narrow\n * `AdditionalContext` slice and treats the user as if they have no app\n * context at all — which is the bug we just fixed.\n *\n * `MJExplorerAppComponent` is the canonical publisher (it owns the\n * snapshot construction); consumers SUBSCRIBE and bind the value to\n * their chat-area's `[appContext]`. Non-Explorer apps (custom MJ apps\n * that don't include explorer-app at all) build their own snapshot via\n * `BuildAppContextSnapshot()` in `@memberjunction/ai-core-plus`.\n *\n * Initial value is `null`; the publisher emits the first real snapshot\n * after the active app + nav state resolve on bootstrap.\n */\n public readonly AppContextSnapshot$ = new BehaviorSubject<AppContextSnapshot | null>(null);\n\n /**\n * Push a fresh AppContextSnapshot. Called by MJExplorerAppComponent\n * after each (a) app/tab change, (b) `handleAgentContextUpdate`\n * merging in `AdditionalContext` from a dashboard. Idempotent — no\n * de-duplication; embedders should treat the stream as \"the latest\n * value is canonical.\"\n */\n public PublishAppContextSnapshot(snapshot: AppContextSnapshot | null): void {\n this.AppContextSnapshot$.next(snapshot);\n }\n\n /**\n * Report the current agent-visible state from a resource component.\n * Call this whenever the dashboard's internal state changes (tab switch,\n * filter change, pipeline status change, drill-down, etc.).\n *\n * @param caller - Pass `this` from the calling component. Used to match\n * against the ComponentCacheManager to identify which cached component\n * this update belongs to.\n * @param context - Key-value pairs representing dashboard state the agent\n * should know about. Each dashboard defines its own shape.\n */\n public SetAgentContext(caller: BaseResourceComponent, context: Record<string, unknown>): void {\n this.AgentContextUpdated$.next({ Caller: caller, AgentContext: context });\n }\n\n /**\n * Register the client tools available from a resource component.\n * Call this on component init and whenever the available tools change.\n * Tools are automatically unregistered when the component becomes inactive\n * (tab switch) and re-registered when it becomes active again.\n *\n * @param caller - Pass `this` from the calling component.\n * @param tools - Array of tool definitions with Name, Description,\n * ParameterSchema (JSON Schema), and Handler function.\n */\n public SetAgentClientTools(caller: BaseResourceComponent, tools: Array<{\n Name: string;\n Description: string;\n ParameterSchema: Record<string, unknown>;\n Handler: (params: Record<string, unknown>) => Promise<unknown>;\n }>): void {\n this.currentAgentTools = tools;\n this.AgentContextUpdated$.next({ Caller: caller, AgentClientTools: tools });\n }\n\n /**\n * Re-publish a cached resource component's tools when its tab is re-focused. Cached components keep\n * their Angular instance but do NOT re-run `ngAfterViewInit`, so they never re-register on reattach\n * — the shell calls this so the just-reactivated surface's tools become the agent's active set\n * again. Replays the set captured for this component at its last detach; no-op (lets a fresh\n * component register itself) when none was captured (e.g. a component's very first attach).\n */\n public NotifyResourceReattached(caller: BaseResourceComponent): void {\n const tools = this.agentToolsByDetachedResource.get(caller);\n if (tools === undefined) {\n return;\n }\n this.currentAgentTools = tools;\n this.AgentContextUpdated$.next({ Caller: caller, AgentClientTools: tools });\n }\n\n /**\n * Capture + clear the active client tools when a resource component's tab is detached (navigated\n * away from), so the previous surface's tools aren't offered to the agent on the next surface. We\n * snapshot whatever tools are CURRENTLY active and key them by the detaching component, so\n * {@link NotifyResourceReattached} can replay them — robust to a wrapper component being the one\n * cached/reattached while an inner child actually registered the tools (e.g. Data Explorer).\n */\n public NotifyResourceDetached(caller: BaseResourceComponent): void {\n this.agentToolsByDetachedResource.set(caller, this.currentAgentTools);\n this.currentAgentTools = [];\n this.AgentContextUpdated$.next({ Caller: caller, AgentClientTools: [] });\n }\n\n /**\n * Drop a destroyed component's captured tools (e.g. on LRU eviction), so the map doesn't retain\n * references to dead component instances.\n */\n public ForgetResource(caller: BaseResourceComponent): void {\n this.agentToolsByDetachedResource.delete(caller);\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach(sub => sub.unsubscribe());\n }\n\n /**\n * Set up global keyboard event listeners to track shift key state\n */\n private setupGlobalShiftKeyDetection(): void {\n // Track shift key via mousedown events (capture phase) instead of keydown/keyup.\n // This is more reliable because:\n // 1. MouseEvent.shiftKey always reflects the actual modifier state at click time\n // 2. No risk of \"stuck\" state from missed keyup events (focus loss, tab switch, etc.)\n // 3. Navigation is always triggered by a click, so the shift state is read\n // at exactly the right moment\n this.subscriptions.push(\n fromEvent<MouseEvent>(document, 'mousedown', { capture: true }).subscribe(event => {\n this.shiftKeyPressed = event.shiftKey;\n })\n );\n }\n\n /**\n * Get current shift key state\n */\n private isShiftPressed(): boolean {\n return this.shiftKeyPressed;\n }\n\n /**\n * Determine if a new tab should be forced based on options and shift key state\n */\n private shouldForceNewTab(options?: NavigationOptions): boolean {\n // If forceNewTab is explicitly set, use that\n if (options?.forceNewTab !== undefined) {\n return options.forceNewTab;\n }\n\n // Otherwise, use global shift key detection\n return this.isShiftPressed();\n }\n\n /**\n * Returns whether the caller should use OpenTabForced (force-new path) or\n * OpenTab (replace-temp path).\n *\n * Rule: only honor an explicit force-new request — from the user via\n * shift+click, or from the caller via `options.forceNewTab`. We deliberately\n * do NOT apply heuristics that auto-switch the workspace out of\n * single-resource mode on cross-resource navigation. A previous version of\n * this method tried to do that (\"force new if single-resource + different\n * resource\") and it caused a regression: every plain hyperlink click on a\n * record opened a new tab and dropped the user into multi-tab mode, even\n * though they didn't ask for it. That violated the principle that mode\n * transitions are user-driven (shift) or explicitly requested (options).\n *\n * If a particular caller really needs the parent context preserved when\n * creating/navigating to a child resource (e.g. \"+New\" on a related-entity\n * grid inside an open record), the caller should pass `forceNewTab: true`\n * in `NavigationOptions`. That keeps intent explicit at the call site\n * instead of buried in a global heuristic.\n */\n private handleSingleResourceModeTransition(forceNew: boolean, _newRequest: TabRequest): boolean {\n return forceNew;\n }\n\n /**\n * Check if a tab request matches an existing tab's resource\n */\n private isSameResource(tab: any, request: TabRequest): boolean {\n // Different apps = different resources\n if (tab.applicationId !== request.ApplicationId) {\n return false;\n }\n\n // For resource-based tabs, compare resourceType and recordId\n if (request.Configuration?.resourceType) {\n const requestRecordId = request.ResourceRecordId || '';\n const tabRecordId = tab.resourceRecordId || '';\n return tab.configuration?.resourceType === request.Configuration.resourceType &&\n tabRecordId === requestRecordId;\n }\n\n // For app nav items, compare appName and navItemName\n if (request.Configuration?.appName && request.Configuration?.navItemName) {\n return tab.configuration?.appName === request.Configuration.appName &&\n tab.configuration?.navItemName === request.Configuration.navItemName;\n }\n\n // Fallback to basic comparison\n return false;\n }\n\n /**\n * Open a navigation item within an app\n */\n public OpenNavItem(appId: string, navItem: NavItem, appColor: string, options?: NavigationOptions): string {\n let forceNew = this.shouldForceNewTab(options);\n\n // Get the app to find its name\n const app = this.appManager.GetAppById(appId);\n const appName = app?.Name || '';\n\n // Dynamic nav items (e.g. orphan entity records) carry their original tab Configuration\n // and should NOT get navItemName stamped on them — that would cause buildResourceUrl\n // to produce a nav-item-style URL like /app/home/<label> instead of the correct\n // resource-type URL like /app/home/record/Entity/ID|...\n const isDynamic = (navItem as DynamicNavItem).isDynamic === true;\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: navItem.Label,\n ResourceRecordId: navItem.RecordID || '', // Also store at top level for consistent tab matching\n Configuration: {\n route: navItem.Route,\n resourceType: navItem.ResourceType,\n driverClass: navItem.DriverClass, // Pass through DriverClass for Custom resource type\n recordId: navItem.RecordID,\n appName: appName, // Store app name for URL building\n appId: appId,\n ...(isDynamic ? {} : { navItemName: navItem.Label }), // Only set for static nav items\n ...(navItem.Configuration || {})\n },\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n let tabId: string;\n if (forceNew) {\n // Always create a new tab\n tabId = this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n // Use existing OpenTab logic (may replace temporary tab)\n tabId = this.workspaceManager.OpenTab(request, appColor);\n }\n\n // Apply query params to the newly opened/activated tab if provided\n if (options?.queryParams) {\n this.applyQueryParamsToTab(tabId, options.queryParams);\n }\n\n return tabId;\n }\n\n /**\n * Open an entity record view\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenEntityRecord(\n entityName: string,\n recordPkey: CompositeKey,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n\n let forceNew = this.shouldForceNewTab(options);\n\n const recordId = recordPkey.ToURLSegment();\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `${entityName} - ${recordId}`,\n Configuration: {\n resourceType: 'Records',\n Entity: entityName, // Must use 'Entity' (capital E) - expected by record-resource.component\n recordId: recordId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: recordId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n let tabId: string;\n if (forceNew) {\n tabId = this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n tabId = this.workspaceManager.OpenTab(request, appColor);\n }\n\n return tabId;\n }\n\n /**\n * Open a view\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenView(\n viewId: string,\n viewName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: viewName,\n Configuration: {\n resourceType: 'MJ: User Views',\n viewId,\n recordId: viewId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: viewId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a dashboard\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenDashboard(\n dashboardId: string,\n dashboardName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: dashboardName,\n Configuration: {\n resourceType: 'Dashboards',\n dashboardId,\n recordId: dashboardId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: dashboardId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a report\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenReport(\n reportId: string,\n reportName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: reportName,\n Configuration: {\n resourceType: 'Reports',\n reportId,\n recordId: reportId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: reportId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open an artifact\n * Artifacts are versioned content containers (reports, dashboards, UI components, etc.)\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenArtifact(\n artifactId: string,\n artifactName?: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: artifactName || `Artifact - ${artifactId}`,\n Configuration: {\n resourceType: 'Artifacts',\n artifactId,\n recordId: artifactId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: artifactId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a dynamic view\n * Dynamic views are entity-based views with custom filters, not saved views\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenDynamicView(\n entityName: string,\n extraFilter?: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const filterSuffix = extraFilter ? ' (Filtered)' : '';\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `${entityName}${filterSuffix}`,\n Configuration: {\n resourceType: 'MJ: User Views',\n Entity: entityName,\n ExtraFilter: extraFilter,\n isDynamic: true,\n recordId: 'dynamic' // Special marker for dynamic views\n },\n ResourceRecordId: 'dynamic',\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a query\n * Uses Home app if available, otherwise falls back to active app or system app\n */\n public OpenQuery(\n queryId: string,\n queryName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: queryName,\n Configuration: {\n resourceType: 'Queries',\n queryId,\n recordId: queryId // Also needed in Configuration for tab-container.component to populate ResourceRecordID\n },\n ResourceRecordId: queryId,\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a new entity record creation form\n * Uses Home app if available, otherwise falls back to active app or system app\n * @param entityName The name of the entity to create a new record for\n * @param options Navigation options including optional newRecordValues for pre-populating fields\n */\n public OpenNewEntityRecord(\n entityName: string,\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n\n let forceNew = this.shouldForceNewTab(options);\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `New ${entityName}`,\n Configuration: {\n resourceType: 'Records',\n Entity: entityName, // Must use 'Entity' (capital E) - expected by record-resource.component\n recordId: '', // Empty recordId indicates new record\n isNew: true, // Flag to indicate this is a new record\n NewRecordValues: options?.newRecordValues // Pass through initial values if provided\n },\n ResourceRecordId: '', // Empty for new records\n IsPinned: options?.pinTab || false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Open a universal search results tab for the given query.\n * This is the primary way to open search results from anywhere in the application.\n *\n * @param query The search query text\n * @param searchOptions Optional search-specific options (e.g., minRelevance, scopeIDs)\n * @param options Navigation options\n */\n public OpenSearch(\n query: string,\n searchOptions?: { minRelevance?: number; scopeIDs?: string[] },\n options?: NavigationOptions\n ): string {\n const appId = this.getDefaultApplicationId();\n const appColor = this.getDefaultAppColor();\n let forceNew = this.shouldForceNewTab(options);\n\n const config: Record<string, unknown> = {\n resourceType: 'Search Results',\n Query: query,\n SearchInput: query,\n recordId: `search-${query}`\n };\n if (searchOptions?.minRelevance != null) {\n config['MinRelevance'] = searchOptions.minRelevance;\n }\n if (searchOptions?.scopeIDs && searchOptions.scopeIDs.length > 0) {\n config['ScopeIDs'] = searchOptions.scopeIDs;\n }\n\n const request: TabRequest = {\n ApplicationId: appId,\n Title: `Search: ${query}`,\n Configuration: config,\n ResourceRecordId: `search-${query}`,\n IsPinned: false\n };\n\n // Handle transition from single-resource mode\n forceNew = this.handleSingleResourceModeTransition(forceNew, request);\n\n if (forceNew) {\n return this.workspaceManager.OpenTabForced(request, appColor);\n } else {\n return this.workspaceManager.OpenTab(request, appColor);\n }\n }\n\n /**\n * Navigate to a nav item by name within the current or specified application.\n * Allows passing additional configuration parameters to merge with the nav item's config.\n * This is useful for cross-resource navigation where a component needs to navigate\n * to another nav item with specific parameters (e.g., navigate to Conversations with a specific conversationId).\n *\n * @param navItemName The label/name of the nav item to navigate to\n * @param configuration Additional configuration to merge (e.g., conversationId, artifactId)\n * @param appId Optional app ID (defaults to current active app)\n * @param options Navigation options\n * @returns The tab ID if successful, null if nav item not found\n */\n public async OpenNavItemByName(\n navItemName: string,\n configuration?: Record<string, unknown>,\n appId?: string,\n options?: NavigationOptions\n ): Promise<string | null> {\n // Get app (use provided or current active)\n const targetAppId = appId || this.appManager.GetActiveApp()?.ID;\n if (!targetAppId) {\n return null;\n }\n\n const app = this.appManager.GetAppById(targetAppId);\n if (!app) {\n return null;\n }\n\n // Find the nav item by name\n const navItems = await app.GetNavItems();\n const navItem = navItems.find(item => item.Label === navItemName);\n if (!navItem) {\n return null;\n }\n\n // Create a merged nav item with additional configuration\n const mergedNavItem: NavItem = {\n ...navItem,\n Configuration: {\n ...(navItem.Configuration || {}),\n ...(configuration || {})\n }\n };\n\n // Use existing OpenNavItem\n return this.OpenNavItem(targetAppId, mergedNavItem, app.GetColor(), options);\n }\n\n /**\n * Switch to an application by ID.\n * This sets the app as active and either opens a specific nav item or creates a default tab.\n * If the requested nav item already has an open tab, switches to that tab instead of creating a new one.\n * @param appId The application ID to switch to\n * @param navItemName Optional name of a nav item to open within the app. If provided, opens that nav item.\n * @param queryParams Optional query params to apply to the target tab. Applied SYNCHRONOUSLY once the\n * target tab is active — critical when navigating (e.g. from a Home pin) to an\n * app whose resource component is cached: the params must be in the tab config\n * BEFORE the tab-container reattaches the cached component, otherwise the cache\n * restores its own (stale) saved params and the navigation intent is lost.\n */\n async SwitchToApp(appId: string, navItemName?: string, queryParams?: Record<string, string | null>): Promise<void> {\n await this.appManager.SetActiveApp(appId);\n\n const app = this.appManager.GetAllApps().find(a => UUIDsEqual(a.ID, appId));\n if (!app) {\n return;\n }\n\n const appTabs = this.workspaceManager.GetAppTabs(appId);\n\n // If a specific nav item is requested\n if (navItemName) {\n const navItems = await app.GetNavItems();\n const navItem = navItems.find(item => item.Label === navItemName);\n if (navItem) {\n // Check if there's already a tab for this nav item\n const existingTab = appTabs.find(tab =>\n tab.title === navItem.Label ||\n (tab.configuration?.['route'] === navItem.Route && navItem.Route)\n );\n\n if (existingTab) {\n // Switch to existing tab\n this.workspaceManager.SetActiveTab(existingTab.id);\n } else {\n // Open new tab for this nav item\n this.OpenNavItem(appId, navItem, app.GetColor());\n }\n // Apply the requested query params to whichever tab is now active — synchronously,\n // so they're present before the (possibly cached) resource component reattaches.\n if (queryParams && Object.keys(queryParams).length > 0) {\n const targetTabId = this.workspaceManager.GetActiveTabId();\n if (targetTabId) {\n this.applyQueryParamsToTab(targetTabId, queryParams);\n }\n }\n return;\n }\n // Nav item not found, fall through to default behavior\n }\n\n // No specific nav item requested - check if app has any tabs\n if (appTabs.length === 0) {\n // Create default tab\n const tabRequest = await app.CreateDefaultTab();\n if (tabRequest) {\n this.workspaceManager.OpenTab(tabRequest, app.GetColor());\n }\n } else {\n // App has tabs - switch to the first one (or active one if exists)\n const config = this.workspaceManager.GetConfiguration();\n const activeAppTab = appTabs.find(t => t.id === config?.activeTabId);\n if (!activeAppTab) {\n // No active tab for this app, switch to first tab\n this.workspaceManager.SetActiveTab(appTabs[0].id);\n }\n }\n\n // Apply requested query params on the DEFAULT path too (previously only the\n // navItemName branch did) — e.g. the omnibar's '@agent' → Chat pre-addressing.\n // Synchronous, so params are present before a cached resource component reattaches.\n if (queryParams && Object.keys(queryParams).length > 0) {\n const targetTabId = this.workspaceManager.GetActiveTabId();\n if (targetTabId) {\n this.applyQueryParamsToTab(targetTabId, queryParams);\n }\n }\n }\n\n /**\n * Update the query params for the currently active tab.\n * This updates the tab's configuration and triggers a URL sync via the shell's\n * workspace configuration subscription.\n *\n * Use this instead of directly calling router.navigate() to ensure proper\n * URL management that respects app-scoped routes.\n *\n * @param queryParams Object containing query param key-value pairs.\n * Use null values to remove a query param.\n * @example\n * // Add or update query params\n * navigationService.UpdateActiveTabQueryParams({ category: 'abc123', dashboard: 'xyz789' });\n *\n * // Remove a query param\n * navigationService.UpdateActiveTabQueryParams({ category: null });\n */\n UpdateActiveTabQueryParams(queryParams: Record<string, string | null>): void {\n const activeTabId = this.workspaceManager.GetActiveTabId();\n if (!activeTabId) {\n console.warn('NavigationService.UpdateActiveTabQueryParams: No active tab');\n return;\n }\n\n this.applyQueryParamsToTab(activeTabId, queryParams);\n }\n\n /**\n * Update query params for a specific tab, optionally only if the tab still hosts\n * the expected resource identity. This matters in single-resource mode where a\n * tab ID can be reused for a different resource while the previous component is\n * detached but still alive in the cache.\n */\n UpdateTabQueryParams(\n tabId: string,\n queryParams: Record<string, string | null>,\n guard?: TabQueryParamUpdateGuard\n ): boolean {\n const tab = this.workspaceManager.GetTab(tabId);\n if (!tab) {\n console.debug('NavigationService.UpdateTabQueryParams: Tab not found; ignoring stale query-param update:', tabId);\n return false;\n }\n\n if (guard && !this.tabMatchesQueryParamGuard(tab, guard)) {\n console.debug('NavigationService.UpdateTabQueryParams: Tab identity changed; ignoring stale query-param update:', {\n tabId,\n guard,\n current: {\n resourceType: tab.configuration?.['resourceType'],\n driverClass: tab.configuration?.['resourceTypeDriverClass'] || tab.configuration?.['driverClass'],\n recordId: tab.resourceRecordId || tab.configuration?.['recordId'],\n navItemName: tab.configuration?.['navItemName'],\n entity: tab.configuration?.['Entity'] || tab.configuration?.['entity']\n }\n });\n return false;\n }\n\n this.applyQueryParamsToTab(tabId, queryParams);\n return true;\n }\n\n /**\n * Notify subscribers that query params changed on a specific tab.\n * Called by the shell when back/forward navigation changes query params on the active tab.\n * The notification includes the tab ID so only the component in that tab reacts.\n */\n NotifyQueryParamsChanged(tabId: string, params: Record<string, string>): void {\n this.queryParamChanged$.next({ TabId: tabId, Params: params });\n }\n\n /**\n * Reactively observe the query params for a specific tab.\n *\n * Backed by the workspace BehaviorSubject, so a subscriber receives the current\n * params *immediately* on subscribe AND every subsequent change — including the\n * deep-link params that the ResourceResolver merges into the tab configuration on\n * a cold/direct URL load.\n *\n * This is the race-free counterpart to {@link NotifyQueryParamsChanged} (a plain\n * Subject that drops events fired before a component has subscribed). A resource\n * component that mounts from workspace restoration can subscribe here and still\n * pick up its initial deep-link state regardless of whether the params landed in\n * the tab config before or after it mounted.\n */\n public ObserveTabQueryParams(tabId: string): Observable<Record<string, string>> {\n return this.workspaceManager.Configuration.pipe(\n map(config => {\n const tab = config?.tabs?.find(t => t.id === tabId);\n return (tab?.configuration?.['queryParams'] || {}) as Record<string, string>;\n }),\n distinctUntilChanged((a, b) => this.shallowParamsEqual(a, b))\n );\n }\n\n private shallowParamsEqual(a: Record<string, string>, b: Record<string, string>): boolean {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) {\n return false;\n }\n return keysA.every(key => a[key] === b[key]);\n }\n\n private tabMatchesQueryParamGuard(tab: { resourceRecordId?: string; configuration?: Record<string, unknown> }, guard: TabQueryParamUpdateGuard): boolean {\n const config = tab.configuration || {};\n const matches = (expected: string | null | undefined, actual: unknown, normalize = false): boolean => {\n if (expected === undefined || expected === null) {\n return true;\n }\n const expectedText = String(expected);\n const actualText = actual == null ? '' : String(actual);\n return normalize\n ? expectedText.trim().toLowerCase() === actualText.trim().toLowerCase()\n : expectedText === actualText;\n };\n\n const currentDriverClass = (config['resourceTypeDriverClass'] || config['driverClass']) as string | undefined;\n const currentRecordId = tab.resourceRecordId || (config['recordId'] as string | undefined) || '';\n const currentEntity = (config['Entity'] || config['entity']) as string | undefined;\n\n // Resource type and entity names can vary by casing/metadata spelling; class names,\n // record IDs, and nav labels are canonical tab identity fields and stay exact-match.\n return matches(guard.resourceType, config['resourceType'], true) &&\n matches(guard.driverClass, currentDriverClass) &&\n matches(guard.recordId, currentRecordId) &&\n matches(guard.navItemName, config['navItemName']) &&\n matches(guard.entity, currentEntity, true);\n }\n\n /**\n * Apply query params to a specific tab by ID.\n * Merges with any existing query params on the tab. Use null values to remove params.\n */\n private applyQueryParamsToTab(tabId: string, queryParams: Record<string, string | null>): void {\n const tab = this.workspaceManager.GetTab(tabId);\n if (!tab) {\n console.warn('NavigationService.applyQueryParamsToTab: Tab not found:', tabId);\n return;\n }\n\n // Get existing queryParams from tab configuration\n const existingQueryParams = (tab.configuration?.['queryParams'] || {}) as Record<string, string | null>;\n\n // Merge with new query params\n const mergedQueryParams: Record<string, string> = {};\n\n // Start with existing params (excluding nulls)\n for (const [key, value] of Object.entries(existingQueryParams)) {\n if (value !== null) {\n mergedQueryParams[key] = value;\n }\n }\n\n // Apply new params (null means remove)\n for (const [key, value] of Object.entries(queryParams)) {\n if (value === null) {\n delete mergedQueryParams[key];\n } else {\n mergedQueryParams[key] = value;\n }\n }\n\n // Update the tab configuration\n this.workspaceManager.UpdateTabConfiguration(tabId, {\n queryParams: Object.keys(mergedQueryParams).length > 0 ? mergedQueryParams : undefined\n });\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-shared",
3
- "version": "5.46.0",
3
+ "version": "5.48.0",
4
4
  "description": "MemberJunction: MJ Explorer Angular Shared Package - utility functions and other reusable elements used across other MJ Angular packages within the MJ Explorer App - do not use outside of MJ Explorer.",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -29,17 +29,17 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@angular/platform-browser": "21.1.3",
32
- "@memberjunction/ai-core-plus": "5.46.0",
33
- "@memberjunction/ai-engine-base": "5.46.0",
34
- "@memberjunction/core": "5.46.0",
35
- "@memberjunction/core-entities": "5.46.0",
36
- "@memberjunction/entity-communications-base": "5.46.0",
37
- "@memberjunction/global": "5.46.0",
38
- "@memberjunction/graphql-dataprovider": "5.46.0",
39
- "@memberjunction/ng-base-application": "5.46.0",
40
- "@memberjunction/ng-base-types": "5.46.0",
41
- "@memberjunction/ng-notifications": "5.46.0",
42
- "@memberjunction/ng-shared-generic": "5.46.0",
32
+ "@memberjunction/ai-core-plus": "5.48.0",
33
+ "@memberjunction/ai-engine-base": "5.48.0",
34
+ "@memberjunction/core": "5.48.0",
35
+ "@memberjunction/core-entities": "5.48.0",
36
+ "@memberjunction/entity-communications-base": "5.48.0",
37
+ "@memberjunction/global": "5.48.0",
38
+ "@memberjunction/graphql-dataprovider": "5.48.0",
39
+ "@memberjunction/ng-base-application": "5.48.0",
40
+ "@memberjunction/ng-base-types": "5.48.0",
41
+ "@memberjunction/ng-notifications": "5.48.0",
42
+ "@memberjunction/ng-shared-generic": "5.48.0",
43
43
  "html-to-image": "^1.11.11",
44
44
  "tslib": "^2.8.1"
45
45
  },