import { useMemo, ReactElement, useState, useContext } from 'react'; import { Handles, NodeAttribute, QueryElementTypes, QueryGraphEdges, SchemaReactflowEntityNode, SchemaReactflowRelationNode, } from '../../model'; import { Abc, CalendarToday, Map, Numbers, Place, QuestionMarkOutlined } from '@mui/icons-material'; import { Button, TextInput, useAppDispatch, useQuerybuilderAttributesShown } from '../../..'; import { attributeShownToggle } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice'; import { isEqual } from 'lodash-es'; import { QueryBuilderDispatcherContext } from '../../panel/QueryBuilderDispatcher'; import { PillDropdownItem } from './PillDropdownItem'; type PillDropdownProps = { node: SchemaReactflowEntityNode | SchemaReactflowRelationNode; attributes: NodeAttribute[]; attributeEdges: (QueryGraphEdges | undefined)[]; open: boolean; mr?: number; className?: string; }; type IconMapType = { [key: string]: ReactElement; }; const IconMap: IconMapType = { temporal: <CalendarToday />, spatial: <Map />, numerical: <Numbers />, categorical: <Abc />, default: <Place />, }; export const PillDropdown = (props: PillDropdownProps) => { const forceOpen = false; const [filter, setFilter] = useState<string>(''); const dispatch = useAppDispatch(); const attributesBeingShown = useQuerybuilderAttributesShown(); const attributesOfInterest = useMemo(() => { return props.attributes.map((attribute) => attributesBeingShown.findIndex((x) => isEqual(x, attribute.handleData)) === -1 ? false : true, ); }, [attributesBeingShown]); return ( <div className={'border-[1px] border-secondary-200 divide-y divide-secondary-200 !z-50'}> {attributesOfInterest && attributesOfInterest.map((showing, i) => { if (!showing) return null; return ( <PillDropdownItem key={props.attributes[i].handleData.attributeName || i} node={props.node} attribute={props.attributes[i]} mr={props.mr} className={props.className} icon={ props.attributes[i].handleData?.attributeDimension ? ( IconMap[props.attributes[i].handleData.attributeDimension || 0] ) : ( <QuestionMarkOutlined /> ) } /> ); })} {(props.open || forceOpen) && ( <> <h4 className="p-1 bg-white border-t-[2px] font-semibold text-2xs">Available Attributes:</h4> <TextInput type={'text'} placeholder="Filter" size="xs" className="!p-0.5" value={filter} onChange={(v) => setFilter(v)} /> <div className="max-h-28 overflow-auto flex flex-col bg-white"> {props.attributes.map((attribute, i) => { if (filter && !attribute.handleData.attributeName?.toLowerCase().includes(filter.toLowerCase())) return null; if (attribute.handleData.attributeName === undefined) { throw new Error('attribute.handleData.attributeName is undefined'); } return ( <Button key={(attribute.handleData.attributeName || '') + i} iconComponent={attribute?.handleData?.attributeDimension ? IconMap[attribute.handleData.attributeDimension] : undefined} iconPosition="trailing" className={`w-full ${attributesOfInterest[i] ? 'bg-secondary-100' : 'bg-white'} justify-between rounded-none text-[0.7em]`} variant="ghost" size={'xs'} label={attribute.handleData.attributeName} onMouseDownCapture={(e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); dispatch(attributeShownToggle(attribute.handleData)); }} ></Button> ); })} </div> </> )} </div> ); };