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 { LuPlaneTakeoff as IconRESTapi } 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 { LuAtSign as IconTerm } from 'react-icons/lu';
export { LuSubscript as IconAlias } from 'react-icons/lu';

View File

@ -4,6 +4,7 @@ import {
IconDestroy,
IconEdit,
IconFilter,
IconGraphSelection,
IconKeyboard,
IconLeftOpen,
IconMoveDown,
@ -13,7 +14,6 @@ import {
IconPredecessor,
IconReset,
IconSave,
IconSettings,
IconStatusOK,
IconTree,
IconTypeGraph
@ -66,8 +66,10 @@ export function HelpRSEditor() {
<IconMoveUp className='inline-icon' /> <kbd>Alt + вверх/вниз</kbd>
</li>
<li>
<IconFilter className='inline-icon' />
<IconSettings className='inline-icon' /> фильтрация по графу термов
<IconFilter className='inline-icon' /> фильтрация по атрибутам
</li>
<li>
<IconGraphSelection className='inline-icon' /> фильтрация по графу термов
</li>
<li>
<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='cc-tab-tools flex flex-col mt-2 items-center rounded-b-2xl backdrop-blur-xs'>
<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 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} />

View File

@ -4,7 +4,7 @@ import {
IconGraphExpand,
IconGraphInputs,
IconGraphOutputs,
IconSettings
IconGraphSelection
} from '@/components/icons';
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>) {
switch (value) {
case DependencyMode.ALL:
return <IconSettings size={size} className={className} />;
return <IconGraphSelection size={size} className={className} />;
case DependencyMode.OUTPUTS:
return <IconGraphOutputs size={size} className={className ?? 'text-primary'} />;
case DependencyMode.INPUTS:

View File

@ -8,7 +8,7 @@ import { useTermGraphStore } from '../../stores/term-graph';
interface ToolbarFocusedCstProps {
className?: string;
focus: IConstituenta | null;
focus: IConstituenta;
resetFocus: () => void;
}
@ -17,10 +17,6 @@ export function ToolbarFocusedCst({ focus, resetFocus, className }: ToolbarFocus
const toggleFocusInputs = useTermGraphStore(state => state.toggleFocusInputs);
const toggleFocusOutputs = useTermGraphStore(state => state.toggleFocusOutputs);
if (!focus) {
return null;
}
return (
<div className={cn('flex items-center cc-icons', className)}>
<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}
/>
<Dropdown stretchLeft isOpen={menu.isOpen} margin='mt-3'>
{Object.values(DependencyMode)
.filter(value => !isNaN(Number(value)))
.map((value, index) => {
const source = value as DependencyMode;
return (
<DropdownButton
key={`${prefixes.cst_source_list}${index}`}
className={!dense ? 'w-72' : undefined}
icon={<IconDependencyMode value={source} size='1rem' />}
onClick={() => handleChange(source)}
>
{!dense ? (
<span>
<b>{labelCstSource(source)}:</b> {describeCstSource(source)}
</span>
) : null}
</DropdownButton>
);
})}
{Object.values(DependencyMode).map((value, index) => {
const source = value as DependencyMode;
return (
<DropdownButton
key={`${prefixes.cst_source_list}${index}`}
className={!dense ? 'w-72' : undefined}
title={dense ? labelCstSource(source) : undefined}
icon={<IconDependencyMode value={source} size='1rem' />}
onClick={() => handleChange(source)}
>
{!dense ? (
<span>
<b>{labelCstSource(source)}:</b> {describeCstSource(source)}
</span>
) : null}
</DropdownButton>
);
})}
</Dropdown>
</div>
);

View File

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

View File

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

View File

@ -107,7 +107,7 @@ export function EditorConstituenta() {
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 ? (
<FormConstituenta
key={activeCst.id}

View File

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