@openmfp/portal-ui-lib 0.187.2 → 0.189.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,7 @@ The main features of this library are:
34
34
  - [The luigiAuthEventsCallbacksService Option](#the-luigiautheventscallbacksservice-option)
35
35
  - [The customMessageListeners Option](#the-custommessagelisteners-option)
36
36
  - [The customGlobalNodesService Option](#the-customglobalnodesservice-option)
37
+ - [The navigationRedirectStrategy Option](#the-navigationredirectstrategy-option)
37
38
  - [Listen and react to Authentication Events](#listen-and-react-to-authentication-events)
38
39
  - [Configure Proxy for Backend REST Calls](#configure-proxy-for-backend-rest-calls)
39
40
  - [Start your Project](#start-your-project)
@@ -634,6 +635,39 @@ const portalOptions: PortalOptions = {
634
635
  }
635
636
  ```
636
637
 
638
+ #### The navigationRedirectStrategy Option
639
+
640
+ This option allows you to customize where and how the portal stores the URL to redirect the user to after login (for example after session expiry or logout). By default the library uses `localStorage`. You can provide your own implementation of `NavigationRedirectStrategy` to use session storage, a backend, or custom logic.
641
+
642
+ ```ts
643
+ import { Injectable } from '@angular/core';
644
+ import { NavigationRedirectStrategy } from '@openmfp/portal-ui-lib';
645
+
646
+ @Injectable()
647
+ export class CustomNavigationRedirectStrategy implements NavigationRedirectStrategy {
648
+ getRedirectUrl(): string {
649
+ return sessionStorage.getItem('returnUrl') || '/';
650
+ }
651
+
652
+ saveRedirectUrl(url: string): void {
653
+ sessionStorage.setItem('returnUrl', url);
654
+ }
655
+
656
+ clearRedirectUrl(): void {
657
+ sessionStorage.removeItem('returnUrl');
658
+ }
659
+ }
660
+ ```
661
+
662
+ In your `main.ts` you can provide your custom implementation like so:
663
+
664
+ ```ts
665
+ const portalOptions: PortalOptions = {
666
+ navigationRedirectStrategy: CustomNavigationRedirectStrategy,
667
+ // ... other portal options
668
+ }
669
+ ```
670
+
637
671
  ### Listen and react to Authentication Events
638
672
 
639
673
  There are following Authentication Events, to which the library consuming application can subscribe and react upon, in case required.
@@ -4,7 +4,7 @@ import * as i1 from '@angular/common/http';
4
4
  import { HttpHeaders, HttpErrorResponse, HttpClient, provideHttpClient } from '@angular/common/http';
5
5
  import { firstValueFrom, Subject, lastValueFrom, tap, filter } from 'rxjs';
6
6
  import * as i1$1 from '@angular/router';
7
- import { ActivatedRoute, NavigationEnd, NavigationStart, RouterOutlet, RouteReuseStrategy, provideRouter } from '@angular/router';
7
+ import { ActivatedRoute, NavigationEnd, RouterOutlet, RouteReuseStrategy, provideRouter } from '@angular/router';
8
8
  import { jwtDecode } from 'jwt-decode';
9
9
  import isEqual from 'lodash.isequal';
10
10
  import oAuth2 from '@luigi-project/plugin-auth-oauth2';
@@ -406,6 +406,7 @@ const LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN = 'OPENMFP_LU
406
406
  const LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE';
407
407
  const HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_HEADER_BAR_CONFIG_SERVICE';
408
408
  const LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_ROUTING_CONFIG_SERVICE';
409
+ const NAVIGATION_REDIRECT_STRATEGY_INJECTION_TOKEN = 'OPENMFP_NAVIGATION_REDIRECT_STRATEGY';
409
410
 
410
411
  class GlobalContextConfigService {
411
412
  constructor() {
@@ -774,6 +775,23 @@ const featureToggleLocalStorage = {
774
775
  },
775
776
  };
776
777
 
778
+ class DefaultNavigationRedirectStrategy {
779
+ getRedirectUrl() {
780
+ return localStorage.getItem(LocalStorageKeys.LAST_NAVIGATION_URL) || '/';
781
+ }
782
+ saveRedirectUrl(url) {
783
+ localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, url);
784
+ }
785
+ clearRedirectUrl() {
786
+ localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, '');
787
+ }
788
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DefaultNavigationRedirectStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
789
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DefaultNavigationRedirectStrategy }); }
790
+ }
791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DefaultNavigationRedirectStrategy, decorators: [{
792
+ type: Injectable
793
+ }] });
794
+
777
795
  class IframeService {
778
796
  constructor() {
779
797
  this.luigiCoreService = inject(LuigiCoreService);
@@ -1772,56 +1790,43 @@ async function initializeAutomaticSessionRefresh(sessionRefreshService, authServ
1772
1790
  const provideSessionRefresh = () => provideAppInitializer(() => initializeAutomaticSessionRefresh(inject(SessionRefreshService), inject(AuthService)));
1773
1791
 
1774
1792
  class NavigationService {
1775
- constructor(router, authService, loginEventService) {
1793
+ constructor(router, authService, loginEventService, navigationRedirectStrategy) {
1776
1794
  this.router = router;
1777
1795
  this.authService = authService;
1778
1796
  this.loginEventService = loginEventService;
1797
+ this.navigationRedirectStrategy = navigationRedirectStrategy;
1798
+ this.lastUrl = '/';
1779
1799
  }
1780
1800
  track() {
1781
1801
  this.router.events
1782
1802
  .pipe(filter$1((event) => event instanceof NavigationEnd))
1783
1803
  .subscribe((event) => {
1784
- this.currentUrl = event.url;
1785
- });
1786
- this.router.events
1787
- .pipe(filter$1((event) => event instanceof NavigationStart))
1788
- .subscribe((event) => {
1789
- this.previousUrl = event.url;
1804
+ this.lastUrl = event.url;
1790
1805
  });
1791
1806
  this.authService.authEvents
1792
- .pipe(filter$1((event) => event === AuthEvent.AUTH_EXPIRED))
1793
- .subscribe({ next: () => this.saveCurrentUrl() });
1794
- this.authService.authEvents
1795
- .pipe(filter$1((event) => event === AuthEvent.LOGOUT))
1796
- .subscribe({
1797
- next: () => {
1798
- this.saveLastNavigationUrl();
1799
- },
1807
+ .pipe(filter$1((event) => event === AuthEvent.AUTH_EXPIRED || event === AuthEvent.LOGOUT))
1808
+ .subscribe(() => {
1809
+ this.saveRedirectUrl();
1800
1810
  });
1801
1811
  this.loginEventService.loginEvents
1802
1812
  .pipe(filter$1((event) => event.type === LoginEventType.LOGIN_TRIGGERED))
1803
- .subscribe({
1804
- next: (event) => {
1805
- this.router.navigate([this.getRedirectUrl()], {
1806
- queryParams: event.queryParams,
1807
- });
1808
- this.clearCurrentUrl();
1809
- },
1813
+ .subscribe((event) => {
1814
+ this.router.navigate([this.getRedirectUrl()], {
1815
+ queryParams: event.queryParams,
1816
+ });
1817
+ this.clearRedirectUrl();
1810
1818
  });
1811
1819
  }
1812
- clearCurrentUrl() {
1813
- localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, '');
1814
- }
1815
- saveCurrentUrl() {
1816
- localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, this.currentUrl);
1820
+ saveRedirectUrl() {
1821
+ this.navigationRedirectStrategy.saveRedirectUrl(this.lastUrl);
1817
1822
  }
1818
- saveLastNavigationUrl() {
1819
- localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, this.previousUrl);
1823
+ clearRedirectUrl() {
1824
+ this.navigationRedirectStrategy.clearRedirectUrl();
1820
1825
  }
1821
1826
  getRedirectUrl() {
1822
- return localStorage.getItem(LocalStorageKeys.LAST_NAVIGATION_URL) || '/';
1827
+ return this.navigationRedirectStrategy.getRedirectUrl();
1823
1828
  }
1824
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: NavigationService, deps: [{ token: i1$1.Router }, { token: AuthService }, { token: LoginEventService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1829
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: NavigationService, deps: [{ token: i1$1.Router }, { token: AuthService }, { token: LoginEventService }, { token: NAVIGATION_REDIRECT_STRATEGY_INJECTION_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); }
1825
1830
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: NavigationService, providedIn: 'root' }); }
1826
1831
  }
1827
1832
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: NavigationService, decorators: [{
@@ -1829,7 +1834,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
1829
1834
  args: [{
1830
1835
  providedIn: 'root',
1831
1836
  }]
1832
- }], ctorParameters: () => [{ type: i1$1.Router }, { type: AuthService }, { type: LoginEventService }] });
1837
+ }], ctorParameters: () => [{ type: i1$1.Router }, { type: AuthService }, { type: LoginEventService }, { type: undefined, decorators: [{
1838
+ type: Inject,
1839
+ args: [NAVIGATION_REDIRECT_STRATEGY_INJECTION_TOKEN]
1840
+ }] }] });
1833
1841
 
1834
1842
  async function track(navigationService) {
1835
1843
  navigationService.track();
@@ -2447,8 +2455,8 @@ class NavigationConfigService {
2447
2455
  nodeAccessibilityResolver: this.luigiNodesService.nodePolicyResolver,
2448
2456
  validWebcomponentUrls: envConfig.validWebcomponentUrls,
2449
2457
  intentMapping: this.intentNavigationService.buildIntentMappings(allNodes),
2450
- nodeChangeHook: function (prevNode, nextNode) {
2451
- this.nodeChangeHookConfigService?.nodeChangeHook(prevNode, nextNode);
2458
+ nodeChangeHook: function (prevNode, nextNode, ctx) {
2459
+ this.nodeChangeHookConfigService?.nodeChangeHook(prevNode, nextNode, ctx.currentContext);
2452
2460
  }.bind(this),
2453
2461
  breadcrumbs: await this.headerBarService.getConfig(),
2454
2462
  };
@@ -2726,6 +2734,10 @@ const addOptionalProviders = (options) => {
2726
2734
  useClass: options.routingConfigService,
2727
2735
  });
2728
2736
  }
2737
+ providers.push({
2738
+ provide: NAVIGATION_REDIRECT_STRATEGY_INJECTION_TOKEN,
2739
+ useClass: options.navigationRedirectStrategy || DefaultNavigationRedirectStrategy,
2740
+ });
2729
2741
  return providers;
2730
2742
  };
2731
2743
 
@@ -2737,5 +2749,5 @@ const addOptionalProviders = (options) => {
2737
2749
  * Generated bundle index. Do not edit.
2738
2750
  */
2739
2751
 
2740
- export { AppSwitcherConfigServiceImpl, AuthConfigService, AuthEvent, AuthService, ConfigService, CustomMessageListenersService, CustomReuseStrategy, DefaultUserProfileConfigService, ERROR_COMPONENT_CONFIG, EntityType, EnvConfigService, GlobalContextConfigService, HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN, HeaderBarService, I18nService, IframeService, LOCAL_CONFIGURATION_SERVICE_INJECTION_TOKEN, LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN, LUIGI_BREADCRUMB_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN, LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN, LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN, LUIGI_EXTENDED_GLOBAL_CONTEXT_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_NODES_CUSTOM_GLOBAL_SERVICE_INJECTION_TOKEN, LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN, LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN, LocalConfigurationServiceImpl, LocalNodesService, LocalStorageKeys, LoginEventService, LoginEventType, LuigiCoreService, LuigiNodesService, NetworkVisibility, NodeContextProcessingServiceImpl, NodeUtilsService, PortalComponent, RequestHeadersService, RoutingConfigServiceImpl, SessionRefreshService, StaticSettingsConfigServiceImpl, THEMING_SERVICE, UserSettingsConfigService, featureToggleLocalStorage, localDevelopmentSettingsLocalStorage, matchesJMESPath, providePortal, userSettingsLocalStorage };
2752
+ export { AppSwitcherConfigServiceImpl, AuthConfigService, AuthEvent, AuthService, ConfigService, CustomMessageListenersService, CustomReuseStrategy, DefaultNavigationRedirectStrategy, DefaultUserProfileConfigService, ERROR_COMPONENT_CONFIG, EntityType, EnvConfigService, GlobalContextConfigService, HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN, HeaderBarService, I18nService, IframeService, LOCAL_CONFIGURATION_SERVICE_INJECTION_TOKEN, LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN, LUIGI_BREADCRUMB_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN, LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN, LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN, LUIGI_EXTENDED_GLOBAL_CONTEXT_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_NODES_CUSTOM_GLOBAL_SERVICE_INJECTION_TOKEN, LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN, LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN, LocalConfigurationServiceImpl, LocalNodesService, LocalStorageKeys, LoginEventService, LoginEventType, LuigiCoreService, LuigiNodesService, NAVIGATION_REDIRECT_STRATEGY_INJECTION_TOKEN, NetworkVisibility, NodeContextProcessingServiceImpl, NodeUtilsService, PortalComponent, RequestHeadersService, RoutingConfigServiceImpl, SessionRefreshService, StaticSettingsConfigServiceImpl, THEMING_SERVICE, UserSettingsConfigService, featureToggleLocalStorage, localDevelopmentSettingsLocalStorage, matchesJMESPath, providePortal, userSettingsLocalStorage };
2741
2753
  //# sourceMappingURL=openmfp-portal-ui-lib.mjs.map