File

libs/ngx-pfe/models/navigation-config.model.ts

Description

Defines the UrlParametersInState to save url parameter value to state.

Index

Properties

Properties

key
key: string
Type : string
stateKeyExpression
stateKeyExpression: JsonPathExpression
Type : JsonPathExpression
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;
}

results matching ""

    No results matching ""