import { useCallback , useEffect , useRef , useState } from "react" ; import { EntityCollection , NavigationContext , SideEntityController , SideEntityPanelProps } from "../../models" ; import { getNavigationEntriesFromPathInternal , NavigationViewInternal } from "../util/navigation_from_path" ; import { useLocation , useNavigate } from "react-router-dom" ; import { removeInitialAndTrailingSlashes } from "../util/navigation_utils" ; const NEW_URL_HASH = "new" ; export const useBuildSideEntityController = ( navigationContext ) : SideEntityController => { const location = useLocation ( ) ; const navigate = useNavigate ( ) ; const initialised = useRef < boolean > ( false ) ; const [ sidePanels , setSidePanels ] = useState < SideEntityPanelProps [ ] > ( [ ] ) ; const collections = navigationContext . navigation ?. collections ; const state = location . state as any ; const baseLocation = state && state . base_location ? state . base_location : location ; const updatePanels = useCallback ( ( newPanels ) => { setSidePanels ( newPanels ) ; navigationContext . removeAllOverridesExcept ( newPanels ) ; } , [ ] ) ; useEffect ( ( ) => { if ( navigationContext . initialised ) { if ( location ?. state && state . panels ) { const statePanel = state . panels as SideEntityPanelProps [ ] ; updatePanels ( statePanel ) ; } else { updatePanels ( [ ] ) ; } } } , [ location ?. state , navigationContext . initialised ] ) ; useEffect ( ( ) => { if ( collections && ! initialised . current ) { if ( navigationContext . isUrlCollectionPath ( location . pathname ) ) { const newFlag = location . hash === `#${ NEW_URL_HASH }` ; const entityOrCollectionPath = navigationContext . urlPathToDataPath ( location . pathname ) ; const sidePanels = buildSidePanelsFromUrl ( entityOrCollectionPath , collections , newFlag ) ; updatePanels ( sidePanels ) ; } initialised . current = true ; } } , [ location , collections , sidePanels ] ) ; const close = useCallback ( ( ) => { if ( sidePanels . length === 0 ) return ; const lastSidePanel = sidePanels [ sidePanels . length - 1 ] ; const locationPanels = location ?. state && state . panels ; if ( locationPanels && locationPanels . length > 0 ) { const updatedPanels = [ ... locationPanels . slice ( 0 , - 1 ) ] ; navigate ( - 1 ) ; } else { const newPath = navigationContext . buildUrlCollectionPath ( lastSidePanel . path ) ; navigate ( newPath , { replace : true } ) ; } } , [ sidePanels , location ] ) ; const open = useCallback ( ( { path , entityId , selectedSubpath , copy , width , ... schemaProps } ) => { if ( copy && ! entityId ) { throw Error ( "If you want to copy an entity you need to provide an entityId" ) ; } if ( schemaProps && ( schemaProps . schema !== undefined || schemaProps . permissions !== undefined || schemaProps . subcollections !== undefined ) ) { const permissions = schemaProps . permissions ; const schemaOrResolver = schemaProps . schema ; const subcollections = schemaProps . subcollections ; const overrideSchemaRegistry = schemaProps . overrideSchemaRegistry ; navigationContext . setOverride ( { path , entityId , schemaConfig : { permissions , schema : typeof schemaOrResolver !== "function" ? schemaOrResolver : undefined , schemaResolver : typeof schemaOrResolver === "function" ? schemaOrResolver : undefined , subcollections , callbacks : schemaProps . callbacks } , overrideSchemaRegistry } ) ; } const cleanPath = removeInitialAndTrailingSlashes ( path ) ; const newPath = entityId ? navigationContext . buildUrlCollectionPath ( `${ cleanPath }/${ entityId }/${ selectedSubpath || "" }` ) : navigationContext . buildUrlCollectionPath ( `${ cleanPath }#${ NEW_URL_HASH }` ) ; const lastSidePanel = sidePanels . length > 0 ? sidePanels [ sidePanels . length - 1 ] : undefined ; if ( entityId && lastSidePanel && lastSidePanel . path === path && lastSidePanel ?. entityId === entityId ) { const updatedPanel = { ... lastSidePanel , selectedSubpath } ; const updatedPanels = [ ... sidePanels . slice ( 0 , - 1 ) , updatedPanel ] ; updatePanels ( updatedPanels ) ; navigate ( navigationContext . buildUrlCollectionPath ( `${ cleanPath }/${ entityId }/${ selectedSubpath || "" }` ) , { replace : true , state : { base_location : baseLocation , panels : updatedPanels } } ) ; } else { const newPanel = { path , entityId , copy : copy !== undefined && copy , width , selectedSubpath } ; const updatedPanels = [ ... sidePanels , newPanel ] ; updatePanels ( updatedPanels ) ; navigate ( newPath , { state : { base_location : baseLocation , panels : updatedPanels } } ) ; } } , [ sidePanels , location ] ) ; return { sidePanels , close , open } ; } ; function buildSidePanelsFromUrl ( path , collections , newFlag ) { const navigationViewsForPath = getNavigationEntriesFromPathInternal ( { path , collections } ) ; const sidePanels = [ ] ; let lastCollectionPath = "" ; for ( let i = 0 ; i < navigationViewsForPath . length ; i ++ ) { const navigationEntry = navigationViewsForPath [ i ] ; if ( navigationEntry . type === "collection" ) { lastCollectionPath = navigationEntry . path ; } if ( i > 0 ) { const previousEntry = navigationViewsForPath [ i - 1 ] ; if ( navigationEntry . type === "entity" ) { if ( previousEntry . type === "collection" ) { sidePanels . push ( { path : navigationEntry . path , entityId : navigationEntry . entityId , copy : false } ) ; } } else if ( navigationEntry . type === "custom_view" ) { if ( previousEntry . type === "entity" ) { const lastSidePanel = sidePanels [ sidePanels . length - 1 ] ; if ( lastSidePanel ) lastSidePanel . selectedSubpath = navigationEntry . view . path ; } } else if ( navigationEntry . type === "collection" ) { if ( previousEntry . type === "entity" ) { const lastSidePanel = sidePanels [ sidePanels . length - 1 ] ; if ( lastSidePanel ) lastSidePanel . selectedSubpath = navigationEntry . collection . path ; } } } } if ( newFlag ) { sidePanels . push ( { path : lastCollectionPath , copy : false } ) ; } return sidePanels ; }