import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; import Dropdown from '../../../components/Common/Dropdown'; import DropdownButton from '../../../components/Common/DropdownButton'; import SelectorButton from '../../../components/Common/SelectorButton'; import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '../../../components/DataTable'; import { CogIcon, FilterIcon, MagnifyingGlassIcon } from '../../../components/Icons'; import { useRSForm } from '../../../context/RSFormContext'; import { useConceptTheme } from '../../../context/ThemeContext'; import useDropdown from '../../../hooks/useDropdown'; import useLocalStorage from '../../../hooks/useLocalStorage'; import useWindowSize from '../../../hooks/useWindowSize'; import { DependencyMode as CstSource } from '../../../models/miscelanious'; import { CstMatchMode } from '../../../models/miscelanious'; import { applyGraphFilter } from '../../../models/miscelanious'; import { CstType, extractGlobals, IConstituenta, matchConstituenta } from '../../../models/rsform'; import { createMockConstituenta } from '../../../models/rsform'; import { colorfgCstStatus } from '../../../utils/color'; import { prefixes } from '../../../utils/constants'; import { describeConstituenta, describeCstMathchMode, describeCstSource, labelCstMathchMode, labelCstSource } from '../../../utils/labels'; import ConstituentaTooltip from '../../../components/Help/ConstituentaTooltip'; // Height that should be left to accomodate navigation panel + bottom margin const LOCAL_NAVIGATION_H = '2.1rem'; // Window width cutoff for expression show const COLUMN_EXPRESSION_HIDE_THRESHOLD = 1500; interface ViewSideConstituentsProps { expression: string baseHeight: string activeID?: number onOpenEdit: (cstID: number) => void } function isMockCst(cst: IConstituenta) { return cst.id <= 0; } const columnHelper = createColumnHelper(); function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: ViewSideConstituentsProps) { const windowSize = useWindowSize(); const { noNavigation, colors } = useConceptTheme(); const { schema } = useRSForm(); const [columnVisibility, setColumnVisibility] = useState({'expression': true}) const [filterMatch, setFilterMatch] = useLocalStorage('side-filter-match', CstMatchMode.ALL); const [filterText, setFilterText] = useLocalStorage('side-filter-text', ''); const [filterSource, setFilterSource] = useLocalStorage('side-filter-dependency', CstSource.ALL); const [filteredData, setFilteredData] = useState(schema?.items ?? []); const matchModeMenu = useDropdown(); const sourceMenu = useDropdown(); useLayoutEffect( () => { setColumnVisibility(prev => { const newValue = (windowSize.width ?? 0) >= COLUMN_EXPRESSION_HIDE_THRESHOLD; if (newValue === prev['expression']) { return prev; } else { return {'expression': newValue} } }); }, [windowSize]); useLayoutEffect( () => { if (!schema?.items) { setFilteredData([]); return; } let filtered: IConstituenta[] = []; if (filterSource === CstSource.EXPRESSION) { const aliases = extractGlobals(expression); filtered = schema.items.filter((cst) => aliases.has(cst.alias)); const names = filtered.map(cst => cst.alias) const diff = Array.from(aliases).filter(name => !names.includes(name)); if (diff.length > 0) { diff.forEach( (alias, index) => filtered.push( createMockConstituenta( schema.id, -index, alias, CstType.BASE, 'Конституента отсутствует' ) ) ); } } else if (!activeID) { filtered = schema.items } else { filtered = applyGraphFilter(schema, activeID, filterSource); } if (filterText) { filtered = filtered.filter((cst) => matchConstituenta(filterText, cst, filterMatch)); } setFilteredData(filtered); }, [filterText, setFilteredData, filterSource, expression, schema, filterMatch, activeID]); const handleRowClicked = useCallback( (cst: IConstituenta, event: React.MouseEvent) => { if (event.altKey && !isMockCst(cst)) { onOpenEdit(cst.id); } }, [onOpenEdit]); const handleDoubleClick = useCallback( (cst: IConstituenta) => { if (!isMockCst(cst)) { onOpenEdit(cst.id); } }, [onOpenEdit]); const handleMatchModeChange = useCallback( (newValue: CstMatchMode) => { matchModeMenu.hide(); setFilterMatch(newValue); }, [matchModeMenu, setFilterMatch]); const handleSourceChange = useCallback( (newValue: CstSource) => { sourceMenu.hide(); setFilterSource(newValue); }, [sourceMenu, setFilterSource]); const columns = useMemo( () => [ columnHelper.accessor('alias', { id: 'alias', header: 'Имя', size: 65, minSize: 65, footer: undefined, cell: props => { const cst = props.row.original; return (<>
{cst.alias}
); } }), columnHelper.accessor(cst => describeConstituenta(cst), { id: 'description', header: 'Описание', size: 1000, minSize: 250, maxSize: 1000, cell: props =>
{props.getValue()}
}), columnHelper.accessor('definition_formal', { id: 'expression', header: 'Выражение', size: 2000, minSize: 0, maxSize: 2000, enableHiding: true, cell: props =>
{props.getValue()}
}) ], [colors]); const conditionalRowStyles = useMemo( (): IConditionalStyle[] => [ { when: (cst: IConstituenta) => cst.id === activeID, style: { backgroundColor: colors.bgSelected }, } ], [activeID, colors]); const maxHeight = useMemo( () => { const siblingHeight = `${baseHeight} - ${LOCAL_NAVIGATION_H}` return (noNavigation ? `calc(min(100vh - 8.2rem, ${siblingHeight}))` : `calc(min(100vh - 11.7rem, ${siblingHeight}))`); }, [noNavigation, baseHeight]); return (<>
setFilterText(event.target.value)} />
} text={labelCstMathchMode(filterMatch)} tabIndex={-1} onClick={matchModeMenu.toggle} /> { matchModeMenu.isActive && { Object.values(CstMatchMode).filter(value => !isNaN(Number(value))).map( (value, index) => { const matchMode = value as CstMatchMode; return ( handleMatchModeChange(matchMode)} >

{labelCstMathchMode(matchMode)}: {describeCstMathchMode(matchMode)}

); })}
}
} text={labelCstSource(filterSource)} tabIndex={-1} onClick={sourceMenu.toggle} /> { sourceMenu.isActive && { Object.values(CstSource).filter(value => !isNaN(Number(value))).map( (value, index) => { const source = value as CstSource; return ( handleSourceChange(source)} >

{labelCstSource(source)}: {describeCstSource(source)}

); })}
}

Список конституент пуст

Измените параметры фильтра

} onRowDoubleClicked={handleDoubleClick} onRowClicked={handleRowClicked} />
); } export default ViewSideConstituents;