@wolkabout/commons 0.0.50 → 0.0.51

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.
@@ -66,7 +66,7 @@ import * as i32 from '@angular/cdk/drag-drop';
66
66
  import { DragDropModule } from '@angular/cdk/drag-drop';
67
67
  import * as i0 from '@angular/core';
68
68
  import { NgModule, InjectionToken, inject, Injectable, DOCUMENT, Inject, Input, Directive, forwardRef, HostListener, TemplateRef, PLATFORM_ID, Pipe, ViewChild, ContentChild, Optional, Self, Component, input, computed, untracked, signal, viewChild, afterNextRender, effect, output, afterRenderEffect, contentChild } from '@angular/core';
69
- import { BehaviorSubject, catchError, of, switchMap, EMPTY, tap, filter, map, combineLatestWith, forkJoin, from, distinctUntilChanged, shareReplay, merge, Subject, takeUntil, combineLatest, take, first } from 'rxjs';
69
+ import { BehaviorSubject, catchError, of, switchMap, EMPTY, tap, filter, map, combineLatestWith, take, from, concatMap, first, forkJoin, distinctUntilChanged, shareReplay, merge, Subject, takeUntil, combineLatest } from 'rxjs';
70
70
  import { jwtDecode } from 'jwt-decode';
71
71
  import { loadRemoteModule } from '@angular-architects/native-federation';
72
72
  import * as i1$3 from '@angular/platform-browser';
@@ -460,38 +460,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
460
460
  }]
461
461
  }] });
462
462
 
463
- const createGlobalPermissionsGuard = (fallbackRoute) => {
464
- let checkedRoutes = [];
465
- const permissionsGuard = (permissions) => (route) => {
466
- const router = inject(Router);
467
- const permissionService = inject(PermissionsService);
468
- const permissionsToCheck = Array.isArray(permissions) ? permissions : [permissions];
469
- return permissionService.hasAnyPermission(permissionsToCheck).pipe(map((hasPermissions) => {
470
- if (hasPermissions) {
471
- checkedRoutes = [];
472
- return true;
473
- }
474
- const currentPath = route.routeConfig?.path;
475
- if (!currentPath) {
476
- checkedRoutes = [];
477
- return router.createUrlTree(fallbackRoute);
463
+ /**
464
+ * Returns 'true' if the route is accessible,
465
+ * Returns the first available route if the requested route is NOT accessible
466
+ * Returns the fallback route if there are no routes accessible.
467
+ *
468
+ * Define "requiredPermissions" in the route data section.
469
+ * The permissions are checked globally, and the result will match if ANY permission is present.
470
+ */
471
+ const globalPermissionGuard = (route) => {
472
+ const router = inject(Router);
473
+ const permissionService = inject(PermissionsService);
474
+ return isAccessible(permissionService, route.data['requiredPermissions'] ?? []).pipe(take(1), switchMap((accessible) => {
475
+ if (accessible) {
476
+ return of(true);
477
+ }
478
+ else {
479
+ return findFirstAvailableRoute(route, permissionService).pipe(map((firstAvailableRoute) => {
480
+ return firstAvailableRoute ? router.createUrlTree(firstAvailableRoute) : false;
481
+ }));
482
+ }
483
+ }));
484
+ };
485
+ /**
486
+ * Checks the requiredPermissions data property of the route is present and checks the access through the permission service.
487
+ * The route is accessible if the user has ANY of the required permissions.
488
+ */
489
+ function isAccessible(permissionService, requiredPermissions) {
490
+ if (requiredPermissions.length === 0) {
491
+ return of(true);
492
+ }
493
+ return permissionService.hasAnyPermission(requiredPermissions);
494
+ }
495
+ /**
496
+ * If any of the sibling routes is accessible, returns the first defined sibling.
497
+ * If no sibling route is accessible, checks the parent route and its sibling accessibility.
498
+ * This repeats until an accessible route is found, or every route was tested.
499
+ * If no accessible route is found, returns null;
500
+ */
501
+ function findFirstAvailableRoute(currentRoute, permissionService) {
502
+ function inspectChildren(route, excludedRoute) {
503
+ const children = (route.routeConfig?.children ?? []).filter(child => child.path && child.path !== '**' && child !== excludedRoute);
504
+ if (children.length === 0) {
505
+ return of(null);
506
+ }
507
+ const parentPath = getFullPath(route);
508
+ return from(children).pipe(concatMap(child => isAccessible(permissionService, child.data ? child.data['requiredPermissions'] : []).pipe(take(1), map(accessible => accessible ? [...parentPath, child.path] : null))), first(result => result !== null, null));
509
+ }
510
+ /**
511
+ * Inspects the route for the available routes. The excludedRoute is the one we traversed from.
512
+ * If an accessible child is found, the child will be selected.
513
+ * If no accessible children are found, the parent will be inspected, and process continues...
514
+ */
515
+ function inspectNode(route, excludedRoute) {
516
+ return inspectChildren(route, excludedRoute).pipe(switchMap(result => {
517
+ if (result !== null) {
518
+ return of(result);
478
519
  }
479
- checkedRoutes.push(currentPath);
480
- const siblings = route.parent?.routeConfig?.children?.filter((route) => !!route.path && route.path !== '**' && !checkedRoutes.includes(route.path)) ?? [];
481
- const parentUrl = route.parent?.pathFromRoot
482
- .flatMap((route) => route.url)
483
- .map((url) => url.path)
484
- .filter(Boolean) ?? [];
485
- const nextRoute = siblings[0];
486
- if (nextRoute) {
487
- return router.createUrlTree([...parentUrl, nextRoute.path]);
520
+ if (!route.parent) {
521
+ return of(null);
488
522
  }
489
- checkedRoutes = [];
490
- return router.createUrlTree(fallbackRoute);
523
+ return inspectNode(route.parent, route.routeConfig);
491
524
  }));
492
- };
493
- return permissionsGuard;
494
- };
525
+ }
526
+ if (!currentRoute.parent) {
527
+ return of(null);
528
+ }
529
+ return inspectNode(currentRoute.parent, currentRoute.routeConfig);
530
+ }
531
+ function getFullPath(snapshot) {
532
+ return snapshot.pathFromRoot
533
+ .flatMap(route => route.url.map(segment => segment.path))
534
+ .filter(segment => segment.length > 0);
535
+ }
495
536
 
496
537
  class AssetManager {
497
538
  /**
@@ -7032,5 +7073,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
7032
7073
  * Generated bundle index. Do not edit.
7033
7074
  */
7034
7075
 
7035
- export { AUTHENTICATION_CLIENT, AssetManager, AuthenticationService, AutocompleteChipsComponent, AutocompleteComponent, BasicTimeSeriesGraphComponent, COLORS, CUSTOM_PERIOD, CardLabeledValueComponent, ConfirmationDialogComponent, DEFAULT_LOCALE, DEFAULT_TIMEZONES, DEFAULT_TIME_ZONE, DataType, DateRangeInputComponent, DateTimeFormFieldComponent, DragDropFileUploadComponent, DurationPipe, FeatureRegistry, GoogleMapComponent, ImageDisplayComponent, ImagePreviewComponent, LAST_ACTIVE_TAB_KEY, LOCALES, LabeledValueComponent, LoadedIconComponent, LoadingIndicatorDirective, LocalSortTableComponent, Locale, LocalizedNumberPipe, LocalizedNumericInputDirective, MILLISECONDS_IN_DAY, MapsLoaderService, MasterDetailsViewComponent, MessageTooltipDirective, MissingTranslationHelper, NestedListDataControl, NestedListDataSource, NestedListViewComponent, NgTemplateContentDirective, NotificationService, OverflowClassDirective, PdfViewerComponent, PeriodErrorStateMatcher, PermissionsService, RELATIVE_TIME_PERIODS, RelativeTimePeriod, RequiresAllGlobalOrAssetPermissionsDirective, RequiresAllPermissionDirective, RequiresGlobalOrAsserPermissionDirective, RequiresPermissionDirective, ScrollIntoViewDirective, SharedModule, SimpleDatePipe, SimpleDateTimePipe, SimpleTimePipe, SortPipe, StandardListDataControl, StandardListDataSource, StandardListViewComponent, TIMEZONES, TabulatedChipViewComponent, TabulatedViewComponent, TenantPropertiesService, ThemeService, TreeComponent, TreeNodeComponent, USERS_TIME_ZONE, ValueDisplayComponent, ValueInputBooleanComponent, ValueInputColorComponent, ValueInputComponent, ValueInputDateComponent, ValueInputDurationComponent, ValueInputEnumComponent, ValueInputHexadecimalComponent, ValueInputLinkComponent, ValueInputLocationComponent, ValueInputNumericComponent, ValueInputStringComponent, ValueInputVectorComponent, angularComponents, arrayToObject, chartThemeDark, chartThemeLight, createGlobalPermissionsGuard, daysAway, determineMagnitude, determineMinMaxValues, endOfPeriod, equalsByValue, fileSizeValidator, flatMap, flatten, format, formatDuration, generateRandomString, groupBy, hoursAway, isContextAccessible, lookUpPathPart, lookUpQueryParam, parseDateRangeInputPeriod, parseTimeInput, saveFile, scale, shared, startOfMonth, startOfPeriod, startOfTheDay, startOfWeek, startOfYear, toDate, toEndOfMonth, toEndOfYear, toJsDate, toOffset, toStartOfMonth, toStartOfTheDay, toStartOfWeek, toStartOfYear, toTime, uniqueBy, uniqueFrom, validateAssetName, validateTypeAssetName };
7076
+ export { AUTHENTICATION_CLIENT, AssetManager, AuthenticationService, AutocompleteChipsComponent, AutocompleteComponent, BasicTimeSeriesGraphComponent, COLORS, CUSTOM_PERIOD, CardLabeledValueComponent, ConfirmationDialogComponent, DEFAULT_LOCALE, DEFAULT_TIMEZONES, DEFAULT_TIME_ZONE, DataType, DateRangeInputComponent, DateTimeFormFieldComponent, DragDropFileUploadComponent, DurationPipe, FeatureRegistry, GoogleMapComponent, ImageDisplayComponent, ImagePreviewComponent, LAST_ACTIVE_TAB_KEY, LOCALES, LabeledValueComponent, LoadedIconComponent, LoadingIndicatorDirective, LocalSortTableComponent, Locale, LocalizedNumberPipe, LocalizedNumericInputDirective, MILLISECONDS_IN_DAY, MapsLoaderService, MasterDetailsViewComponent, MessageTooltipDirective, MissingTranslationHelper, NestedListDataControl, NestedListDataSource, NestedListViewComponent, NgTemplateContentDirective, NotificationService, OverflowClassDirective, PdfViewerComponent, PeriodErrorStateMatcher, PermissionsService, RELATIVE_TIME_PERIODS, RelativeTimePeriod, RequiresAllGlobalOrAssetPermissionsDirective, RequiresAllPermissionDirective, RequiresGlobalOrAsserPermissionDirective, RequiresPermissionDirective, ScrollIntoViewDirective, SharedModule, SimpleDatePipe, SimpleDateTimePipe, SimpleTimePipe, SortPipe, StandardListDataControl, StandardListDataSource, StandardListViewComponent, TIMEZONES, TabulatedChipViewComponent, TabulatedViewComponent, TenantPropertiesService, ThemeService, TreeComponent, TreeNodeComponent, USERS_TIME_ZONE, ValueDisplayComponent, ValueInputBooleanComponent, ValueInputColorComponent, ValueInputComponent, ValueInputDateComponent, ValueInputDurationComponent, ValueInputEnumComponent, ValueInputHexadecimalComponent, ValueInputLinkComponent, ValueInputLocationComponent, ValueInputNumericComponent, ValueInputStringComponent, ValueInputVectorComponent, angularComponents, arrayToObject, chartThemeDark, chartThemeLight, daysAway, determineMagnitude, determineMinMaxValues, endOfPeriod, equalsByValue, fileSizeValidator, flatMap, flatten, format, formatDuration, generateRandomString, globalPermissionGuard, groupBy, hoursAway, isContextAccessible, lookUpPathPart, lookUpQueryParam, parseDateRangeInputPeriod, parseTimeInput, saveFile, scale, shared, startOfMonth, startOfPeriod, startOfTheDay, startOfWeek, startOfYear, toDate, toEndOfMonth, toEndOfYear, toJsDate, toOffset, toStartOfMonth, toStartOfTheDay, toStartOfWeek, toStartOfYear, toTime, uniqueBy, uniqueFrom, validateAssetName, validateTypeAssetName };
7036
7077
  //# sourceMappingURL=wolkabout-commons.mjs.map