/** * Hierarchy Component * - Provides a frame for global controls and tree structure * - Fetches the complete tree of concepts in a concept scheme. * - Displays the tree in a nested list. * @todo type document, likely via extended SanityDocument type. */ import {createContext, useCallback, useContext, useState} from 'react' import {Flex, Spinner, Stack, Box, Text, Inline} from '@sanity/ui' import {AddCircleIcon} from '@sanity/icons' import {randomKey} from '@sanity/util/content' import {useListeningQuery} from 'sanity-plugin-utils' import {useCreateConcept} from '../hooks' import {trunkBuilder} from '../queries' import {DocumentConcepts} from '../types' import {HierarchyButton} from '../styles' import {SchemeContext} from './TreeView' import {TreeStructure} from './TreeStructure' import {NewScheme} from './guides' export const TreeContext = createContext(null) type GlobalVisibility = { treeId: string treeVisibility: string } export const Hierarchy = () => { const document: any = useContext(SchemeContext) || {} const documentId = document.displayed?._id const createConcept = useCreateConcept(document) const createTopConcept = useCallback(() => { createConcept('topConcept') }, [createConcept]) const createEntryConcept = useCallback(() => { createConcept('concept') }, [createConcept]) // `randomKey` is used on treeId to initiate a re-rendering of all child // elements on expand/collapse and re-initialize any local toggle state // that had been set. const [globalVisibility, setGlobalVisibility] = useState({ treeId: randomKey(3), treeVisibility: 'open', }) const handleExpand = useCallback(() => { setGlobalVisibility({treeId: randomKey(3), treeVisibility: 'open'}) }, []) const handleCollapse = useCallback(() => { setGlobalVisibility({treeId: randomKey(3), treeVisibility: 'closed'}) }, []) const {data, loading, error} = useListeningQuery( { fetch: trunkBuilder(), listen: `*[_type == "skosConcept" || _id == $id]`, }, { params: {id: documentId}, } ) if (loading) { return ( Loading hierarchy… ) } else if (error) { return
error: {error}
} else if (!data) { return } return ( // @ts-expect-error — The compiler complains about this being null. // I suspect this is an error. Hierarchy Tree Hierarchy is determined by the 'Broader' relationships assigned to each concept. {(data.topConcepts?.filter((concept) => (concept?.childConcepts?.length ?? 0) > 0) .length > 0 || data.orphans?.filter((concept) => (concept?.childConcepts?.length ?? 0) > 0).length > 0) && ( Collapse | Expand )} {document.displayed?.controls && ( Add Top Concept Add Concept )} ) } export default Hierarchy