UNPKG

@cmk/fe_utils

Version:
252 lines (230 loc) 7.71 kB
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react' import { AppState, EditorStateType } from '../types' import { AppController } from '../types' import { replacePlaceholdersInString } from '../renderer' import { EditorRendererControllerType } from '../types/editorRendererController' export type EditorControllerAppStateParams = { properties: EditorStateType['properties'] attributes: EditorStateType['attributes'] transformers: EditorStateType['transformers'] currentViewportElements: EditorRendererControllerType['currentViewportElements'] } export const useAppController = ( params: EditorControllerAppStateParams ): AppController => { const { properties, currentViewportElements, transformers } = params const [appState, setAppState] = useState<AppState>({ forms: {}, _data: {}, treeviews: { selectedId: {}, selectedItem: {}, }, tableUis: {}, buttonStates: {}, navigationStates: {}, currentThemeName: 'light', }) const actions = useMemo(() => { /** update/add navstates - TODO still flat in appstate * @param key - key = elementId of navElement * @param value - value = value of navElement * */ const updateProperty = (key: string, value: unknown) => { setAppState((current) => ({ ...current, [key]: value })) } /** remove navstates - TODO still flat in appstate * @param key - key = elementId of navElement * */ const removeProperty = (key: string) => { setAppState((current) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { [key]: _, ...rest } = current return rest as typeof appState }) } /** change/add formData for specifc form-element with elementId * @param elementId - elementId of form-element * @param newFormData - newFormData = new formdata for form-element * */ const changeFormData = ( elementId: string, newFormData: Record<string, unknown> ) => { setAppState((current) => { // const formData = current.forms?.[elementId] ?? {} // const newFormData = { ...formData, [inputName]: value } return { ...current, forms: { ...current.forms, [elementId]: newFormData }, } }) } /** get formData for specific form-element with element * @param elementId - elementId of form-element * */ const getFormData = (elementId: string) => { return appState.forms?.[elementId] ?? {} } /** update/add data from API/EPs * @param key - key = currently actionId TODO * @param value - value = querried data (axios response) */ const updateData = (key: string, value: { [key: string]: unknown }) => { setAppState((current) => { return { ...current, _data: { ...current._data, [key]: value }, } }) } /** remove data from API/EPs (is this function used?) * @param key - key = see above */ const removeData = (key: string) => { setAppState((current) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { [key]: _, ...rest } = current return rest as typeof appState }) } const changeButtonState = (buttonElementId: string) => { setAppState((current) => { console.log('changeButtonState', buttonElementId, current?.buttonStates?.[buttonElementId]) return { ...current, buttonStates: { ...current.buttonStates, [buttonElementId]: (current?.buttonStates?.[buttonElementId] as any) === '' ? true : !current?.buttonStates?.[buttonElementId], }, } }) } const changeTreeviewSelectedItem = ( treeViewElementId: string, selectedId: string, selectedItem: Record<string, unknown> ) => { setAppState((current) => { return { ...current, treeviews: { ...current.treeviews, selectedItem: { ...(current.treeviews.selectedItem ?? {}), [treeViewElementId]: selectedItem, }, selectedId: { ...((current.treeviews.selectedId ?? {}) as (typeof appState)['treeviews']['selectedId']), [treeViewElementId]: [selectedId], }, }, } }) } const updateTableUi = (tableUi: { [key: string]: { onSetFilters: Dispatch< SetStateAction<{ filterKey: string; value: string }[]> > filters: { filterKey: string; value: string }[] } }) => { setAppState((current) => { return { ...current, tableUis: { ...current.tableUis, ...tableUi, }, } }) } const updateCurrentTheme = (themeName: string) => { setAppState((current) => { return { ...current, currentThemeName: themeName, } }) } return { updateTableUi, getFormData, changeFormData, addProperty: updateProperty, removeProperty, updateProperty, updateData, removeData, changeTreeviewSelectedItem, changeButtonState, updateCurrentTheme, } }, [setAppState, appState?.forms]) useEffect(() => { const onTreeViewSelectionChange = ( treeViewElementId: string, itemId: string ) => { const treeviewItemsPropertyValue = properties?.find?.( (prop) => prop.element_id === treeViewElementId && prop.prop_name === 'items' && typeof prop.prop_value === 'string' && prop.prop_value.includes('{_data.') )?.prop_value const treeViewElement = currentViewportElements?.find?.( (element) => element.element_id === treeViewElementId ) if (!treeviewItemsPropertyValue || !treeViewElement) return const treeviewItemsPropertyValueResolved0 = replacePlaceholdersInString( treeviewItemsPropertyValue as string, appState, [], properties, treeViewElement ) const transformer = transformers.find( (trans) => trans.element_id === treeViewElementId ) const transformerFunction = transformer?.transformer_string ? eval(transformer?.transformer_string) : null // need to transform if transformer is present to get the name of the id column -> nodeId const treeviewItemsPropertyValueResolved = transformerFunction ? transformerFunction(treeviewItemsPropertyValueResolved0) : treeviewItemsPropertyValueResolved0 const id = itemId?.[0] ?? itemId?.[0]?.[0] const item = treeviewItemsPropertyValueResolved?.find?.( (item: unknown) => item && typeof item === 'object' && 'nodeId' in item && item.nodeId === id ) if (!item) return actions.changeTreeviewSelectedItem(treeViewElementId, id, item) } const treeviewElementIds = Object.keys(appState.treeviews.selectedId) treeviewElementIds.forEach((elementId) => { const selectedId = appState.treeviews.selectedId[elementId] if (selectedId) { // TODO: check if this is correct -> selectedId as any onTreeViewSelectionChange(elementId, selectedId as unknown as string) } }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [appState?._data]) const controller = useMemo(() => { return { state: appState, actions, } }, [appState, actions]) return controller }