import { isArray, isPlainObject } from 'lodash'; import { ApplicationScope } from '../../types/application/index.js'; import { NotificationPosition } from './notification.js'; import { WidgetTypes } from './widget.js'; export type SelectedStateVarProps = { id: string; name: string; scope?: ApplicationScope; }; export type SelectedEventProps = { id: string; name: string; scope?: ApplicationScope; }; type SelectedWidgetProps = { id: string; name: string; type: WidgetTypes; }; type SelectedTimerProps = { id: string; name: string; scope: ApplicationScope; }; // Saved in the DSL. Not the same strings as what gets used in the runtime export enum TriggerStepType { RUN_JS = 'runJs', RUN_APIS = 'executeApi', CANCEL_APIS = 'cancelApi', NAVIGATE_TO = 'navigateTo', NAVIGATE_TO_APP = 'navigateToApp', NAVIGATE_TO_ROUTE = 'navigateToRoute', SET_QUERY_PARAMS = 'setQueryParams', CONTROL_SLIDEOUT = 'controlSlideout', CONTROL_MODAL = 'controlModal', CONTROL_TIMER = 'controlTimer', RESET_COMPONENT = 'resetComponent', RESET_STATE_VAR = 'resetStateVar', SET_STATE_VAR = 'setStateVar', SET_COMPONENT_PROPERTY = 'setComponentProperty', SHOW_ALERT = 'showAlert', SET_PROFILE = 'setProfile', TRIGGER_EVENT = 'triggerEvent', RUN_SUPERBLOCKS_OPTIMIZED_APIS = 'optimizedPageLoadApis' } // react-toastify type options type TypeOptions = 'info' | 'success' | 'warning' | 'error' | 'default'; export type ValidStepDef = | { id: string; type: TriggerStepType.RUN_APIS; apiNames: string[]; onSuccess: MultiStepDef; onError: MultiStepDef; } | { id: string; type: TriggerStepType.RUN_SUPERBLOCKS_OPTIMIZED_APIS; } | { id: string; type: TriggerStepType.CANCEL_APIS; apiNames: string[]; onCancel?: MultiStepDef; } | { id: string; type: TriggerStepType.RUN_JS; code?: string; } | { id: string; type: TriggerStepType.NAVIGATE_TO; url: string; newWindow: boolean; replaceHistory?: boolean; // TODO: This is currently unused, needs to be added to the form arguments: string; } | { id: string; type: TriggerStepType.NAVIGATE_TO_APP; targetApp: { name: string; id: string; // TODO: this url can change overtime (if default page is changed) but getting it dynamiclly on navigate might take extra time // Ideally, we should be able to redirect to url with only applicatoinId to app with default page url: string; }; queryParams: string; // this string is parsed at execution time newWindowApp: boolean; } | { id: string; type: TriggerStepType.NAVIGATE_TO_ROUTE; routeId: string; // only used to tell the user there might be an error (i.e. deleted routed), you never want to use this for routing routePathDescriptor: string; routeParams?: Record; queryParams?: string; // parsed at execution keepQueryParams?: boolean; newWindow: boolean; } | { id: string; // we use URL_PARAMS as our identifier because it might include more than query params in the future type: TriggerStepType.SET_QUERY_PARAMS; queryParams?: string; // parsed at execution keepQueryParams?: boolean; } | { id: string; type: TriggerStepType.CONTROL_SLIDEOUT; name: string; direction: 'open' | 'close'; } | { id: string; type: TriggerStepType.CONTROL_MODAL; name: string; direction: 'open' | 'close'; } | { id: string; type: TriggerStepType.CONTROL_TIMER; name: string; command: 'start' | 'stop' | 'toggle'; // optional, because timers without state are pre-AppScope and are defaulted to Page scope state?: SelectedTimerProps; } | { id: string; type: TriggerStepType.SET_STATE_VAR; state: SelectedStateVarProps; // TODO: this should be optional value: string; // TODO: this should be optional } | { id: string; type: TriggerStepType.RESET_STATE_VAR; state: SelectedStateVarProps; // TODO: this should be optional } | { id: string; type: TriggerStepType.RESET_COMPONENT; widget: SelectedWidgetProps; propertyName: string; resetChildren: boolean; } | { id: string; type: TriggerStepType.SHOW_ALERT; message: string; style: TypeOptions; alertDuration?: number; alertPosition?: NotificationPosition; } | { id: string; type: TriggerStepType.SET_COMPONENT_PROPERTY; widget: SelectedWidgetProps; propertyName: string; propertyValue: string; } | { id: string; type: TriggerStepType.SET_PROFILE; profileId: string; profileAction: 'set' | 'unset'; } | { id: string; type: TriggerStepType.TRIGGER_EVENT; event: SelectedEventProps; eventPayload: Record; // map of argument id to value }; export type StepDef = | { id: string; } | ValidStepDef; export type MultiStepDef = StepDef[]; export type ValidMultiStepDef = ValidStepDef[]; export type EventArg = { id: string; name: string; }; export type EventDefinition = { id: string; name: string; arguments: EventArg[]; onTrigger: MultiStepDef; }; export type EventDefinitionLoose = Omit & { // on FE, we are not cleaning irrelavant fields when switching action type, so using unknown to avoid schema check failure onTrigger: unknown[]; }; export function isValidStepDef(step: unknown): step is ValidStepDef { if (isPlainObject(step)) { return 'type' in (step as Record); } return false; } export function isValidMultiStepDef(steps: unknown[]): steps is ValidMultiStepDef { if (isArray(steps)) { return steps.every(isValidStepDef); } return false; }