File

libs/pfe-connector/src/lib/frame/page-action-status.ts

Index

Properties

Properties

pendingTasksInjector (Optional)
Type Injector
Description

When set, the next page lookup counts as a pending task of this injector, so a server render waits for it before serializing.

import {
  PageNavigationConfiguration,
  PfeBusinessService,
  PfeConfigurationService,
  PfeNavigationService,
  PfeServiceActivatorService
} from '@allianz/ngx-pfe';
import { CustomAction, TalyPageDataService } from '@allianz/taly-core';
import { BackLinkUtilsService } from '@allianz/taly-core/web-components';
import { Injector } from '@angular/core';
import { pendingUntilEvent } from '@angular/core/rxjs-interop';
import { Observable, combineLatest, from, of } from 'rxjs';
import { filter, map, mergeMap } from 'rxjs/operators';

export interface PageActionStatusOptions {
  /**
   * When set, the next page lookup counts as a pending task of this injector, so a server render
   * waits for it before serializing.
   */
  pendingTasksInjector?: Injector;
}

export function createPageActionStatusObservable(
  pfeServiceActivatorService: PfeServiceActivatorService,
  pfeNavigationService: PfeNavigationService,
  pfeConfigurationService: PfeConfigurationService,
  pfeBusinessService: PfeBusinessService,
  backLinkUtilsService: BackLinkUtilsService,
  talyPageDataService: TalyPageDataService,
  nextButtonDisabledWhenPageInvalid: boolean,
  options?: PageActionStatusOptions
) {
  const navOrServiceActivatorInProgress$ = createNavOrServiceActivatorInProgressObservable(
    pfeServiceActivatorService,
    pfeNavigationService
  );

  const currentPageData$ = talyPageDataService.pageData$;

  // Back button should be disabled if Navigation|Service_Activator is in progress
  const disableBack$ = navOrServiceActivatorInProgress$;

  // Next button should be enabled by default, but be disabled if nextButtonDisabledWhenPageInvalid set to true and the page is invalid
  const disableNext$ = nextButtonDisabledWhenPageInvalid
    ? combineLatest([pfeNavigationService.pageStatus$, navOrServiceActivatorInProgress$]).pipe(
        map(([isPageValid, inProgress]) => {
          return !isPageValid || inProgress;
        })
      )
    : navOrServiceActivatorInProgress$;

  const lastPageObservable$: Observable<boolean> = createLastPageObservable(
    pfeBusinessService,
    pfeNavigationService,
    pfeConfigurationService,
    options
  );

  return combineLatest([disableBack$, disableNext$, lastPageObservable$, currentPageData$]).pipe(
    map(([disableBack, disableNext, isLastPage, currentPageData]) => {
      const backLinkFeatureActiveForActions: boolean =
        backLinkUtilsService.isBackLinkFeatureActiveForActions(isLastPage);
      const customActions = currentPageData.pageActionConfig?.extraActions?.filter(
        (extraAction) => typeof extraAction === 'object' && Boolean(extraAction?.label)
      ) as CustomAction[];

      return {
        backDisabled: disableBack,
        nextDisabled: disableNext,
        nextHidden: backLinkFeatureActiveForActions
          ? false
          : currentPageData.pageActionConfig?.nextButtonHidden ?? false,
        backHidden: currentPageData.pageActionConfig?.backButtonHidden ?? false,
        backButtonUseTertiaryStyle:
          currentPageData.pageActionConfig?.backButtonUseTertiaryStyle ?? false,
        showSaveOfferButton: Boolean(
          currentPageData.pageActionConfig?.extraActions?.includes('SAVE_OFFER') ?? false
        ),
        showCancelButton: Boolean(
          currentPageData.pageActionConfig?.extraActions?.includes('CANCEL_OPERATION') ?? false
        ),
        customActions: customActions ?? [],
        isLastPage
      };
    })
  );
}

function createLastPageObservable(
  pfeBusinessService: PfeBusinessService,
  pfeNavigationService: PfeNavigationService,
  pfeConfigurationService: PfeConfigurationService,
  options?: PageActionStatusOptions
): Observable<boolean> {
  const pendingTasksInjector = options?.pendingTasksInjector;
  // Angular does not track these promises, so without a pending task the server could serialize the page before the lookup emits and render the wrong Back button
  const fromLookup = <T>(lookup: Promise<T>): Observable<T> =>
    pendingTasksInjector
      ? from(lookup).pipe(pendingUntilEvent(pendingTasksInjector))
      : from(lookup);

  return pfeNavigationService.currentPageId$.pipe(
    filter((pageId: string | undefined): pageId is string => Boolean(pageId)),
    mergeMap((pageId: string) => {
      return fromLookup(pfeConfigurationService.getPageNavigationConfiguration(pageId));
    }),
    mergeMap((currentPageNavConfig: PageNavigationConfiguration | undefined) => {
      if (!currentPageNavConfig) return of(false);

      return fromLookup(pfeBusinessService.getNextPage(currentPageNavConfig));
    }),
    map((pageId) => !pageId)
  );
}

export function createNavOrServiceActivatorInProgressObservable(
  pfeServiceActivatorService: PfeServiceActivatorService,
  pfeNavigationService: PfeNavigationService
): Observable<boolean> {
  return combineLatest([
    pfeServiceActivatorService.serviceActivatorCallInProgress$,
    pfeNavigationService.navigationInProgress$
  ]).pipe(
    map(([serviceActivator, navigation]) => {
      return serviceActivator || navigation;
    })
  );
}

results matching ""

    No results matching ""