libs/pfe-connector/src/lib/frame/page-action-status.ts
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;
})
);
}