libs/ngx-pfe/models/navigation-config.model.ts
Configuration for a service activator to be called.
[id: string]:
|
import { Conditions } from '../pfe-conditions/public-api';
import { NavServiceActivatorConfig, NavServiceActivatorConfigsArray } from '../pfe-service-activator/service/service-activator.model';
import { PfeActionConfig } from './../pfe-actions/pfe-actions.model';
import { JsonPathExpression } from './jsonpath-expression-type.model';
import { NavOptionErrorPageConfig } from './navigation-config-error-page.model';
/**
* Unique ID of a page.
*/
export type PageId = string;
/**
* Enum of meta keys that can be used to do specific navigations to other sections of navigation config
*/
export enum META_KEYS {
FIRST_PAGE = 'FIRST_PAGE',
}
export interface MetaNav {
metaNavId: META_KEYS;
}
export enum NavigationType {
FORWARD = 'FORWARD',
BACKWARD = 'BACKWARD',
}
/**
* Configuration for a service activator to be called.
*/
export interface GlobalServiceActivators<ACTIONS = PfeActionConfig> {
[id: string]: NavServiceActivatorConfig<ACTIONS>;
}
/**
* The PfeNavigationConfiguration contains all configuration values that are required for
* the navigation between different pages in a flow.
* The execution flow is as follows:
*
* 1. Execute service activators
* 2. Retrieve result and store to state
* 3. Execute navigation conditions
*
*/
export interface PfeNavigationConfiguration<ACTIONS = PfeActionConfig> {
/**
* The id to be displayed when a non recoverable error occurs.
*
* An example for such an error is a failed service activator call.
* It is possible to exclude certain http status codes from the automatic error handling with the
* serviceActivatorErrorHandlingExcludeStatusCodes configuration in the application config.
*
* @deprecated true
* @deprecationMessage Use the errorPageNavigation instead.
*/
errorPageID?: string;
/**
* Determines the error page to be displayed.
* Allows it to evaluate navigation options. Additionally to the state, the full response object is available under the key "$.response"
* For example the status response code can be accessed like this: "$.response.status"
*
* The state is available under the key "$.state"
*/
errorPageNavigation?: NavOptionErrorPageConfig[];
/**
* First page configuration.
* It can be either a pageId (as string) or a first page configuration with their next options.
*/
firstPage?: string | FirstPageConfiguration<ACTIONS>;
/**
* The collection of the navigation configuration for all pages of a flow.
*/
pages: PageNavigationConfiguration<ACTIONS>[];
/**
* Global service activators configuration registry. The service activators here can be triggered by their
* ID in the navigation page configuration.
* This makes it possible to trigger the same service activator on multiple navigations.
* It is also possible to overwrite some of the attributes in the page navigations.
*
* Example:
*
* "serviceActivators": {
* "IDofThisServiceActivator": {
* "path": "customerInformation",
* "responseDataMapping": [
* {
* "responseDataExpression": "$",
* "stateKeyExpression": "$.saveResponseHere"
* }
* ]
* }
* }
*/
serviceActivators?: GlobalServiceActivators<ACTIONS>;
}
export type PageNavigationConfiguration<ACTIONS = PfeActionConfig> =
| RegularPageNavigationConfiguration<ACTIONS>
| NavigationNodeConfiguration<ACTIONS>;
/**
* # Navigation configuration
*
* The navigation configuration determines the next page to be shown, dependent on values in the state.
*
* Each next page can have a number of conditions. These conditions are connected with AND,
* which means, all of them have to evaluate to true for the page to be shown.
*
* The navigation options are checked in the order, as they are defined in the configuration.
* This means, if the conditions of the first option evaluates to true, the navigation is started
* immediately, the other options are not checked anymore.
*
*/
interface RegularPageNavigationConfiguration<ACTIONS = PfeActionConfig> {
/**
* The pageID is a unique ID of a page throughout the whole configuration.
* In the navigation it references pages from the page configuration.
*/
pageId: PageId;
/**
* The pageConfigIdReference allows it to map a navigation config to a different pageConfig than the pageID.
* This makes it possible, to reuse the same pageConfig multiple times in the navigation. (1 pageConfig -> n navigationConfigs)
*
* If there is also a pageConfig with the pageId of this navigation config, a deep merge is done on top of the pageConfigIdReference.
* This makes it possible, to overwrite certain parts of the referenced page config.
* By default, arrays are replaced. If a concat should be done instead, the pageConfigIdReferenceDeepMergeArrays flag can be used.
*/
pageConfigIdReference?: PageId;
/**
* Used in combination with pageConfigIdReference. Do not overwrite arrays, but concat them.
*/
pageConfigIdReferenceDeepMergeArrays?: boolean;
/**
* Flag that sequentially executes all the service activators configured in the page.
*
* Should not be used anymore. Instead use the TRIGGER_SERVICE_ACTIVATORS action with the executeServiceActivatorsSequential flag.
*
* @deprecated true
* @deprecationMessage Use "executeServiceActivatorsSequential" inside "onPageEnterActions"
*/
executeServiceActivatorsSync?: boolean;
/**
* Service activators to be called, when a page is opened.
*/
onPageEnterServiceActivators?: NavServiceActivatorConfigsArray<ACTIONS>;
/**
* Service activators to be called, when a user leaves the current page. (=click on the next button)
*/
onPageLeaveServiceActivators?: NavServiceActivatorConfigsArray<ACTIONS>;
/**
* Service activators to be called, when a user click in some button on the current page.
*
* Example of how add a new serviceActivator call called "getCustomerInformation":
*
* "serviceActivators": {
* "getCustomerInformation": {
* "path": "customerInformation",
* "serviceActivatorMethod": "GET",
* "requestDataMapping": [
* {
* "stateKeyExpression": "$.documentId",
* "requestDataExpression": "$.documentId"
* }
* ],
* "responseDataMapping": [
* {
* "responseDataExpression": "$",
* "stateKeyExpression": "$.saveResponseHere"
* }
* ]
* }
* }
*/
serviceActivators?: {
[key: string]: NavServiceActivatorConfig<ACTIONS>;
};
/**
* The list of possible next pages in the navigation flow.
*/
nextOptionList?: NavOptionConfig[];
/**
* The list of possible previous pages in the navigation flow.
*
* If the backOptionList is not set, the automatically remembered history of the visited pages
* will be used for the back navigation.
* An empty backOptionList ([]) will prevent a back navigation.
*/
backOptionList?: NavOptionConfig[];
/**
* Do not add this page to the history of navigated pages.
*/
omitFromHistory?: boolean;
/**
* If this attribute is set to true, the remote state storage will
* be shutdown when this page is entered.
* This means the latest state will not be updated anymore.
*/
shutdownStateStorage?: boolean;
/**
* Allows the user to directly navigate this page within the flow
* without a restored state.
* Default is false, which means the user gets redirected to the first page, if no state
* was restored.
*/
allowDirectNavigationWithoutState?: boolean;
/**
* By default when restoring the state it will navigate to the last visited page. If false
* then it will navigate to the page passed in the fragment of url.
* ex: allianz.com/blabla#navigateToThisPage
*/
navigateToLastVisitedPage?: boolean;
/**
* set to true to remove pages that have been visited
* multiple nextOptionList pages that stores value to the state
*/
removePageFromState?: boolean;
/**
* A list of actions of the page,
* the actions are executed sequentially before the user enters the page
*
* They can use conditions to determine if they should be executed or not.
* The following information is available for this in the state:
* $._pfe.navigationState.navigatingTo
* $._pfe.navigationState.navigatingFrom
*/
onPageEnterActions?: ACTIONS[];
/**
* A list of actions of the page,
* the actions are executed sequentially before the user leaves the page in forward direction in the flow.
*/
onPageLeaveActions?: ACTIONS[];
/**
* Actions that are executed when the navigation of one page to another one is started.
* They can use conditions to determine if they should be executed or not.
*
* The following information is available for this in the state:
* $._pfe.navigationState.navigatingTo
* $._pfe.navigationState.navigatingFrom
*/
onNavigationStartActions?: ACTIONS[];
/**
* A list of actions of the page,
* the actions are executed sequentially before the user leaves the page in a backward direction in the flow.
*/
onPageLeaveBackwardsActions?: ACTIONS[];
}
interface NavigationNodeConfiguration<ACTIONS = PfeActionConfig> extends RegularPageNavigationConfiguration<ACTIONS> {
/**
* Setting the navigationNode flag, turns this page into a pure navigation node.
*
* This means the page is not attached to a pageType (=invisible). Instead navigating to it, immediately triggers another navigation.
* This makes it possible to use a navigationNode as a decision gateway that navigates to another page, based on certain conditions.
*
* Navigation nodes are not added to the history of visited pages, that means navigating backwards after a navigation node
* leads to the page that triggered the original navigation to the navigation node.
* A backwards navigation from within a navigationNode is therefore also not possible.
*
* When a page is turned into a navigation node, it cannot be used together with the pageConfigIdReference, pageConfigIdReferenceDeepMergeArrays,
* backOptionList, onPageLeaveActions and onPageLeaveBackwardsActions attributes.
*
* omitFromHistory will be activated automatically.
*/
navigationNode: boolean;
pageConfigIdReference?: never;
pageConfigIdReferenceDeepMergeArrays?: never;
backOptionList?: never;
onPageLeaveActions: never;
onPageLeaveBackwardsActions: never;
}
export function isNavigationNode(
pageConfig?: RegularPageNavigationConfiguration<unknown> | NavigationNodeConfiguration<unknown>
): pageConfig is NavigationNodeConfiguration {
return (pageConfig as NavigationNodeConfiguration)?.navigationNode !== undefined;
}
/**
* First page configurations which includes a list of possible first pages.
*
*/
export interface FirstPageConfiguration<ACTIONS = PfeActionConfig> {
/**
* ServiceActivators that are executed before the first page evaluation is done.
* The navigation to the first page can use the response data.
* @deprecated true
* @deprecationMessage Use "onEnterActions"
*/
onEnterServiceActivators?: NavServiceActivatorConfigsArray<ACTIONS>;
/**
* A list of actions to be executed before navigate to the
* first page.
*/
onEnterActions?: ACTIONS[];
/**
* The list of possible first pages.
*/
nextOptionList: NavOptionConfig[];
}
export interface NavOptionConfig {
/**
* The ID of the next page to be displayed, if the conditions evaluate to true.
* The ID is a reference to the page configuration.
*
* The nextPageId can also be a jsonPath expression, that will be resolved during navigation.
*/
nextPageId?: string;
/**
* # ExpressionCondition Syntax
*
* The navigation conditions use jsonPath (https://github.com/dchester/jsonpath) expressions to select data from the state.
* There is tooling support available to create and test jsonpath expression.
* The PFE dev tools also contain a possibility to test and debug expressions against a JSON.
*
* The conditions to be evaluated can either be an array of {@link Condition} or an {@link ConditionAdvanced} object.
*
* They are an optional attribute. If they are omitted, the result of true is assumed.
*
* The selected data can then be compared with certain operators to a second value or a literal.
*
* Possible operators are
*
* ```
* ==
* ```
* Checks if the two values are equal.
*
* ```
* !=
* ```
* Checks that the two values are not equal.
*
* ```
* < and >
* ```
* Compares the numerical value, to check if one of them is larger or
* smaller than the other one.
*
* The jsonpath syntax has the following basic format:
*
* ```
* $.<attribute or expression>
* ```
*
* For example:
*
* ```
* $.myCustomTextAreaID
* ```
*
* Keys, that contain special characters can be accessed in the following way:
*
* ```
* $['some-attribute-name']
* ```
*
* Example configuration.
*
* This example also shows, how jsonpath expressions can be used, to extract data from arrays.
*
* ```json
* {
* "pageId": "damage-type-selection",
* "nextOptionList": [
* {
* "nextPageId": "page-type-overview",
* "conditions": [
* {
* "value1Expression":
* "$.damageTypeButtons..[?(@ == 'pageTypeOverview')]"
* }
* ]
* },
* {
* "nextPageId": "settlement-option",
* "conditions": [
* {
* "value1Expression": "$.damageTypeButtons..[?(@ == 'WATER_DAMAGE')]"
* }
* ]
* },
* {
* "nextPageId": "other-page",
* "conditions": {
* "operator": "AND",
* "conditions": [
* {
* "value1Expression": "$.damageTypeButtons..[?(@ == 'PARK_DAMAGE')]"
* }
* ]
* }
* }
* ]
* }
* ```
*/
conditions?: Conditions;
/**
* Navigation to an external url:
*
* Also it is possible to specify an external url as the next page based on a specific condition.
*
* In this case the configuration will be:
*
* - nextPageId : <External url> It is possible, to use JSON Path expressions within the URL using {} and inside the expression
* - external: true
*
* ```json
* [
* {
* "pageId": "lastpage",
* "nextOptionList": [
* {
* "nextPageId": "https://www.google.es?someValue={$.aaa.bbb}",
* "external": true
* }
* ]
* }
* ]
* ```
*
* Its also possible to use a more complex parse of the params on the URL @see ExternalNavigationPathParams but both
* options are not compatible.
*/
external?: boolean;
/**
* Allow to handle all the navigation path params that are provided when
* its an external navigation.
* You can use this in 2 different ways, that can be mixed together, in the following examples
* the final URL its the same.
* ```json
* [
* {
* "pageId": "lastpage",
* "nextOptionList": [
* {
* "nextPageId": "/account/?contractId={contractId}",
* "external": true,
* "externalNavigationPathParams": [
* {
* "id": "contractId",
* "value": "$.policy.contractId"
* }
* ]
* }
* ]
* }
* ]
* ```
* ```json
* [
* {
* "pageId": "lastpage",
* "nextOptionList": [
* {
* "nextPageId": "/account/?",
* "external": true,
* "externalNavigationPathParams": [
* {
* "name": "contractId",
* "value": "$.policy.contractId"
* }
* ]
* }
* ]
* }
* ]
* ```
*/
externalNavigationPathParams?: ExternalNavigationPathParams[];
/**
* Propagate forward specified path params from the current route to external navigation.
* If a path param is not found, it will be ignored.
*
* ```json
* [
* {
* "pageId": "lastpage",
* "nextOptionList": [
* {
* "nextPageId": "/account/",
* "external": true,
* "externalPathParamPropagations": ["startImpersonation"]
* }
* ]
* }
* ]
* ```
*
* It is not possible to use JSON Path expressions within the URL if this option is in use.
* Define them with externalNavigationPathParams instead.
*/
externalPathParamPropagations?: string[];
/**
* List of possibles userInputState updates
*/
updateStateValues?: StateUpdates[];
/**
* The meta navigation for the next page to be displayed, if the conditions evaluate to true.
* This meta navigation is a group of navigations that appear in the navigation.json. (f.e first page nav)
*
*/
metaNavigation?: MetaNav;
}
export interface ExternalNavigationPathParams {
/** The name of the param, for example "contractNumber" */
name?: string;
/** The value in the URL for example {contractNumber} */
id?: string;
/** The value of the param, it can be a JsonPathExpression or just a value */
value: string;
/** A list of conditions to add that param */
conditions?: Conditions;
}
/**
* This interface define the content of a state update
*/
export interface StateUpdates {
/**
* Key or id of the element to be modified in the state
*/
key: JsonPathExpression;
/**
* Value to be added, replace, update or copy an existing inputState item
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value?: any | JsonPathExpression;
/**
* Possible operations to be apply
*/
operation?: StateOperations;
/**
* List of conditions that identify in which case we want to do this update.
* In case of not define this list we will apply the update directly
*/
conditions?: Conditions;
}
/**
* State operation through different variables
*/
export enum StateOperations {
REMOVE = 'remove',
PUSH = 'push',
DECREASE = 'decrease',
INCREASE = 'increase',
/** Joins the "key" using the "value" as a join operator */
JOIN = 'join',
}
/**
* Defines the serviceActivators to be triggered while doing so manually.
*/
export enum ServiceActivatorHook {
'ENTER' = 0,
'LEAVE' = 1,
}
/**
* Defines the UrlParametersInState to save url parameter value to state.
*/
export interface UrlParametersInState {
key: string;
stateKeyExpression: JsonPathExpression;
}