import React, {useState} from 'react'; import {ManifestContext} from './ManifestContext'; import {initialState} from './app.state'; import { take } from 'rxjs/operators'; import path from 'ramda/src/path'; import { CoreServices } from '../services'; export const ManifestStateProvider = ({children}) => { const [manifest, setManifest] = useState(initialState); const svc = new CoreServices(); const loadAppManifest = (activeApp) => { // Make store available to svc on init // svc['store'] = store; // setManifest({ ...manifest, activeApp, activeManifestItem: activeApp['manifestItems'][activeApp.startState], navigationStack: [] }); }; const loadStartState = () => { const activeManifestItem = manifest && manifest.activeApp && manifest.activeApp['manifestItems'] ? manifest.activeApp['manifestItems'][manifest.activeApp.startState] : manifest.activeManifestItem; const activeNode = activeManifestItem.nodes[activeManifestItem.startNode]; setManifest({ ...manifest, activeManifestItem, activeManifestItemId: activeManifestItem.id, activeNode, navigationStack: [] }); } const setActiveApp = (activeApp) => { setManifest({ ...manifest, activeApp }) }; const setActiveManifestItem = (data: { pathToFlows: string[]; appId: string; itemId: number | string; defaultNodeKey?: string; itemOne?: any; itemTwo?: any; }) => { console.log('hello', data) checkDeactivateState( svc, checkActivateState, [ (state, data) => { const { pathToFlows, itemId, defaultNodeKey } = data; const activeApp = state.activeApp; console.log({data}) const activeManifestItem = path(pathToFlows, activeApp)[itemId]; const startNode = activeManifestItem.itemType === 'flow' ? activeManifestItem['startNode'] : null; if (startNode) { const activeNode = defaultNodeKey ? activeManifestItem['nodes'][defaultNodeKey] : activeManifestItem['nodes'][startNode]; let navigationStack; if (state.activeNode && !pathToFlows.includes('contextMenu')) { const prevNode = { ...state.activeNode, prevState: state.activeManifestItemId }; navigationStack = [...state.navigationStack, prevNode]; } else if (pathToFlows.includes('contextMenu')) { navigationStack = []; } else { navigationStack = []; } setManifest({ ...manifest, activeApp: activeApp, activeManifestItemId: itemId, activeManifestItem, activeNode: { ...activeNode, id: startNode }, navigationStack }); } else { setManifest({ ...manifest, activeApp: activeApp, activeManifestItemId: itemId, activeManifestItem, activeNode: null }); } } // makeServerCallOnStateFlow, // listenToCallsForLoader, // getFullItemOneAfterManifest ] )(manifest, data); }; const setNextNode = (data) => { checkDeactivateNode( svc, checkActivateNode, [ // set the next node (state: any, data) => { const compKey = data; if (state.activeManifestItem.itemType !== 'flow') { return; } const nodesObj = state.activeManifestItem.nodes; const activeNode = nodesObj[compKey]; if (Object.is(activeNode, state.activeNode)) { return; } // If a decision node, don't push to navstack if (state && state.activeNode && state.activeNode.nodeType && state.activeNode.nodeType === 'decision') { setManifest({ ...manifest, activeNode: { ...activeNode, id: compKey } }); } else { setManifest({ ...manifest, navigationStack: [...state.navigationStack, state.activeNode], activeNode: { ...activeNode, id: compKey } }); } } // TODO: makeServerCallOnNode ] )(manifest, data) }; const setPreviousNode = () => { ((state: any) => { const navigationStack = state.navigationStack; const prevNode = navigationStack.pop(); if (prevNode && state && state.activeManifestItem && state.activeManifestItem.nodes) { const prevItemIds = Object.entries(state.activeManifestItem.nodes) .filter((node: any) => prevNode['component'] === node[1]['component']) .map(data => { if (data && data.length > 0) { return data[0]; } return data; }); if (prevItemIds.length > 0) prevNode.id = prevItemIds[0]; } if (prevNode && prevNode.prevState) { const activeManifestItemId = prevNode.prevState; const activeManifestItem = state.manifest.activeApp['manifestItems'][activeManifestItemId]; setManifest({ ...manifest, activeManifestItemId, activeManifestItem, activeNode: prevNode, navigationStack }); } else { setManifest({ ...manifest, activeNode: prevNode, navigationStack }); } })(manifest) }; return ( {children} ); }; //// CHECK ACTIVATE STATE export const checkActivateState = (state, data, svc: CoreServices, callbacks: Function[]) => { const { pathToFlows, itemId } = data; const activeApp = state.activeApp; console.log({state, data}) const activeManifestItem = path(pathToFlows, activeApp)[itemId]; if (activeManifestItem && activeManifestItem.activateStateGuard) { activeManifestItem.activateStateGuard(svc) .pipe(take(1)) .subscribe(canGo => { if(canGo) { console.log({state, data}) callbacks.forEach(cb => cb(state, data)) } }) } else { console.log({state, data}) callbacks.forEach(cb => cb(state, data)) } }; // CHECK CURRENT MANIFEST ITEM IF IT CAN BE DEACTIVATED export const checkDeactivateState = (svc: CoreServices, checkActivateNextState: Function, callbacks: Function[]) => { return (state, data) => { const activeManifestItem =state.activeManifestItem; if (activeManifestItem && activeManifestItem.deactivateStateGuard) { activeManifestItem.deactivateStateGuard(svc) .pipe(take(1)) .subscribe(canGo => { if(canGo) { if (state && state.activeApp) checkActivateNextState(state, data, svc, callbacks); } }) } else { if (state && state.activeApp) { console.log('jiii', activeManifestItem) checkActivateNextState(state, data, svc, callbacks); } } } }; //// CHECK ACTIVATE NODE export const checkActivateNode = (state, data, svc: CoreServices, callbacks: Function[]) => { const nodeKey = data; const activeManifestItem = state.activeManifestItem; const activeNode = activeManifestItem.nodes[nodeKey]; if (activeNode && activeNode.activateNodeGuard) { activeNode.activateNodeGuard(svc) .pipe(take(1)) .subscribe(canGo => { if(canGo) { callbacks.forEach(cb => cb(state, data)) } }) } else { callbacks.forEach(cb => cb(state, data)) } }; // CHECK CURRENT NODE IF IT CAN BE DEACTIVATED export const checkDeactivateNode = (svc: CoreServices, checkActivateNextNode: Function, callbacks: Function[]) => { return (state, data) => { const activeNode =state.activeNode; if (activeNode && activeNode.deactivateNodeGuard) { activeNode.deactivateNodeGuard(svc) .pipe(take(1)) .subscribe(canGo => { if(canGo) { if (state && state.activeApp) checkActivateNextNode(state, data, svc, callbacks); } }) } else { if (state && state.activeApp) { checkActivateNextNode(state, data, svc, callbacks); } } } };