UNPKG

@cmk/fe_utils

Version:
328 lines (311 loc) 12.5 kB
import { EditorRendererControllerType, EditorStateType, Element, } from '../../editorRendererController' import { replacePlaceholdersInString } from '../placeholder/replacePlaceholder' import { queryAction } from './queryAction' import { toast } from 'react-hot-toast' type EditorRendererController = EditorRendererControllerType export const createAppAction = (params: { element: Element eventName: string editorState: EditorStateType currentViewportElements: EditorRendererController['currentViewportElements'] ELEMENT_MODELS: EditorRendererController['ELEMENT_MODELS'] appController: EditorRendererController['appController'] icons?: Record<string, string> navigate: (to: string) => void isProduction?: boolean // formData?: Record<string, any> }): ((...fnParams: unknown[]) => Promise<void>) | undefined => { const { element, editorState, currentViewportElements, ELEMENT_MODELS, appController, eventName, icons, navigate, isProduction, // formData, } = params const elementProps = editorState.properties?.filter( (prop) => prop.element_id === element.element_id ) const templateProps = editorState.properties?.filter( (prop) => prop.template_id === element.template_id && !elementProps.find((elprop) => elprop.prop_name === prop.prop_name) ) const allElementProps = [...(elementProps ?? []), ...(templateProps ?? [])] const getPropActionIdsByName = (key: string) => allElementProps?.find((prop) => prop.prop_name === key)?.action_ids ?? [] const actionIds = getPropActionIdsByName(eventName) // const eventProps = getPropByName(eventName) as string[] return !actionIds?.length ? undefined : async (...fnParams: unknown[]) => { console.debug('app action called', eventName, fnParams) // click actions are currently assosiacted with endpoint events only! // const actionIds: string[] = eventProps const navigationActionElements = actionIds .map( (actId) => currentViewportElements.find((el) => el.element_id === actId) ?? null ) .filter((el) => el) const navigationActionElementIds = navigationActionElements.map( (el) => el?.element_id ) as string[] for (let a = 0; a < actionIds.length; a++) { const actionId = actionIds[a] const endpointAction = editorState.actions.find( (act) => act.action_id === actionId ) const navigationAction = navigationActionElementIds.includes(actionId) const action = editorState.actions.find( (act) => act.action_id === actionId ) const isPageNavigation = action?.internal_action_name === 'navigatePage' if (!endpointAction && !navigationAction && !isPageNavigation) { console.warn( 'No ep and no nav -action found for actionId', actionId ) continue } // console.debug( // 'app action called WITH', // eventName, // fnParams, // isPageNavigation, // endpointAction, // navigationAction // ) if (isPageNavigation) { const actionsParmValue = editorState.action_params.find( (ap) => ap.param_name === 'navigatePage' && ap.element_id === element.element_id && actionId === ap.action_id )?.param_value const elementTemplateValuesDict = editorState.action_params .filter((ap) => ap.element_id === element.element_id) .reduce<Record<string, string>>((acc, cur) => { return { ...acc, [cur.param_name]: cur.param_value, } }, {}) const componentModel = ELEMENT_MODELS.find( (mod) => mod.type === element.element_type ) const isItemEvent = componentModel?.schema?.properties[eventName]?.eventType const elementTemplateValuesDictAdj = isItemEvent ? Object.keys(elementTemplateValuesDict).reduce< Record<string, string> >((acc, cur) => { const value = elementTemplateValuesDict?.[ cur as keyof typeof elementTemplateValuesDict ] const replaceValue = element.element_type === 'TreeView' ? (fnParams?.[1] as string) : (fnParams?.[0] as string) const newValue = typeof value === 'string' && ['string', 'number'].includes(typeof replaceValue) ? value?.replaceAll?.('{itemId}', replaceValue) : value const matches = typeof newValue === 'string' && newValue?.match?.( /{(_data|form|formData|props|treeviews|buttonStates)\.[^}]*}/g ) const newValueReplaced = matches ? replacePlaceholdersInString( newValue, appController.state, editorState.composite_component_props, editorState.properties, element, undefined, undefined, icons, undefined, componentModel?.renderType === 'form' ? (fnParams?.[1] as Record<string, unknown>) : undefined ) : newValue const regexOnlyNumbersOrDecimal = /^[0-9]+(\.[0-9]+)?$/ const isNumberOrDecimal = regexOnlyNumbersOrDecimal.test(newValueReplaced) const newValueAdj = isNumberOrDecimal ? parseFloat(newValueReplaced) : newValueReplaced return { ...acc, [cur]: newValueAdj, } }, {}) : elementTemplateValuesDict const actionsParmValueAdj = isItemEvent && elementTemplateValuesDictAdj?.['navigatePage'] ? elementTemplateValuesDictAdj?.['navigatePage'] : actionsParmValue if (!actionsParmValueAdj) { console.debug( 'actionsParmValueAdj for pageNavigation is not valid', actionsParmValueAdj ) return } if (isProduction) { console.debug( 'Navigate to page ...', actionsParmValue, actionsParmValueAdj, isProduction ) navigate('/' + actionsParmValueAdj) } else { console.warn( 'Navigate to page not implemented in dev mode, will navigate to ' + actionsParmValue, actionsParmValueAdj, isProduction ) toast.error( 'Navigate to page not implemented in dev mode, navigate to /' + actionsParmValueAdj ) } continue } else if (endpointAction) { const endpointId = endpointAction.endpoint_id const endpoint = editorState.externalApis .map((api) => api.endpoints.map((ep) => ({ ...ep, api_id: api.external_api_id, })) ) .flat() .find((ep) => ep.endpoint_id === endpointId) const api = editorState.externalApis.find( (api) => api.external_api_id === endpoint?.api_id ) const url = (api?.base_url || '') + (endpoint?.url || '') const action = editorState.actions.find( (act) => act.endpoint_id === endpoint?.endpoint_id ) const elementTemplateValuesDict = editorState.action_params .filter((ap) => ap.element_id === element.element_id) .reduce<Record<string, string>>((acc, cur) => { return { ...acc, [cur.param_name]: cur.param_value, } }, {}) const componentModel = ELEMENT_MODELS.find( (mod) => mod.type === element.element_type ) const isItemEvent = componentModel?.schema?.properties[eventName]?.eventType const elementTemplateValuesDictAdj = isItemEvent ? Object.keys(elementTemplateValuesDict).reduce< Record<string, string> >((acc, cur) => { const value = elementTemplateValuesDict?.[ cur as keyof typeof elementTemplateValuesDict ] const replaceValue = element.element_type === 'TreeView' ? (fnParams?.[1] as string) : (fnParams?.[0] as string) const newValue = typeof value === 'string' && ['string', 'number'].includes(typeof replaceValue) ? value?.replaceAll?.('{itemId}', replaceValue) : value const matches = typeof newValue === 'string' && newValue?.match?.( /{(_data|form|formData|props|treeviews|buttonStates)\.[^}]*}/g ) const newValueReplaced = matches ? replacePlaceholdersInString( newValue, appController.state, editorState.composite_component_props, editorState.properties, element, undefined, undefined, icons, undefined, componentModel?.renderType === 'form' ? (fnParams?.[1] as Record<string, unknown>) : undefined ) : newValue const regexOnlyNumbersOrDecimal = /^[0-9]+(\.[0-9]+)?$/ const isNumberOrDecimal = regexOnlyNumbersOrDecimal.test(newValueReplaced) const newValueAdj = isNumberOrDecimal ? parseFloat(newValueReplaced) : newValueReplaced return { ...acc, [cur]: newValueAdj, } }, {}) : elementTemplateValuesDict console.debug( 'elementTemplateValuesDictAdj', elementTemplateValuesDictAdj, isItemEvent, componentModel, eventName, componentModel?.schema?.properties[eventName], fnParams, ['string', 'number'].includes(typeof fnParams?.[1]), fnParams, elementTemplateValuesDict ) await queryAction( appController, action?.action_id ?? '', // should never happen -> should always have action endpoint?.method as string, url, !!endpoint?.use_cookies, endpoint?.body, endpoint?.headers, endpoint?.params, endpoint?.response_type, undefined, elementTemplateValuesDictAdj ) } else if (navigationAction) { const navElementId = actionId const actionParam = editorState.action_params.find( (ap) => ap.param_name === navElementId ) const elementWithEvent = actionParam?.element_id if (!elementWithEvent) return appController.actions.updateProperty( navElementId, actionParam.param_value ) } } } }