mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Implement search setup for EditConsituenta
This commit is contained in:
parent
47564c9d91
commit
b8fe9953a9
|
@ -1,13 +1,15 @@
|
||||||
import { useLayoutEffect, useMemo, useState } from 'react';
|
import { useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||||
|
import Divider from '../../components/Common/Divider';
|
||||||
import MiniButton from '../../components/Common/MiniButton';
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
import SubmitButton from '../../components/Common/SubmitButton';
|
import SubmitButton from '../../components/Common/SubmitButton';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
import { DumpBinIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
import { DumpBinIcon, HelpIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import { type CstType, EditMode, ICstUpdateData, SyntaxTree } from '../../utils/models';
|
import { type CstType, EditMode, ICstUpdateData, SyntaxTree } from '../../utils/models';
|
||||||
import { getCstTypeLabel } from '../../utils/staticUI';
|
import { getCstTypeLabel, mapStatusInfo } from '../../utils/staticUI';
|
||||||
import EditorRSExpression from './EditorRSExpression';
|
import EditorRSExpression from './EditorRSExpression';
|
||||||
import ViewSideConstituents from './elements/ViewSideConstituents';
|
import ViewSideConstituents from './elements/ViewSideConstituents';
|
||||||
|
|
||||||
|
@ -150,6 +152,36 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onOpenEdit, onDe
|
||||||
onClick={handleDelete}
|
onClick={handleDelete}
|
||||||
icon={<DumpBinIcon size={5} color={isEnabled ? 'text-red' : ''} />}
|
icon={<DumpBinIcon size={5} color={isEnabled ? 'text-red' : ''} />}
|
||||||
/>
|
/>
|
||||||
|
<div id='cst-help' className='flex items-center ml-[0.25rem]'>
|
||||||
|
<HelpIcon color='text-primary' size={5} />
|
||||||
|
</div>
|
||||||
|
<ConceptTooltip anchorSelect='#cst-help'>
|
||||||
|
<div className='max-w-[35rem]'>
|
||||||
|
<h1>Подсказки</h1>
|
||||||
|
<p><b className='text-red'>Изменения сохраняются ПОСЛЕ нажатия на кнопку снизу или слева вверху</b></p>
|
||||||
|
<p><b>Клик на формальное выражение</b> - обратите внимание на кнопки снизу.<br/>Для каждой есть горячая клавиша в подсказке</p>
|
||||||
|
<p><b>Список конституент справа</b> - обратите внимание на настройки фильтрации</p>
|
||||||
|
<p>- слева от ввода текста настраивается набор атрибутов конституенты</p>
|
||||||
|
<p>- справа от ввода текста настраивается список конституент, которые фильтруются</p>
|
||||||
|
<p>- текущая конституента выделена цветом строки</p>
|
||||||
|
<p>- двойнок клин / Alt + клик - выбор редактируемой конституенты</p>
|
||||||
|
<p>- при наведении на ID конституенты отображаются ее атрибуты</p>
|
||||||
|
<p>- столбец "Описание" содержит один из непустых текстовых атрибутов</p>
|
||||||
|
<Divider margins='mt-2' />
|
||||||
|
<h1>Статусы</h1>
|
||||||
|
{ [... mapStatusInfo.values()].map(info => {
|
||||||
|
return (<p className='py-1'>
|
||||||
|
<span className={`inline-block font-semibold min-w-[4rem] text-center border ${info.color}`}>
|
||||||
|
{info.text}
|
||||||
|
</span>
|
||||||
|
<span> - </span>
|
||||||
|
<span>
|
||||||
|
{info.tooltip}
|
||||||
|
</span>
|
||||||
|
</p>);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</ConceptTooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<TextArea id='term' label='Термин'
|
<TextArea id='term' label='Термин'
|
||||||
|
@ -167,6 +199,7 @@ function EditorConstituenta({ activeID, onShowAST, onCreateCst, onOpenEdit, onDe
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
<EditorRSExpression id='expression' label='Формальное выражение'
|
<EditorRSExpression id='expression' label='Формальное выражение'
|
||||||
|
activeCst={activeCst}
|
||||||
placeholder='Родоструктурное выражение, задающее формальное определение'
|
placeholder='Родоструктурное выражение, задающее формальное определение'
|
||||||
value={expression}
|
value={expression}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Loader } from '../../components/Common/Loader';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import useCheckExpression from '../../hooks/useCheckExpression';
|
import useCheckExpression from '../../hooks/useCheckExpression';
|
||||||
import { TokenID } from '../../utils/enums';
|
import { TokenID } from '../../utils/enums';
|
||||||
import { IRSErrorDescription, SyntaxTree } from '../../utils/models';
|
import { IConstituenta, IRSErrorDescription, SyntaxTree } from '../../utils/models';
|
||||||
import { getCstExpressionPrefix } from '../../utils/staticUI';
|
import { getCstExpressionPrefix } from '../../utils/staticUI';
|
||||||
import ParsingResult from './elements/ParsingResult';
|
import ParsingResult from './elements/ParsingResult';
|
||||||
import RSLocalButton from './elements/RSLocalButton';
|
import RSLocalButton from './elements/RSLocalButton';
|
||||||
|
@ -17,6 +17,7 @@ import { getSymbolSubstitute, TextWrapper } from './elements/textEditing';
|
||||||
|
|
||||||
interface EditorRSExpressionProps {
|
interface EditorRSExpressionProps {
|
||||||
id: string
|
id: string
|
||||||
|
activeCst?: IConstituenta
|
||||||
label: string
|
label: string
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
@ -30,10 +31,10 @@ interface EditorRSExpressionProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditorRSExpression({
|
function EditorRSExpression({
|
||||||
id, label, disabled, isActive, placeholder, value, setValue, onShowAST,
|
id, activeCst, label, disabled, isActive, placeholder, value, setValue, onShowAST,
|
||||||
toggleEditMode, setTypification, onChange
|
toggleEditMode, setTypification, onChange
|
||||||
}: EditorRSExpressionProps) {
|
}: EditorRSExpressionProps) {
|
||||||
const { schema, activeCst } = useRSForm();
|
const { schema } = useRSForm();
|
||||||
const [isModified, setIsModified] = useState(false);
|
const [isModified, setIsModified] = useState(false);
|
||||||
const { parseData, checkExpression, resetParse, loading } = useCheckExpression({ schema });
|
const { parseData, checkExpression, resetParse, loading } = useCheckExpression({ schema });
|
||||||
const expressionCtrl = useRef<HTMLTextAreaElement>(null);
|
const expressionCtrl = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
|
@ -27,7 +27,6 @@ function RSTabsMenu({showUploadDialog, showCloneDialog}: RSTabsMenuProps) {
|
||||||
} = useRSForm();
|
} = useRSForm();
|
||||||
const schemaMenu = useDropdown();
|
const schemaMenu = useDropdown();
|
||||||
const editMenu = useDropdown();
|
const editMenu = useDropdown();
|
||||||
|
|
||||||
|
|
||||||
const handleClaimOwner = useCallback(() => {
|
const handleClaimOwner = useCallback(() => {
|
||||||
editMenu.hide();
|
editMenu.hide();
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import Dropdown from '../../../components/Common/Dropdown';
|
||||||
|
import DropdownButton from '../../../components/Common/DropdownButton';
|
||||||
|
import useDropdown from '../../../hooks/useDropdown';
|
||||||
|
import { DependencyMode } from '../../../utils/models';
|
||||||
|
import { getDependencyLabel } from '../../../utils/staticUI';
|
||||||
|
|
||||||
|
interface DependencyModePickerProps {
|
||||||
|
value: DependencyMode
|
||||||
|
onChange: (value: DependencyMode) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
function DependencyModePicker({ value, onChange }: DependencyModePickerProps) {
|
||||||
|
const pickerMenu = useDropdown();
|
||||||
|
|
||||||
|
const handleChange = useCallback(
|
||||||
|
(newValue: DependencyMode) => {
|
||||||
|
pickerMenu.hide();
|
||||||
|
onChange(newValue);
|
||||||
|
}, [pickerMenu, onChange]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={pickerMenu.ref}>
|
||||||
|
<span
|
||||||
|
className='text-sm font-semibold underline cursor-pointer select-none whitespace-nowrap'
|
||||||
|
tabIndex={-1}
|
||||||
|
onClick={pickerMenu.toggle}
|
||||||
|
>
|
||||||
|
{getDependencyLabel(value)}
|
||||||
|
</span>
|
||||||
|
{ pickerMenu.isActive &&
|
||||||
|
<Dropdown stretchLeft >
|
||||||
|
<DropdownButton onClick={() => handleChange(DependencyMode.ALL)}>
|
||||||
|
<p><b>вся схема:</b> список всех конституент схемы</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(DependencyMode.EXPRESSION)}>
|
||||||
|
<p><b>выражение:</b> список идентификаторов из выражения</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(DependencyMode.OUTPUTS)}>
|
||||||
|
<p><b>потребители:</b> конституенты, ссылающиеся на данную</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(DependencyMode.INPUTS)}>
|
||||||
|
<p><b>поставщики:</b> конституенты, на которые ссылается данная</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(DependencyMode.EXPAND_OUTPUTS)}>
|
||||||
|
<p><b>зависимые:</b> конституенты, зависящие по цепочке</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(DependencyMode.EXPAND_INPUTS)}>
|
||||||
|
<p><b>влияющие:</b> конституенты, влияющие на данную (цепочка)</p>
|
||||||
|
</DropdownButton>
|
||||||
|
</Dropdown>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// case DependencyMode.OUTPUTS: return 'потребители';
|
||||||
|
// case DependencyMode.INPUTS: return 'поставщики';
|
||||||
|
// case DependencyMode.EXPAND_INPUTS: return 'влияющие';
|
||||||
|
// case DependencyMode.EXPAND_OUTPUTS: return 'зависимые';
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DependencyModePicker;
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import Dropdown from '../../../components/Common/Dropdown';
|
||||||
|
import DropdownButton from '../../../components/Common/DropdownButton';
|
||||||
|
import useDropdown from '../../../hooks/useDropdown';
|
||||||
|
import { CstMatchMode } from '../../../utils/models';
|
||||||
|
import { getCstCompareLabel } from '../../../utils/staticUI';
|
||||||
|
|
||||||
|
interface MatchModePickerProps {
|
||||||
|
value: CstMatchMode
|
||||||
|
onChange: (value: CstMatchMode) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
function MatchModePicker({ value, onChange }: MatchModePickerProps) {
|
||||||
|
const pickerMenu = useDropdown();
|
||||||
|
|
||||||
|
const handleChange = useCallback(
|
||||||
|
(newValue: CstMatchMode) => {
|
||||||
|
pickerMenu.hide();
|
||||||
|
onChange(newValue);
|
||||||
|
}, [pickerMenu, onChange]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={pickerMenu.ref}>
|
||||||
|
<span
|
||||||
|
className='text-sm font-semibold underline cursor-pointer select-none whitespace-nowrap'
|
||||||
|
tabIndex={-1}
|
||||||
|
onClick={pickerMenu.toggle}
|
||||||
|
>
|
||||||
|
{getCstCompareLabel(value)}
|
||||||
|
</span>
|
||||||
|
{ pickerMenu.isActive &&
|
||||||
|
<Dropdown>
|
||||||
|
<DropdownButton onClick={() => handleChange(CstMatchMode.ALL)}>
|
||||||
|
<p><b>везде:</b> искать во всех атрибутах</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(CstMatchMode.EXPR)}>
|
||||||
|
<p><b>ФВ:</b> искать в формальных выражениях</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(CstMatchMode.TERM)}>
|
||||||
|
<p><b>термин:</b> искать в терминах</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(CstMatchMode.TEXT)}>
|
||||||
|
<p><b>текст:</b> искать в определениях и конвенциях</p>
|
||||||
|
</DropdownButton>
|
||||||
|
<DropdownButton onClick={() => handleChange(CstMatchMode.NAME)}>
|
||||||
|
<p><b>ID:</b> искать в идентификаторах конституент</p>
|
||||||
|
</DropdownButton>
|
||||||
|
</Dropdown>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MatchModePicker;
|
|
@ -1,14 +1,15 @@
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import Checkbox from '../../../components/Common/Checkbox';
|
|
||||||
import ConceptDataTable from '../../../components/Common/ConceptDataTable';
|
import ConceptDataTable from '../../../components/Common/ConceptDataTable';
|
||||||
import { useRSForm } from '../../../context/RSFormContext';
|
import { useRSForm } from '../../../context/RSFormContext';
|
||||||
import { useConceptTheme } from '../../../context/ThemeContext';
|
import { useConceptTheme } from '../../../context/ThemeContext';
|
||||||
import useLocalStorage from '../../../hooks/useLocalStorage';
|
import useLocalStorage from '../../../hooks/useLocalStorage';
|
||||||
import { prefixes } from '../../../utils/constants';
|
import { prefixes } from '../../../utils/constants';
|
||||||
import { CstType, extractGlobals,type IConstituenta, matchConstituenta } from '../../../utils/models';
|
import { applyGraphFilter, CstMatchMode, CstType, DependencyMode, extractGlobals, IConstituenta, matchConstituenta } from '../../../utils/models';
|
||||||
import { getCstDescription, getMockConstituenta, mapStatusInfo } from '../../../utils/staticUI';
|
import { getCstDescription, getMockConstituenta, mapStatusInfo } from '../../../utils/staticUI';
|
||||||
import ConstituentaTooltip from './ConstituentaTooltip';
|
import ConstituentaTooltip from './ConstituentaTooltip';
|
||||||
|
import DependencyModePicker from './DependencyModePicker';
|
||||||
|
import MatchModePicker from './MatchModePicker';
|
||||||
|
|
||||||
interface ViewSideConstituentsProps {
|
interface ViewSideConstituentsProps {
|
||||||
expression: string
|
expression: string
|
||||||
|
@ -19,31 +20,38 @@ interface ViewSideConstituentsProps {
|
||||||
function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideConstituentsProps) {
|
function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideConstituentsProps) {
|
||||||
const { darkMode } = useConceptTheme();
|
const { darkMode } = useConceptTheme();
|
||||||
const { schema } = useRSForm();
|
const { schema } = useRSForm();
|
||||||
|
|
||||||
|
const [filterMatch, setFilterMatch] = useLocalStorage('side-filter-match', CstMatchMode.ALL);
|
||||||
|
const [filterText, setFilterText] = useLocalStorage('side-filter-text', '');
|
||||||
|
const [filterSource, setFilterSource] = useLocalStorage('side-filter-dependency', DependencyMode.ALL);
|
||||||
|
|
||||||
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);
|
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);
|
||||||
const [filterText, setFilterText] = useLocalStorage('side-filter-text', '')
|
|
||||||
const [onlyExpression, setOnlyExpression] = useLocalStorage('side-filter-flag', false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!schema?.items) {
|
if (!schema?.items) {
|
||||||
setFilteredData([]);
|
setFilteredData([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (onlyExpression) {
|
let filtered: IConstituenta[] = [];
|
||||||
|
if (filterSource === DependencyMode.EXPRESSION) {
|
||||||
const aliases = extractGlobals(expression);
|
const aliases = extractGlobals(expression);
|
||||||
const filtered = schema?.items.filter((cst) => aliases.has(cst.alias));
|
filtered = schema.items.filter((cst) => aliases.has(cst.alias));
|
||||||
const names = filtered.map(cst => cst.alias)
|
const names = filtered.map(cst => cst.alias)
|
||||||
const diff = Array.from(aliases).filter(name => !names.includes(name));
|
const diff = Array.from(aliases).filter(name => !names.includes(name));
|
||||||
if (diff.length > 0) {
|
if (diff.length > 0) {
|
||||||
diff.forEach(
|
diff.forEach(
|
||||||
(alias, index) => filtered.push(getMockConstituenta(-index, alias, CstType.BASE, 'Конституента отсутствует')));
|
(alias, index) => filtered.push(getMockConstituenta(-index, alias, CstType.BASE, 'Конституента отсутствует')));
|
||||||
}
|
}
|
||||||
setFilteredData(filtered);
|
} else if (!activeID) {
|
||||||
} else if (!filterText) {
|
filtered = schema.items
|
||||||
setFilteredData(schema?.items);
|
|
||||||
} else {
|
} else {
|
||||||
setFilteredData(schema?.items.filter((cst) => matchConstituenta(filterText, cst)));
|
filtered = applyGraphFilter(schema, activeID, filterSource);
|
||||||
}
|
}
|
||||||
}, [filterText, setFilteredData, onlyExpression, expression, schema]);
|
if (filterText) {
|
||||||
|
filtered = filtered.filter((cst) => matchConstituenta(filterText, cst, filterMatch));
|
||||||
|
}
|
||||||
|
setFilteredData(filtered);
|
||||||
|
}, [filterText, setFilteredData, filterSource, expression, schema, filterMatch, activeID]);
|
||||||
|
|
||||||
const handleRowClicked = useCallback(
|
const handleRowClicked = useCallback(
|
||||||
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
(cst: IConstituenta, event: React.MouseEvent<Element, MouseEvent>) => {
|
||||||
|
@ -130,25 +138,19 @@ function ViewSideConstituents({ expression, activeID, onOpenEdit }: ViewSideCons
|
||||||
}
|
}
|
||||||
], []
|
], []
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='max-h-[80vh] overflow-y-scroll border flex-grow w-full'>
|
<div className='max-h-[80vh] min-h-[40rem] overflow-y-scroll border flex-grow w-full'>
|
||||||
<div className='sticky top-0 left-0 right-0 z-10 flex items-center justify-between w-full gap-1 px-2 py-1 bg-white border-b-2 border-gray-400 rounded dark:bg-gray-700 dark:border-gray-300'>
|
<div className='sticky top-0 left-0 right-0 z-10 flex items-center justify-between w-full gap-1 px-2 py-1 bg-white border-b-2 border-gray-400 rounded dark:bg-gray-700 dark:border-gray-300'>
|
||||||
<div className='w-full'>
|
<div className='flex items-center justify-between w-full'>
|
||||||
|
<MatchModePicker value={filterMatch} onChange={setFilterMatch}/>
|
||||||
<input type='text'
|
<input type='text'
|
||||||
className='w-full px-2 outline-none dark:bg-gray-700 hover:text-clip'
|
className='w-full px-2 outline-none dark:bg-gray-700 hover:text-clip'
|
||||||
placeholder='текст для фильтрации списка'
|
placeholder='наберите текст фильтра'
|
||||||
value={filterText}
|
value={filterText}
|
||||||
onChange={event => { setFilterText(event.target.value); }}
|
onChange={event => { setFilterText(event.target.value); }}
|
||||||
disabled={onlyExpression}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='w-fit min-w-[8rem]'>
|
|
||||||
<Checkbox
|
|
||||||
label='из выражения'
|
|
||||||
value={onlyExpression}
|
|
||||||
onChange={event => { setOnlyExpression(event.target.checked); }}
|
|
||||||
/>
|
/>
|
||||||
|
<DependencyModePicker value={filterSource} onChange={setFilterSource}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ConceptDataTable
|
<ConceptDataTable
|
||||||
|
|
|
@ -226,6 +226,25 @@ export enum ExpressionStatus {
|
||||||
VERIFIED
|
VERIFIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dependency mode for schema analysis
|
||||||
|
export enum DependencyMode {
|
||||||
|
ALL = 0,
|
||||||
|
EXPRESSION,
|
||||||
|
OUTPUTS,
|
||||||
|
INPUTS,
|
||||||
|
EXPAND_OUTPUTS,
|
||||||
|
EXPAND_INPUTS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constituent compare mode
|
||||||
|
export enum CstMatchMode {
|
||||||
|
ALL = 1,
|
||||||
|
EXPR,
|
||||||
|
TERM,
|
||||||
|
TEXT,
|
||||||
|
NAME
|
||||||
|
}
|
||||||
|
|
||||||
// ========== Model functions =================
|
// ========== Model functions =================
|
||||||
export function inferStatus(parse?: ParsingStatus, value?: ValueClass): ExpressionStatus {
|
export function inferStatus(parse?: ParsingStatus, value?: ValueClass): ExpressionStatus {
|
||||||
if (!parse || !value) {
|
if (!parse || !value) {
|
||||||
|
@ -317,22 +336,23 @@ export function LoadRSFormData(schema: IRSFormData): IRSForm {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function matchConstituenta(query: string, target?: IConstituenta) {
|
export function matchConstituenta(query: string, target: IConstituenta, mode: CstMatchMode) {
|
||||||
if (!target) {
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
|
||||||
return false;
|
target.alias.match(query)) {
|
||||||
} else if (target.alias.match(query)) {
|
|
||||||
return true;
|
return true;
|
||||||
} else if (target.term.resolved.match(query)) {
|
|
||||||
return true;
|
|
||||||
} else if (target.definition.formal.match(query)) {
|
|
||||||
return true;
|
|
||||||
} else if (target.definition.text.resolved.match(query)) {
|
|
||||||
return true;
|
|
||||||
} else if (target.convention.match(query)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TERM) &&
|
||||||
|
target.term.resolved.match(query)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.EXPR) &&
|
||||||
|
target.definition.formal.match(query)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.TEXT)) {
|
||||||
|
return (target.definition.text.resolved.match(query) || target.convention.match(query));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function matchRSFormMeta(query: string, target: IRSFormMeta) {
|
export function matchRSFormMeta(query: string, target: IRSFormMeta) {
|
||||||
|
@ -345,3 +365,21 @@ export function matchRSFormMeta(query: string, target: IRSFormMeta) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function applyGraphFilter(schema: IRSForm, start: number, mode: DependencyMode): IConstituenta[] {
|
||||||
|
if (mode === DependencyMode.ALL) {
|
||||||
|
return schema.items;
|
||||||
|
}
|
||||||
|
let ids: number[] | undefined = undefined
|
||||||
|
switch (mode) {
|
||||||
|
case DependencyMode.OUTPUTS: { ids = schema.graph.nodes.get(start)?.outputs; break; }
|
||||||
|
case DependencyMode.INPUTS: { ids = schema.graph.nodes.get(start)?.inputs; break; }
|
||||||
|
case DependencyMode.EXPAND_OUTPUTS: { ids = schema.graph.expandOutputs([start]) ; break; }
|
||||||
|
case DependencyMode.EXPAND_INPUTS: { ids = schema.graph.expandInputs([start]) ; break; }
|
||||||
|
}
|
||||||
|
if (!ids) {
|
||||||
|
return schema.items;
|
||||||
|
} else {
|
||||||
|
return schema.items.filter(cst => ids!.find(id => id === cst.id));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { LayoutTypes } from 'reagraph';
|
import { LayoutTypes } from 'reagraph';
|
||||||
|
|
||||||
import { resolveErrorClass,RSErrorClass, RSErrorType, TokenID } from './enums';
|
import { resolveErrorClass,RSErrorClass, RSErrorType, TokenID } from './enums';
|
||||||
import { CstType, ExpressionStatus, type IConstituenta, IRSErrorDescription,type IRSForm, ISyntaxTreeNode,ParsingStatus, ValueClass } from './models';
|
import { CstMatchMode,CstType, DependencyMode,ExpressionStatus, type IConstituenta, IRSErrorDescription,type IRSForm, ISyntaxTreeNode,ParsingStatus, ValueClass } from './models';
|
||||||
|
|
||||||
export interface IRSButtonData {
|
export interface IRSButtonData {
|
||||||
text: string
|
text: string
|
||||||
|
@ -273,6 +273,27 @@ export const mapLayoutLabels: Map<string, string> = new Map([
|
||||||
['nooverlap', 'Без перекрытия']
|
['nooverlap', 'Без перекрытия']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export function getCstCompareLabel(mode: CstMatchMode): string {
|
||||||
|
switch(mode) {
|
||||||
|
case CstMatchMode.ALL: return 'везде';
|
||||||
|
case CstMatchMode.EXPR: return 'ФВ';
|
||||||
|
case CstMatchMode.TERM: return 'термин';
|
||||||
|
case CstMatchMode.TEXT: return 'текст';
|
||||||
|
case CstMatchMode.NAME: return 'ID';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDependencyLabel(mode: DependencyMode): string {
|
||||||
|
switch(mode) {
|
||||||
|
case DependencyMode.ALL: return 'вся схема';
|
||||||
|
case DependencyMode.EXPRESSION: return 'выражение';
|
||||||
|
case DependencyMode.OUTPUTS: return 'потребители';
|
||||||
|
case DependencyMode.INPUTS: return 'поставщики';
|
||||||
|
case DependencyMode.EXPAND_INPUTS: return 'влияющие';
|
||||||
|
case DependencyMode.EXPAND_OUTPUTS: return 'зависимые';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const GraphLayoutSelector: {value: LayoutTypes, label: string}[] = [
|
export const GraphLayoutSelector: {value: LayoutTypes, label: string}[] = [
|
||||||
{ value: 'forceatlas2', label: 'Атлас 2D'},
|
{ value: 'forceatlas2', label: 'Атлас 2D'},
|
||||||
{ value: 'forceDirected2d', label: 'Силы 2D'},
|
{ value: 'forceDirected2d', label: 'Силы 2D'},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user