mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
Rework Search panels UI
This commit is contained in:
parent
a44a43214c
commit
8d062baa8b
2
TODO.txt
2
TODO.txt
|
@ -12,7 +12,7 @@ For more specific TODOs see comments in code
|
|||
- система обработки ошибок backend
|
||||
|
||||
[Tech]
|
||||
- reload react-data-table-component
|
||||
- multilevel modals / rework modal system
|
||||
|
||||
[deployment]
|
||||
- logs collection
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
interface ButtonProps
|
||||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children' | 'title'> {
|
||||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children' | 'title'| 'type'> {
|
||||
text?: string
|
||||
icon?: React.ReactNode
|
||||
tooltip?: string
|
||||
|
@ -11,21 +11,19 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'child
|
|||
}
|
||||
|
||||
function Button({
|
||||
id, text, icon, tooltip,
|
||||
text, icon, tooltip,
|
||||
dense, disabled,
|
||||
borderClass = 'border rounded',
|
||||
colorClass = 'clr-btn-default',
|
||||
dimensions = 'w-fit h-fit',
|
||||
loading, onClick,
|
||||
loading,
|
||||
...props
|
||||
}: ButtonProps) {
|
||||
const padding = dense ? 'px-1' : 'px-3 py-2';
|
||||
const cursor = 'disabled:cursor-not-allowed ' + (loading ? 'cursor-progress ' : 'cursor-pointer ');
|
||||
return (
|
||||
<button id={id}
|
||||
type='button'
|
||||
<button type='button'
|
||||
disabled={disabled ?? loading}
|
||||
onClick={onClick}
|
||||
title={tooltip}
|
||||
className={`inline-flex items-center gap-2 align-middle justify-center select-none ${padding} ${colorClass} ${dimensions} ${borderClass} ${cursor}`}
|
||||
{...props}
|
||||
|
|
34
rsconcept/frontend/src/components/Common/SelectorButton.tsx
Normal file
34
rsconcept/frontend/src/components/Common/SelectorButton.tsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
interface SelectorButtonProps
|
||||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children' | 'title' | 'type'> {
|
||||
text?: string
|
||||
icon?: React.ReactNode
|
||||
tooltip?: string
|
||||
dimensions?: string
|
||||
borderClass?: string
|
||||
colorClass?: string
|
||||
transparent?: boolean
|
||||
}
|
||||
|
||||
|
||||
function SelectorButton({
|
||||
text, icon, tooltip,
|
||||
colorClass = 'clr-btn-default',
|
||||
dimensions = 'w-fit h-fit',
|
||||
transparent,
|
||||
...props
|
||||
}: SelectorButtonProps) {
|
||||
const cursor = 'disabled:cursor-not-allowed cursor-pointer';
|
||||
const position = `px-1 flex flex-start items-center gap-1 ${dimensions}`
|
||||
return (
|
||||
<button type='button'
|
||||
className={`text-sm small-caps ${!transparent && 'border'} ${cursor} ${position} text-btn text-controls ${!transparent && colorClass}`}
|
||||
title={tooltip}
|
||||
{...props}
|
||||
>
|
||||
{icon && icon}
|
||||
{text && <div className={'font-semibold whitespace-nowrap pb-1'}>{text}</div>}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectorButton;
|
|
@ -16,7 +16,7 @@ import SelectMulti from '../Common/SelectMulti';
|
|||
import TextInput from '../Common/TextInput';
|
||||
import DataTable, { IConditionalStyle } from '../DataTable';
|
||||
import HelpTerminologyControl from '../Help/HelpTerminologyControl';
|
||||
import { HelpIcon } from '../Icons';
|
||||
import { HelpIcon, MagnifyingGlassIcon } from '../Icons';
|
||||
import ReferenceTypeButton from './ReferenceTypeButton';
|
||||
import WordformButton from './WordformButton';
|
||||
|
||||
|
@ -284,12 +284,17 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
|||
</div>}
|
||||
{type === ReferenceType.ENTITY &&
|
||||
<div className='flex flex-col gap-2'>
|
||||
<TextInput
|
||||
dimensions='w-full'
|
||||
placeholder='текст фильтра'
|
||||
value={filter}
|
||||
onChange={event => setFilter(event.target.value)}
|
||||
/>
|
||||
<div className='relative'>
|
||||
<div className='absolute inset-y-0 flex items-center pl-3 pointer-events-none text-controls'>
|
||||
<MagnifyingGlassIcon />
|
||||
</div>
|
||||
<TextInput
|
||||
dimensions='w-full pl-10'
|
||||
placeholder='Поиск'
|
||||
value={filter}
|
||||
onChange={event => setFilter(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className='border min-h-[15.5rem] max-h-[15.5rem] text-sm overflow-y-auto'>
|
||||
<DataTable
|
||||
data={filteredData}
|
||||
|
@ -311,8 +316,9 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
|||
</div>
|
||||
<div className='flex gap-4 flex-start'>
|
||||
<TextInput
|
||||
label='Отсылаемый идентификатор'
|
||||
dimensions='max-w-[18rem] min-w-[18rem] whitespace-nowrap'
|
||||
label='Отсылаемая конституента'
|
||||
dimensions='max-w-[16rem] min-w-[16rem] whitespace-nowrap'
|
||||
placeholder='Имя'
|
||||
singleRow
|
||||
value={alias}
|
||||
onChange={event => setAlias(event.target.value)}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { useCallback } from 'react';
|
||||
|
||||
import Button from '../../components/Common/Button';
|
||||
import Dropdown from '../../components/Common/Dropdown';
|
||||
import DropdownCheckbox from '../../components/Common/DropdownCheckbox';
|
||||
import SelectorButton from '../../components/Common/SelectorButton';
|
||||
import { FilterCogIcon } from '../../components/Icons';
|
||||
import { useAuth } from '../../context/AuthContext';
|
||||
import useDropdown from '../../hooks/useDropdown';
|
||||
import { LibraryFilterStrategy } from '../../models/miscelanious';
|
||||
import { prefixes } from '../../utils/constants';
|
||||
import { describeLibraryFilter, labelLibraryFilter } from '../../utils/labels';
|
||||
|
||||
interface PickerStrategyProps {
|
||||
value: LibraryFilterStrategy
|
||||
|
@ -14,65 +16,52 @@ interface PickerStrategyProps {
|
|||
}
|
||||
|
||||
function PickerStrategy({ value, onChange }: PickerStrategyProps) {
|
||||
const pickerMenu = useDropdown();
|
||||
const strategyMenu = useDropdown();
|
||||
const { user } = useAuth();
|
||||
|
||||
const handleChange = useCallback(
|
||||
(newValue: LibraryFilterStrategy) => {
|
||||
pickerMenu.hide();
|
||||
strategyMenu.hide();
|
||||
onChange(newValue);
|
||||
}, [pickerMenu, onChange]);
|
||||
}, [strategyMenu, onChange]);
|
||||
|
||||
function isStrategyDisabled(strategy: LibraryFilterStrategy): boolean {
|
||||
if (
|
||||
strategy === LibraryFilterStrategy.PERSONAL ||
|
||||
strategy === LibraryFilterStrategy.SUBSCRIBE ||
|
||||
strategy === LibraryFilterStrategy.OWNED
|
||||
) {
|
||||
return !user;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={pickerMenu.ref} className='h-full text-right'>
|
||||
<Button
|
||||
icon={<FilterCogIcon color='text-controls' size={6} />}
|
||||
dense
|
||||
tooltip='Фильтры'
|
||||
colorClass='clr-input clr-hover text-btn'
|
||||
dimensions='h-full py-1 px-2 border-none'
|
||||
onClick={pickerMenu.toggle}
|
||||
<div ref={strategyMenu.ref} className='h-full text-right'>
|
||||
<SelectorButton
|
||||
tooltip='Список фильтров'
|
||||
transparent
|
||||
icon={<FilterCogIcon size={5} />}
|
||||
text={labelLibraryFilter(value)}
|
||||
tabIndex={-1}
|
||||
onClick={strategyMenu.toggle}
|
||||
/>
|
||||
{ pickerMenu.isActive &&
|
||||
{ strategyMenu.isActive &&
|
||||
<Dropdown>
|
||||
<DropdownCheckbox
|
||||
setValue={() => handleChange(LibraryFilterStrategy.MANUAL)}
|
||||
value={value === LibraryFilterStrategy.MANUAL}
|
||||
label='Отображать все'
|
||||
/>
|
||||
<DropdownCheckbox
|
||||
setValue={() => handleChange(LibraryFilterStrategy.COMMON)}
|
||||
value={value === LibraryFilterStrategy.COMMON}
|
||||
label='Общедоступные'
|
||||
tooltip='Отображать только общедоступные схемы'
|
||||
/>
|
||||
<DropdownCheckbox
|
||||
setValue={() => handleChange(LibraryFilterStrategy.CANONICAL)}
|
||||
value={value === LibraryFilterStrategy.CANONICAL}
|
||||
label='Неизменные'
|
||||
tooltip='Отображать только стандартные схемы'
|
||||
/>
|
||||
<DropdownCheckbox
|
||||
setValue={() => handleChange(LibraryFilterStrategy.PERSONAL)}
|
||||
value={value === LibraryFilterStrategy.PERSONAL}
|
||||
label='Личные'
|
||||
disabled={!user}
|
||||
tooltip='Отображать только подписки и владеемые схемы'
|
||||
/>
|
||||
<DropdownCheckbox
|
||||
setValue={() => handleChange(LibraryFilterStrategy.SUBSCRIBE)}
|
||||
value={value === LibraryFilterStrategy.SUBSCRIBE}
|
||||
label='Подписки'
|
||||
disabled={!user}
|
||||
tooltip='Отображать только подписки'
|
||||
/>
|
||||
<DropdownCheckbox
|
||||
setValue={() => handleChange(LibraryFilterStrategy.OWNED)}
|
||||
value={value === LibraryFilterStrategy.OWNED}
|
||||
disabled={!user}
|
||||
label='Я - Владелец!'
|
||||
tooltip='Отображать только владеемые схемы'
|
||||
/>
|
||||
{ Object.values(LibraryFilterStrategy).map(
|
||||
(enumValue, index) => {
|
||||
const strategy = enumValue as LibraryFilterStrategy;
|
||||
return (
|
||||
<DropdownCheckbox
|
||||
key={`${prefixes.library_filters_list}${index}`}
|
||||
value={value === strategy}
|
||||
setValue={() => handleChange(strategy)}
|
||||
label={labelLibraryFilter(strategy)}
|
||||
tooltip={describeLibraryFilter(strategy)}
|
||||
disabled={isStrategyDisabled(strategy)}
|
||||
/>);
|
||||
})}
|
||||
</Dropdown>}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -76,12 +76,8 @@ function SearchPanel({ total, filtered, query, setQuery, strategy, setStrategy,
|
|||
{filtered} из {total}
|
||||
</span>
|
||||
</div>
|
||||
<div className='flex items-center justify-center w-full ml-8'>
|
||||
<PickerStrategy
|
||||
value={strategy}
|
||||
onChange={handleChangeStrategy}
|
||||
/>
|
||||
<div className='relative w-96 min-w-[10rem] select-none'>
|
||||
<div className='flex items-center justify-center w-full gap-1'>
|
||||
<div className='relative min-w-[10rem] select-none'>
|
||||
<div className='absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-controls'>
|
||||
<MagnifyingGlassIcon />
|
||||
</div>
|
||||
|
@ -89,10 +85,14 @@ function SearchPanel({ total, filtered, query, setQuery, strategy, setStrategy,
|
|||
type='text'
|
||||
value={query}
|
||||
className='w-full p-2 pl-10 text-sm outline-none clr-input'
|
||||
placeholder='Поиск схемы...'
|
||||
placeholder='Поиск'
|
||||
onChange={handleChangeQuery}
|
||||
/>
|
||||
</div>
|
||||
<PickerStrategy
|
||||
value={strategy}
|
||||
onChange={handleChangeStrategy}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
import { useCallback } from 'react';
|
||||
|
||||
import Dropdown from '../../../components/Common/Dropdown';
|
||||
import DropdownButton from '../../../components/Common/DropdownButton';
|
||||
import { CogIcon } from '../../../components/Icons';
|
||||
import useDropdown from '../../../hooks/useDropdown';
|
||||
import { DependencyMode } from '../../../models/miscelanious';
|
||||
import { labelDependencyMode } from '../../../utils/labels';
|
||||
|
||||
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} className='h-full'>
|
||||
<button
|
||||
className='h-full w-[7.5rem] px-1 py-1 border clr-input clr-hover clr-btn-default text-btn inline-flex align-middle gap-1'
|
||||
title='Настройка фильтрации по графу термов'
|
||||
tabIndex={-1}
|
||||
onClick={pickerMenu.toggle}
|
||||
>
|
||||
<CogIcon color='text-controls' size={5} />
|
||||
<span className='text-sm font-semibold whitespace-nowrap'>{labelDependencyMode(value)}</span>
|
||||
</button>
|
||||
{ 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>
|
||||
);
|
||||
}
|
||||
|
||||
export default DependencyModePicker;
|
|
@ -1,58 +0,0 @@
|
|||
import { useCallback } from 'react';
|
||||
|
||||
import Dropdown from '../../../components/Common/Dropdown';
|
||||
import DropdownButton from '../../../components/Common/DropdownButton';
|
||||
import { FilterCogIcon } from '../../../components/Icons';
|
||||
import useDropdown from '../../../hooks/useDropdown';
|
||||
import { CstMatchMode } from '../../../models/miscelanious';
|
||||
import { labelCstMathchMode } from '../../../utils/labels';
|
||||
|
||||
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} className='h-full'>
|
||||
<button
|
||||
className='h-full w-[6rem] px-1 py-1 border clr-input clr-hover clr-btn-default text-btn inline-flex align-middle gap-1'
|
||||
title='Настройка атрибутов для фильтрации'
|
||||
tabIndex={-1}
|
||||
onClick={pickerMenu.toggle}
|
||||
>
|
||||
<FilterCogIcon color='text-controls' size={5} />
|
||||
<span className='text-sm font-semibold whitespace-nowrap'>{labelCstMathchMode(value)}</span>
|
||||
</button>
|
||||
{ pickerMenu.isActive &&
|
||||
<Dropdown stretchLeft>
|
||||
<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>имя:</b> искать в идентификаторах конституент</p>
|
||||
</DropdownButton>
|
||||
</Dropdown>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MatchModePicker;
|
|
@ -1,22 +1,28 @@
|
|||
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 { MagnifyingGlassIcon } from '../../../components/Icons';
|
||||
import { CogIcon, FilterCogIcon, 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 } from '../../../models/miscelanious';
|
||||
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 } from '../../../utils/labels';
|
||||
import {
|
||||
describeConstituenta, describeCstMathchMode,
|
||||
describeCstSource, labelCstMathchMode,
|
||||
labelCstSource
|
||||
} from '../../../utils/labels';
|
||||
import ConstituentaTooltip from './ConstituentaTooltip';
|
||||
import DependencyModePicker from './DependencyModePicker';
|
||||
import MatchModePicker from './MatchModePicker';
|
||||
|
||||
// Height that should be left to accomodate navigation panel + bottom margin
|
||||
const LOCAL_NAVIGATION_H = '2.1rem';
|
||||
|
@ -46,10 +52,13 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
|||
|
||||
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 [filterSource, setFilterSource] = useLocalStorage('side-filter-dependency', CstSource.ALL);
|
||||
|
||||
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);
|
||||
|
||||
const matchModeMenu = useDropdown();
|
||||
const sourceMenu = useDropdown();
|
||||
|
||||
useLayoutEffect(
|
||||
() => {
|
||||
setColumnVisibility(prev => {
|
||||
|
@ -69,7 +78,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
|||
return;
|
||||
}
|
||||
let filtered: IConstituenta[] = [];
|
||||
if (filterSource === DependencyMode.EXPRESSION) {
|
||||
if (filterSource === CstSource.EXPRESSION) {
|
||||
const aliases = extractGlobals(expression);
|
||||
filtered = schema.items.filter((cst) => aliases.has(cst.alias));
|
||||
const names = filtered.map(cst => cst.alias)
|
||||
|
@ -113,6 +122,18 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
|||
}
|
||||
}, [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', {
|
||||
|
@ -196,18 +217,59 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
|||
</div>
|
||||
<input type='text'
|
||||
className='w-[14rem] pr-2 pl-8 py-1 outline-none select-none hover:text-clip clr-input'
|
||||
placeholder='текст фильтра'
|
||||
placeholder='Поиск'
|
||||
value={filterText}
|
||||
onChange={event => setFilterText(event.target.value)}
|
||||
/>
|
||||
<MatchModePicker
|
||||
value={filterMatch}
|
||||
onChange={setFilterMatch}
|
||||
/>
|
||||
<DependencyModePicker
|
||||
value={filterSource}
|
||||
onChange={setFilterSource}
|
||||
/>
|
||||
<div ref={matchModeMenu.ref}>
|
||||
<SelectorButton
|
||||
tooltip='Настройка атрибутов для фильтрации'
|
||||
transparent
|
||||
icon={<FilterCogIcon size={5} />}
|
||||
text={labelCstMathchMode(filterMatch)}
|
||||
tabIndex={-1}
|
||||
onClick={matchModeMenu.toggle}
|
||||
/>
|
||||
{ matchModeMenu.isActive &&
|
||||
<Dropdown stretchLeft>
|
||||
{ Object.values(CstMatchMode).filter(value => !isNaN(Number(value))).map(
|
||||
(value, index) => {
|
||||
const matchMode = value as CstMatchMode;
|
||||
return (
|
||||
<DropdownButton
|
||||
key={`${prefixes.cst_match_mode_list}${index}`}
|
||||
onClick={() => handleMatchModeChange(matchMode)}
|
||||
>
|
||||
<p><span className='font-semibold'>{labelCstMathchMode(matchMode)}:</span> {describeCstMathchMode(matchMode)}</p>
|
||||
</DropdownButton>);
|
||||
})}
|
||||
</Dropdown>}
|
||||
</div>
|
||||
|
||||
<div ref={sourceMenu.ref}>
|
||||
<SelectorButton
|
||||
tooltip='Настройка фильтрации по графу термов'
|
||||
transparent
|
||||
icon={<CogIcon size={4} />}
|
||||
text={labelCstSource(filterSource)}
|
||||
tabIndex={-1}
|
||||
onClick={sourceMenu.toggle}
|
||||
/>
|
||||
{ sourceMenu.isActive &&
|
||||
<Dropdown stretchLeft>
|
||||
{ Object.values(CstSource).filter(value => !isNaN(Number(value))).map(
|
||||
(value, index) => {
|
||||
const source = value as CstSource;
|
||||
return (
|
||||
<DropdownButton
|
||||
key={`${prefixes.cst_source_list}${index}`}
|
||||
onClick={() => handleSourceChange(source)}
|
||||
>
|
||||
<p><span className='font-semibold'>{labelCstSource(source)}:</span> {describeCstSource(source)}</p>
|
||||
</DropdownButton>);
|
||||
})}
|
||||
</Dropdown>}
|
||||
</div>
|
||||
</div>
|
||||
<div className='overflow-y-auto text-sm' style={{maxHeight : `${maxHeight}`}}>
|
||||
<DataTable
|
||||
|
|
|
@ -36,6 +36,9 @@ export const prefixes = {
|
|||
cst_list: 'cst-list-',
|
||||
cst_wordform_list: 'cst-wordform-list-',
|
||||
cst_status_list: 'cst-status-list-',
|
||||
cst_match_mode_list: 'cst-match-mode-list-',
|
||||
cst_source_list: 'cst-source-list-',
|
||||
library_filters_list: 'library-filters-list',
|
||||
topic_list: 'topic-list-',
|
||||
library_list: 'library-list-',
|
||||
wordform_list: 'wordform-list'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// =========== Modules contains all text descriptors ==========
|
||||
|
||||
import { GramData,Grammeme, ReferenceType } from '../models/language';
|
||||
import { CstMatchMode, DependencyMode, HelpTopic } from '../models/miscelanious';
|
||||
import { CstMatchMode, DependencyMode, HelpTopic, LibraryFilterStrategy } from '../models/miscelanious';
|
||||
import { CstClass, CstType, ExpressionStatus, IConstituenta } from '../models/rsform';
|
||||
import { IFunctionArg, IRSErrorDescription, ISyntaxTreeNode, ParsingStatus, RSErrorType, TokenID } from '../models/rslang';
|
||||
|
||||
|
@ -128,17 +128,27 @@ export function describeToken(id: TokenID): string {
|
|||
|
||||
export function labelCstMathchMode(mode: CstMatchMode): string {
|
||||
switch (mode) {
|
||||
case CstMatchMode.ALL: return 'везде';
|
||||
case CstMatchMode.EXPR: return 'выраж';
|
||||
case CstMatchMode.ALL: return 'общий';
|
||||
case CstMatchMode.EXPR: return 'выражение';
|
||||
case CstMatchMode.TERM: return 'термин';
|
||||
case CstMatchMode.TEXT: return 'текст';
|
||||
case CstMatchMode.NAME: return 'имя';
|
||||
}
|
||||
}
|
||||
|
||||
export function labelDependencyMode(mode: DependencyMode): string {
|
||||
export function describeCstMathchMode(mode: CstMatchMode): string {
|
||||
switch (mode) {
|
||||
case DependencyMode.ALL: return 'вся схема';
|
||||
case CstMatchMode.ALL: return 'искать во всех атрибутах';
|
||||
case CstMatchMode.EXPR: return 'искать в формальных выражениях';
|
||||
case CstMatchMode.TERM: return 'искать в терминах';
|
||||
case CstMatchMode.TEXT: return 'искать в определениях и конвенциях';
|
||||
case CstMatchMode.NAME: return 'искать в идентификаторах конституент';
|
||||
}
|
||||
}
|
||||
|
||||
export function labelCstSource(mode: DependencyMode): string {
|
||||
switch (mode) {
|
||||
case DependencyMode.ALL: return 'не ограничен';
|
||||
case DependencyMode.EXPRESSION: return 'выражение';
|
||||
case DependencyMode.OUTPUTS: return 'потребители';
|
||||
case DependencyMode.INPUTS: return 'поставщики';
|
||||
|
@ -147,6 +157,39 @@ export function labelDependencyMode(mode: DependencyMode): string {
|
|||
}
|
||||
}
|
||||
|
||||
export function describeCstSource(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 function labelLibraryFilter(strategy: LibraryFilterStrategy): string {
|
||||
switch (strategy) {
|
||||
case LibraryFilterStrategy.MANUAL: return 'отображать все';
|
||||
case LibraryFilterStrategy.COMMON: return 'общедоступные';
|
||||
case LibraryFilterStrategy.CANONICAL: return 'неизменные';
|
||||
case LibraryFilterStrategy.PERSONAL: return 'личные';
|
||||
case LibraryFilterStrategy.SUBSCRIBE: return 'подписки';
|
||||
case LibraryFilterStrategy.OWNED: return 'владелец';
|
||||
}
|
||||
}
|
||||
|
||||
export function describeLibraryFilter(strategy: LibraryFilterStrategy): string {
|
||||
switch (strategy) {
|
||||
case LibraryFilterStrategy.MANUAL: return 'Отображать все схемы';
|
||||
case LibraryFilterStrategy.COMMON: return 'Отображать общедоступные схемы';
|
||||
case LibraryFilterStrategy.CANONICAL: return 'Отображать стандартные схемы';
|
||||
case LibraryFilterStrategy.PERSONAL: return 'Отображать подписки и владеемые схемы';
|
||||
case LibraryFilterStrategy.SUBSCRIBE: return 'Отображать подписки';
|
||||
case LibraryFilterStrategy.OWNED: return 'Отображать владеемые схемы';
|
||||
}
|
||||
}
|
||||
|
||||
export const mapLableLayout: Map<string, string> =
|
||||
new Map([
|
||||
['forceatlas2', 'Граф: Атлас 2D'],
|
||||
|
|
Loading…
Reference in New Issue
Block a user