F: Improve graph filtering for CstList
Some checks failed
Frontend CI / build (22.x) (push) Has been cancelled
Frontend CI / notify-failure (push) Has been cancelled

This commit is contained in:
Ivan 2025-07-25 16:02:43 +03:00
parent 628c91e57b
commit 72f7be3247
10 changed files with 65 additions and 62 deletions

View File

@ -106,6 +106,7 @@ export { LuDatabase as IconDatabase } from 'react-icons/lu';
export { LuView as IconDBStructure } from 'react-icons/lu'; export { LuView as IconDBStructure } from 'react-icons/lu';
export { LuPlaneTakeoff as IconRESTapi } from 'react-icons/lu'; export { LuPlaneTakeoff as IconRESTapi } from 'react-icons/lu';
export { LuImage as IconImage } from 'react-icons/lu'; export { LuImage as IconImage } from 'react-icons/lu';
export { PiFediverseLogo as IconGraphSelection } from 'react-icons/pi';
export { GoVersions as IconVersions } from 'react-icons/go'; export { GoVersions as IconVersions } from 'react-icons/go';
export { LuAtSign as IconTerm } from 'react-icons/lu'; export { LuAtSign as IconTerm } from 'react-icons/lu';
export { LuSubscript as IconAlias } from 'react-icons/lu'; export { LuSubscript as IconAlias } from 'react-icons/lu';

View File

@ -4,6 +4,7 @@ import {
IconDestroy, IconDestroy,
IconEdit, IconEdit,
IconFilter, IconFilter,
IconGraphSelection,
IconKeyboard, IconKeyboard,
IconLeftOpen, IconLeftOpen,
IconMoveDown, IconMoveDown,
@ -13,7 +14,6 @@ import {
IconPredecessor, IconPredecessor,
IconReset, IconReset,
IconSave, IconSave,
IconSettings,
IconStatusOK, IconStatusOK,
IconTree, IconTree,
IconTypeGraph IconTypeGraph
@ -66,8 +66,10 @@ export function HelpRSEditor() {
<IconMoveUp className='inline-icon' /> <kbd>Alt + вверх/вниз</kbd> <IconMoveUp className='inline-icon' /> <kbd>Alt + вверх/вниз</kbd>
</li> </li>
<li> <li>
<IconFilter className='inline-icon' /> <IconFilter className='inline-icon' /> фильтрация по атрибутам
<IconSettings className='inline-icon' /> фильтрация по графу термов </li>
<li>
<IconGraphSelection className='inline-icon' /> фильтрация по графу термов
</li> </li>
<li> <li>
<IconChild className='inline-icon' /> отображение наследованных <IconChild className='inline-icon' /> отображение наследованных

View File

@ -97,7 +97,9 @@ export function TGReadonlyFlow({ schema }: TGReadonlyFlowProps) {
<div className='relative w-full h-full flex flex-col'> <div className='relative w-full h-full flex flex-col'>
<div className='cc-tab-tools flex flex-col mt-2 items-center rounded-b-2xl backdrop-blur-xs'> <div className='cc-tab-tools flex flex-col mt-2 items-center rounded-b-2xl backdrop-blur-xs'>
<ToolbarGraphFilter /> <ToolbarGraphFilter />
<ToolbarFocusedCst className='-translate-x-9' focus={focusCst} resetFocus={() => setFocusCst(null)} /> {focusCst ? (
<ToolbarFocusedCst className='-translate-x-9' focus={focusCst} resetFocus={() => setFocusCst(null)} />
) : null}
</div> </div>
<div className='absolute z-pop top-24 sm:top-16 left-2 sm:left-3 w-54 flex flex-col pointer-events-none'> <div className='absolute z-pop top-24 sm:top-16 left-2 sm:left-3 w-54 flex flex-col pointer-events-none'>
<SelectColoring schema={schema} /> <SelectColoring schema={schema} />

View File

@ -4,7 +4,7 @@ import {
IconGraphExpand, IconGraphExpand,
IconGraphInputs, IconGraphInputs,
IconGraphOutputs, IconGraphOutputs,
IconSettings IconGraphSelection
} from '@/components/icons'; } from '@/components/icons';
import { DependencyMode } from '../stores/cst-search'; import { DependencyMode } from '../stores/cst-search';
@ -13,7 +13,7 @@ import { DependencyMode } from '../stores/cst-search';
export function IconDependencyMode({ value, size = '1.25rem', className }: DomIconProps<DependencyMode>) { export function IconDependencyMode({ value, size = '1.25rem', className }: DomIconProps<DependencyMode>) {
switch (value) { switch (value) {
case DependencyMode.ALL: case DependencyMode.ALL:
return <IconSettings size={size} className={className} />; return <IconGraphSelection size={size} className={className} />;
case DependencyMode.OUTPUTS: case DependencyMode.OUTPUTS:
return <IconGraphOutputs size={size} className={className ?? 'text-primary'} />; return <IconGraphOutputs size={size} className={className ?? 'text-primary'} />;
case DependencyMode.INPUTS: case DependencyMode.INPUTS:

View File

@ -8,7 +8,7 @@ import { useTermGraphStore } from '../../stores/term-graph';
interface ToolbarFocusedCstProps { interface ToolbarFocusedCstProps {
className?: string; className?: string;
focus: IConstituenta | null; focus: IConstituenta;
resetFocus: () => void; resetFocus: () => void;
} }
@ -17,10 +17,6 @@ export function ToolbarFocusedCst({ focus, resetFocus, className }: ToolbarFocus
const toggleFocusInputs = useTermGraphStore(state => state.toggleFocusInputs); const toggleFocusInputs = useTermGraphStore(state => state.toggleFocusInputs);
const toggleFocusOutputs = useTermGraphStore(state => state.toggleFocusOutputs); const toggleFocusOutputs = useTermGraphStore(state => state.toggleFocusOutputs);
if (!focus) {
return null;
}
return ( return (
<div className={cn('flex items-center cc-icons', className)}> <div className={cn('flex items-center cc-icons', className)}>
<div className='w-31 mt-0.5 text-right select-none text-(--acc-fg-purple)'> <div className='w-31 mt-0.5 text-right select-none text-(--acc-fg-purple)'>

View File

@ -36,25 +36,24 @@ export function SelectGraphFilter({ value, dense, className, onChange, ...restPr
onClick={menu.toggle} onClick={menu.toggle}
/> />
<Dropdown stretchLeft isOpen={menu.isOpen} margin='mt-3'> <Dropdown stretchLeft isOpen={menu.isOpen} margin='mt-3'>
{Object.values(DependencyMode) {Object.values(DependencyMode).map((value, index) => {
.filter(value => !isNaN(Number(value))) const source = value as DependencyMode;
.map((value, index) => { return (
const source = value as DependencyMode; <DropdownButton
return ( key={`${prefixes.cst_source_list}${index}`}
<DropdownButton className={!dense ? 'w-72' : undefined}
key={`${prefixes.cst_source_list}${index}`} title={dense ? labelCstSource(source) : undefined}
className={!dense ? 'w-72' : undefined} icon={<IconDependencyMode value={source} size='1rem' />}
icon={<IconDependencyMode value={source} size='1rem' />} onClick={() => handleChange(source)}
onClick={() => handleChange(source)} >
> {!dense ? (
{!dense ? ( <span>
<span> <b>{labelCstSource(source)}:</b> {describeCstSource(source)}
<b>{labelCstSource(source)}:</b> {describeCstSource(source)} </span>
</span> ) : null}
) : null} </DropdownButton>
</DropdownButton> );
); })}
})}
</Dropdown> </Dropdown>
</div> </div>
); );

View File

@ -35,25 +35,24 @@ export function SelectMatchMode({ value, dense, className, onChange, ...restProp
onClick={menu.toggle} onClick={menu.toggle}
/> />
<Dropdown stretchLeft isOpen={menu.isOpen} margin='mt-3'> <Dropdown stretchLeft isOpen={menu.isOpen} margin='mt-3'>
{Object.values(CstMatchMode) {Object.values(CstMatchMode).map((value, index) => {
.filter(value => !isNaN(Number(value))) const matchMode = value as CstMatchMode;
.map((value, index) => { return (
const matchMode = value as CstMatchMode; <DropdownButton
return ( key={`${prefixes.cst_source_list}${index}`}
<DropdownButton className={!dense ? 'w-80' : undefined}
key={`${prefixes.cst_source_list}${index}`} title={dense ? labelCstMatchMode(matchMode) : undefined}
className={!dense ? 'w-80' : undefined} icon={<IconCstMatchMode value={matchMode} size='1rem' />}
icon={<IconCstMatchMode value={matchMode} size='1rem' />} onClick={() => handleChange(matchMode)}
onClick={() => handleChange(matchMode)} >
> {!dense ? (
{!dense ? ( <span>
<span> <b>{labelCstMatchMode(matchMode)}:</b> {describeCstMatchMode(matchMode)}
<b>{labelCstMatchMode(matchMode)}:</b> {describeCstMatchMode(matchMode)} </span>
</span> ) : null}
) : null} </DropdownButton>
</DropdownButton> );
); })}
})}
</Dropdown> </Dropdown>
</div> </div>
); );

View File

@ -55,7 +55,7 @@ const labelColoringRecord: Record<GraphColoring, string> = {
}; };
const labelCstMatchModeRecord: Record<CstMatchMode, string> = { const labelCstMatchModeRecord: Record<CstMatchMode, string> = {
[CstMatchMode.ALL]: 'общий', [CstMatchMode.ALL]: 'фильтр',
[CstMatchMode.EXPR]: 'выражение', [CstMatchMode.EXPR]: 'выражение',
[CstMatchMode.TERM]: 'термин', [CstMatchMode.TERM]: 'термин',
[CstMatchMode.TEXT]: 'текст', [CstMatchMode.TEXT]: 'текст',
@ -70,6 +70,14 @@ const describeCstMatchModeRecord: Record<CstMatchMode, string> = {
[CstMatchMode.NAME]: 'только имена' [CstMatchMode.NAME]: 'только имена'
}; };
const labelCstSourceRecord: Record<DependencyMode, string> = {
[DependencyMode.ALL]: 'граф',
[DependencyMode.OUTPUTS]: 'потребители',
[DependencyMode.INPUTS]: 'поставщики',
[DependencyMode.EXPAND_OUTPUTS]: 'зависимые',
[DependencyMode.EXPAND_INPUTS]: 'влияющие'
};
const describeCstSourceRecord: Record<DependencyMode, string> = { const describeCstSourceRecord: Record<DependencyMode, string> = {
[DependencyMode.ALL]: 'все конституенты', [DependencyMode.ALL]: 'все конституенты',
[DependencyMode.OUTPUTS]: 'прямые исходящие', [DependencyMode.OUTPUTS]: 'прямые исходящие',
@ -256,14 +264,6 @@ const describeTokenRecord: Partial<Record<TokenID, string>> = {
[TokenID.ITERATE]: prepareTooltip('Перебор элементов множества', 'Alt + 6') [TokenID.ITERATE]: prepareTooltip('Перебор элементов множества', 'Alt + 6')
}; };
const labelCstSourceRecord: Record<DependencyMode, string> = {
[DependencyMode.ALL]: 'не ограничен',
[DependencyMode.OUTPUTS]: 'потребители',
[DependencyMode.INPUTS]: 'поставщики',
[DependencyMode.EXPAND_OUTPUTS]: 'зависимые',
[DependencyMode.EXPAND_INPUTS]: 'влияющие'
};
/** /**
* Generates description for {@link IConstituenta}. * Generates description for {@link IConstituenta}.
*/ */

View File

@ -107,7 +107,7 @@ export function EditorConstituenta() {
isNarrow={isNarrow} isNarrow={isNarrow}
/> />
<div className='mx-0 md:mx-auto pt-8 md:w-195 shrink-0 xs:pt-0'> <div className='mx-0 min-w-140 md:mx-auto pt-8 md:w-195 shrink-0 xs:pt-0'>
{activeCst ? ( {activeCst ? (
<FormConstituenta <FormConstituenta
key={activeCst.id} key={activeCst.id}

View File

@ -168,8 +168,12 @@ export function TGFlow() {
<div className='relative' tabIndex={-1} onKeyDown={handleKeyDown}> <div className='relative' tabIndex={-1} onKeyDown={handleKeyDown}>
<div className='cc-tab-tools flex flex-col items-center rounded-b-2xl backdrop-blur-xs'> <div className='cc-tab-tools flex flex-col items-center rounded-b-2xl backdrop-blur-xs'>
<ToolbarTermGraph /> <ToolbarTermGraph />
<ToolbarFocusedCst focus={focusCst} resetFocus={() => setFocus(null)} /> {focusCst ? (
{!focusCst ? ( <ToolbarFocusedCst
focus={focusCst} //
resetFocus={() => setFocus(null)}
/>
) : (
<ToolbarGraphSelection <ToolbarGraphSelection
graph={schema.graph} graph={schema.graph}
isCore={cstID => { isCore={cstID => {
@ -180,7 +184,7 @@ export function TGFlow() {
value={selected} value={selected}
onChange={handleSetSelected} onChange={handleSetSelected}
/> />
) : null} )}
</div> </div>
<div className='absolute z-pop top-24 sm:top-16 left-2 sm:left-3 w-54 flex flex-col pointer-events-none'> <div className='absolute z-pop top-24 sm:top-16 left-2 sm:left-3 w-54 flex flex-col pointer-events-none'>