mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-08-14 21:00:37 +03:00
Refactor data tables and implement argument selection
This commit is contained in:
parent
cefd0d3c40
commit
cc79fffd34
|
@ -7,14 +7,15 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'title
|
||||||
}
|
}
|
||||||
|
|
||||||
function MiniButton({
|
function MiniButton({
|
||||||
icon, tooltip, noHover, tabIndex, dimensions,
|
icon, tooltip, noHover, tabIndex,
|
||||||
|
dimensions='w-fit h-fit',
|
||||||
...props
|
...props
|
||||||
}: MiniButtonProps) {
|
}: MiniButtonProps) {
|
||||||
return (
|
return (
|
||||||
<button type='button'
|
<button type='button'
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
tabIndex={tabIndex ?? -1}
|
tabIndex={tabIndex ?? -1}
|
||||||
className={`px-1 py-1 w-fit h-fit rounded-full cursor-pointer disabled:cursor-not-allowed clr-btn-clear ${noHover ? 'outline-none' : 'clr-hover'} ${dimensions}`}
|
className={`px-1 py-1 rounded-full cursor-pointer disabled:cursor-not-allowed clr-btn-clear ${noHover ? 'outline-none' : 'clr-hover'} ${dimensions}`}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
|
|
|
@ -19,8 +19,8 @@ function TextInput({
|
||||||
colors = 'clr-input',
|
colors = 'clr-input',
|
||||||
...props
|
...props
|
||||||
}: TextInputProps) {
|
}: TextInputProps) {
|
||||||
const borderClass = noBorder ? '': 'border';
|
const borderClass = noBorder ? '' : 'border';
|
||||||
const outlineClass = noOutline ? '': 'clr-outline';
|
const outlineClass = noOutline ? '' : 'clr-outline';
|
||||||
return (
|
return (
|
||||||
<div className={`flex ${dense ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
|
<div className={`flex ${dense ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
|
||||||
{label &&
|
{label &&
|
||||||
|
|
|
@ -48,6 +48,7 @@ extends Pick<ReactCodeMirrorProps,
|
||||||
'id' | 'height' | 'value' | 'className' | 'onFocus' | 'onBlur' | 'placeholder'
|
'id' | 'height' | 'value' | 'className' | 'onFocus' | 'onBlur' | 'placeholder'
|
||||||
> {
|
> {
|
||||||
label?: string
|
label?: string
|
||||||
|
dimensions?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
innerref?: RefObject<ReactCodeMirrorRef> | undefined
|
innerref?: RefObject<ReactCodeMirrorRef> | undefined
|
||||||
onChange?: (newValue: string) => void
|
onChange?: (newValue: string) => void
|
||||||
|
@ -55,6 +56,7 @@ extends Pick<ReactCodeMirrorProps,
|
||||||
|
|
||||||
function RSInput({
|
function RSInput({
|
||||||
id, label, innerref, onChange, disabled,
|
id, label, innerref, onChange, disabled,
|
||||||
|
dimensions = 'w-full',
|
||||||
...props
|
...props
|
||||||
}: RSInputProps) {
|
}: RSInputProps) {
|
||||||
const { darkMode, colors } = useConceptTheme();
|
const { darkMode, colors } = useConceptTheme();
|
||||||
|
@ -126,7 +128,7 @@ function RSInput({
|
||||||
}, [thisRef]);
|
}, [thisRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex flex-col w-full ${cursor}`}>
|
<div className={`flex flex-col ${dimensions} ${cursor}`}>
|
||||||
{label &&
|
{label &&
|
||||||
<Label
|
<Label
|
||||||
text={label}
|
text={label}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { IConstituenta, isMockCst } from '../../models/rsform';
|
||||||
|
import { colorfgCstStatus,IColorTheme } from '../../utils/color';
|
||||||
|
import { describeExpressionStatus } from '../../utils/labels';
|
||||||
|
import ConceptTooltip from '../Common/ConceptTooltip';
|
||||||
|
import ConstituentaTooltip from '../Help/ConstituentaTooltip';
|
||||||
|
|
||||||
|
interface ConstituentaBadgeProps {
|
||||||
|
prefixID?: string
|
||||||
|
shortTooltip?: boolean
|
||||||
|
value: IConstituenta
|
||||||
|
theme: IColorTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConstituentaBadge({ value, prefixID, shortTooltip, theme }: ConstituentaBadgeProps) {
|
||||||
|
return (<div className='w-fit'>
|
||||||
|
<div
|
||||||
|
id={`${prefixID}${value.alias}`}
|
||||||
|
className='min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
||||||
|
style={{
|
||||||
|
borderWidth: '1px',
|
||||||
|
borderColor: colorfgCstStatus(value.status, theme),
|
||||||
|
color: colorfgCstStatus(value.status, theme),
|
||||||
|
backgroundColor: isMockCst(value) ? theme.bgWarning : theme.bgInput,
|
||||||
|
fontWeight: 600
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{value.alias}
|
||||||
|
</div>
|
||||||
|
{ !shortTooltip && <ConstituentaTooltip data={value} anchor={`#${prefixID}${value.alias}`} />}
|
||||||
|
{ shortTooltip &&
|
||||||
|
<ConceptTooltip
|
||||||
|
anchorSelect={`#${prefixID}${value.alias}`}
|
||||||
|
place='right'
|
||||||
|
>
|
||||||
|
<p><span className='font-semibold'>Статус</span>: {describeExpressionStatus(value.status)}</p>
|
||||||
|
</ConceptTooltip>}
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConstituentaBadge;
|
108
rsconcept/frontend/src/components/Shared/ConstituentaPicker.tsx
Normal file
108
rsconcept/frontend/src/components/Shared/ConstituentaPicker.tsx
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
|
import { CstMatchMode } from '../../models/miscelanious';
|
||||||
|
import { IConstituenta, matchConstituenta } from '../../models/rsform';
|
||||||
|
import { prefixes } from '../../utils/constants';
|
||||||
|
import { describeConstituenta } from '../../utils/labels';
|
||||||
|
import ConceptSearch from '../Common/ConceptSearch';
|
||||||
|
import DataTable, { createColumnHelper,IConditionalStyle } from '../DataTable';
|
||||||
|
import ConstituentaBadge from './ConstituentaBadge';
|
||||||
|
|
||||||
|
interface ConstituentaPickerProps {
|
||||||
|
prefixID?: string
|
||||||
|
data?: IConstituenta[]
|
||||||
|
rows?: number
|
||||||
|
|
||||||
|
prefilterFunc?: (cst: IConstituenta) => boolean
|
||||||
|
describeFunc?: (cst: IConstituenta) => string
|
||||||
|
matchFunc?: (cst: IConstituenta, filter: string) => boolean
|
||||||
|
|
||||||
|
value?: IConstituenta
|
||||||
|
onSelectValue: (newValue: IConstituenta) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnHelper = createColumnHelper<IConstituenta>();
|
||||||
|
|
||||||
|
function ConstituentaPicker({
|
||||||
|
data, value,
|
||||||
|
rows = 4,
|
||||||
|
prefixID = prefixes.cst_list,
|
||||||
|
describeFunc = describeConstituenta,
|
||||||
|
matchFunc = (cst, filter) => matchConstituenta(cst, filter, CstMatchMode.ALL),
|
||||||
|
prefilterFunc,
|
||||||
|
onSelectValue
|
||||||
|
} : ConstituentaPickerProps) {
|
||||||
|
const { colors } = useConceptTheme();
|
||||||
|
const [ filteredData, setFilteredData ] = useState<IConstituenta[]>([]);
|
||||||
|
const [ filterText, setFilterText ] = useState('');
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
if (!data) {
|
||||||
|
setFilteredData([]);
|
||||||
|
} else {
|
||||||
|
const newData = prefilterFunc ? data.filter(prefilterFunc) : data;
|
||||||
|
if (filterText) {
|
||||||
|
setFilteredData(newData.filter(cst => matchFunc(cst, filterText)));
|
||||||
|
} else {
|
||||||
|
setFilteredData(newData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [data, filterText, matchFunc, prefilterFunc]);
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
columnHelper.accessor('alias', {
|
||||||
|
id: 'alias',
|
||||||
|
size: 65,
|
||||||
|
minSize: 65,
|
||||||
|
maxSize: 65,
|
||||||
|
cell: props =>
|
||||||
|
<ConstituentaBadge
|
||||||
|
theme={colors}
|
||||||
|
value={props.row.original}
|
||||||
|
prefixID={prefixID}
|
||||||
|
/>
|
||||||
|
}),
|
||||||
|
columnHelper.accessor(cst => describeFunc(cst), {
|
||||||
|
id: 'description'
|
||||||
|
})
|
||||||
|
], [colors, prefixID, describeFunc]);
|
||||||
|
|
||||||
|
const size = useMemo(() => (`${0.125 + 1.94*rows}rem`), [rows]);
|
||||||
|
|
||||||
|
const conditionalRowStyles = useMemo(
|
||||||
|
(): IConditionalStyle<IConstituenta>[] => [{
|
||||||
|
when: (cst: IConstituenta) => cst.id === value?.id,
|
||||||
|
style: { backgroundColor: colors.bgSelected },
|
||||||
|
}], [value, colors]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<ConceptSearch dense
|
||||||
|
value={filterText}
|
||||||
|
onChange={newValue => setFilterText(newValue)}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className='overflow-y-auto text-sm border select-none'
|
||||||
|
style={{ maxHeight: size, minHeight: size }}
|
||||||
|
>
|
||||||
|
<DataTable dense noHeader
|
||||||
|
data={filteredData}
|
||||||
|
columns={columns}
|
||||||
|
conditionalRowStyles={conditionalRowStyles}
|
||||||
|
noDataComponent={
|
||||||
|
<span className='flex flex-col justify-center p-2 text-center min-h-[5rem]'>
|
||||||
|
<p>Список конституент пуст</p>
|
||||||
|
<p>Измените параметры фильтра</p>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
onRowClicked={onSelectValue}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConstituentaPicker;
|
|
@ -1,28 +1,167 @@
|
||||||
import { Dispatch } from 'react';
|
import { createColumnHelper } from '@tanstack/react-table';
|
||||||
|
import { Dispatch, useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import ConceptSearch from '../../components/Common/ConceptSearch';
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
|
import DataTable, { IConditionalStyle } from '../../components/DataTable';
|
||||||
|
import { CheckIcon, CrossIcon } from '../../components/Icons';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
|
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
|
||||||
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
|
import { IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
import { IArgumentValue } from '../../models/rslang';
|
import { IArgumentValue } from '../../models/rslang';
|
||||||
|
import { prefixes } from '../../utils/constants';
|
||||||
|
|
||||||
interface ArgumentsTabProps {
|
interface ArgumentsTabProps {
|
||||||
state: IArgumentsState
|
state: IArgumentsState
|
||||||
|
schema: IRSForm
|
||||||
partialUpdate: Dispatch<Partial<IArgumentsState>>
|
partialUpdate: Dispatch<Partial<IArgumentsState>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IArgumentsState {
|
export interface IArgumentsState {
|
||||||
arguments?: IArgumentValue[]
|
arguments: IArgumentValue[]
|
||||||
filterText: string
|
|
||||||
definition: string
|
definition: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function ArgumentsTab({state, partialUpdate}: ArgumentsTabProps) {
|
const argumentsHelper = createColumnHelper<IArgumentValue>();
|
||||||
|
|
||||||
|
function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
||||||
|
const { colors } = useConceptTheme();
|
||||||
|
|
||||||
|
const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined);
|
||||||
|
const [selectedArgument, setSelectedArgument] = useState<IArgumentValue | undefined>(undefined);
|
||||||
|
|
||||||
|
const [argumentValue, setArgumentValue] = useState('');
|
||||||
|
|
||||||
|
const handleSelectArgument = useCallback(
|
||||||
|
(arg: IArgumentValue) => {
|
||||||
|
setSelectedArgument(arg);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSelectConstituenta = useCallback(
|
||||||
|
(cst: IConstituenta) => {
|
||||||
|
setSelectedCst(cst);
|
||||||
|
setArgumentValue(cst.alias);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClearArgument = useCallback(
|
||||||
|
(target: IArgumentValue) => {
|
||||||
|
target.value = '';
|
||||||
|
partialUpdate({
|
||||||
|
arguments: [
|
||||||
|
target,
|
||||||
|
...state.arguments.filter(arg => arg.alias !== target.alias)
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}, [partialUpdate, state.arguments]);
|
||||||
|
|
||||||
|
const handleAssignArgument = useCallback(
|
||||||
|
(target: IArgumentValue, value: string) => {
|
||||||
|
target.value = value;
|
||||||
|
partialUpdate({
|
||||||
|
arguments: [
|
||||||
|
target,
|
||||||
|
...state.arguments.filter(arg => arg.alias !== target.alias)
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}, [partialUpdate, state.arguments]);
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
argumentsHelper.accessor('alias', {
|
||||||
|
id: 'alias',
|
||||||
|
header: 'Имя',
|
||||||
|
size: 40,
|
||||||
|
minSize: 40,
|
||||||
|
maxSize: 40,
|
||||||
|
cell: props => <div className='w-full text-center'>{props.getValue()}</div>
|
||||||
|
}),
|
||||||
|
argumentsHelper.accessor(arg => arg.value || 'свободный аргумент', {
|
||||||
|
id: 'value',
|
||||||
|
header: 'Значение',
|
||||||
|
size: 200,
|
||||||
|
minSize: 200,
|
||||||
|
maxSize: 200,
|
||||||
|
}),
|
||||||
|
argumentsHelper.accessor(arg => arg.typification, {
|
||||||
|
id: 'type',
|
||||||
|
header: 'Типизация',
|
||||||
|
size: 150,
|
||||||
|
minSize: 150,
|
||||||
|
maxSize: 150,
|
||||||
|
enableHiding: true,
|
||||||
|
cell: props => <div className='text-sm min-w-[9.3rem] max-w-[9.3rem] break-words'>{props.getValue()}</div>
|
||||||
|
}),
|
||||||
|
argumentsHelper.display({
|
||||||
|
id: 'actions',
|
||||||
|
size: 50,
|
||||||
|
minSize: 50,
|
||||||
|
maxSize: 50,
|
||||||
|
cell: props =>
|
||||||
|
<div className='max-h-[1.2rem]'>
|
||||||
|
{props.row.original.value &&
|
||||||
|
<MiniButton
|
||||||
|
tooltip='Очистить значение'
|
||||||
|
icon={<CrossIcon size={3} color='text-warning'/>}
|
||||||
|
noHover
|
||||||
|
onClick={() => handleClearArgument(props.row.original)}
|
||||||
|
/>}
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
], [handleClearArgument]);
|
||||||
|
|
||||||
|
const conditionalRowStyles = useMemo(
|
||||||
|
(): IConditionalStyle<IArgumentValue>[] => [{
|
||||||
|
when: (arg: IArgumentValue) => arg.alias === selectedArgument?.alias,
|
||||||
|
style: { backgroundColor: colors.bgSelected },
|
||||||
|
}], [selectedArgument, colors]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col gap-3'>
|
<div className='flex flex-col gap-3'>
|
||||||
<ConceptSearch
|
|
||||||
value={state.filterText}
|
<div className='overflow-y-auto text-sm border select-none max-h-[7.5rem] min-h-[7.5rem]'>
|
||||||
onChange={newValue => partialUpdate({ filterText: newValue} )}
|
<DataTable dense
|
||||||
dense
|
data={state.arguments}
|
||||||
|
columns={columns}
|
||||||
|
conditionalRowStyles={conditionalRowStyles}
|
||||||
|
noDataComponent={
|
||||||
|
<span className='flex flex-col justify-center p-2 text-center min-h-[5rem]'>
|
||||||
|
<p>Аргументы отсутствуют</p>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
onRowClicked={handleSelectArgument}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
title='Выберите аргумент из списка сверху и значение из списка снизу'
|
||||||
|
className='flex items-center justify-center w-full gap-2 select-none'
|
||||||
|
>
|
||||||
|
<span className='font-semibold text-center'>{selectedArgument?.alias || 'ARG'}</span>
|
||||||
|
<span>=</span>
|
||||||
|
<RSInput
|
||||||
|
dimensions='max-w-[12rem] w-full'
|
||||||
|
value={argumentValue}
|
||||||
|
onChange={newValue => setArgumentValue(newValue)}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
tooltip='Подставить значение аргумента'
|
||||||
|
icon={<CheckIcon
|
||||||
|
size={6}
|
||||||
|
color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'}
|
||||||
|
/>}
|
||||||
|
disabled={!argumentValue || !selectedArgument}
|
||||||
|
onClick={() => handleAssignArgument(selectedArgument!, argumentValue)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ConstituentaPicker
|
||||||
|
value={selectedCst}
|
||||||
|
data={schema?.items}
|
||||||
|
onSelectValue={handleSelectConstituenta}
|
||||||
|
prefixID={prefixes.cst_modal_list}
|
||||||
|
rows={5}
|
||||||
|
/>
|
||||||
|
|
||||||
<RSInput id='result'
|
<RSInput id='result'
|
||||||
placeholder='Итоговое определение'
|
placeholder='Итоговое определение'
|
||||||
height='4.8rem'
|
height='4.8rem'
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
import { Dispatch, useEffect, useMemo, useState } from 'react';
|
import { Dispatch, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import ConceptSearch from '../../components/Common/ConceptSearch';
|
|
||||||
import SelectSingle from '../../components/Common/SelectSingle';
|
import SelectSingle from '../../components/Common/SelectSingle';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
import DataTable, { createColumnHelper,IConditionalStyle } from '../../components/DataTable';
|
|
||||||
import ConstituentaTooltip from '../../components/Help/ConstituentaTooltip';
|
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
|
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
|
||||||
import { useLibrary } from '../../context/LibraryContext';
|
import { useLibrary } from '../../context/LibraryContext';
|
||||||
import { useConceptTheme } from '../../context/ThemeContext';
|
import { applyFilterCategory, CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform';
|
||||||
import { CstMatchMode } from '../../models/miscelanious';
|
|
||||||
import { applyFilterCategory, CATEGORY_CST_TYPE, IConstituenta, IRSForm, matchConstituenta } from '../../models/rsform';
|
|
||||||
import { colorfgCstStatus } from '../../utils/color';
|
|
||||||
import { prefixes } from '../../utils/constants';
|
import { prefixes } from '../../utils/constants';
|
||||||
|
|
||||||
export interface ITemplateState {
|
export interface ITemplateState {
|
||||||
templateID?: number
|
templateID?: number
|
||||||
prototype?: IConstituenta
|
prototype?: IConstituenta
|
||||||
filterCategory?: IConstituenta
|
filterCategory?: IConstituenta
|
||||||
filterText: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TemplateTabProps {
|
interface TemplateTabProps {
|
||||||
|
@ -25,11 +18,7 @@ interface TemplateTabProps {
|
||||||
partialUpdate: Dispatch<Partial<ITemplateState>>
|
partialUpdate: Dispatch<Partial<ITemplateState>>
|
||||||
}
|
}
|
||||||
|
|
||||||
const constituentaHelper = createColumnHelper<IConstituenta>();
|
|
||||||
|
|
||||||
function TemplateTab({ state, partialUpdate }: TemplateTabProps) {
|
function TemplateTab({ state, partialUpdate }: TemplateTabProps) {
|
||||||
const { colors } = useConceptTheme();
|
|
||||||
|
|
||||||
const { templates, retrieveTemplate } = useLibrary();
|
const { templates, retrieveTemplate } = useLibrary();
|
||||||
const [ selectedSchema, setSelectedSchema ] = useState<IRSForm | undefined>(undefined);
|
const [ selectedSchema, setSelectedSchema ] = useState<IRSForm | undefined>(undefined);
|
||||||
|
|
||||||
|
@ -91,58 +80,8 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) {
|
||||||
if (state.filterCategory) {
|
if (state.filterCategory) {
|
||||||
data = applyFilterCategory(state.filterCategory, selectedSchema);
|
data = applyFilterCategory(state.filterCategory, selectedSchema);
|
||||||
}
|
}
|
||||||
if (state.filterText) {
|
|
||||||
data = data.filter(cst => matchConstituenta(state.filterText, cst, CstMatchMode.TERM));
|
|
||||||
}
|
|
||||||
setFilteredData(data);
|
setFilteredData(data);
|
||||||
}, [state.filterText, state.filterCategory, selectedSchema]);
|
}, [state.filterCategory, selectedSchema]);
|
||||||
|
|
||||||
function handleSelectTemplate(cst: IConstituenta) {
|
|
||||||
partialUpdate( { prototype: cst } );
|
|
||||||
}
|
|
||||||
|
|
||||||
const columns = useMemo(
|
|
||||||
() => [
|
|
||||||
constituentaHelper.accessor('alias', {
|
|
||||||
id: 'alias',
|
|
||||||
size: 65,
|
|
||||||
minSize: 65,
|
|
||||||
cell: props => {
|
|
||||||
const cst = props.row.original;
|
|
||||||
return (<>
|
|
||||||
<div
|
|
||||||
id={`${prefixes.cst_template_ist}${cst.alias}`}
|
|
||||||
className='min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
|
||||||
style={{
|
|
||||||
borderWidth: '1px',
|
|
||||||
borderColor: colorfgCstStatus(cst.status, colors),
|
|
||||||
color: colorfgCstStatus(cst.status, colors),
|
|
||||||
fontWeight: 600
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cst.alias}
|
|
||||||
</div>
|
|
||||||
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_template_ist}${cst.alias}`} />
|
|
||||||
</>);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
constituentaHelper.accessor('term_resolved', {
|
|
||||||
id: 'term',
|
|
||||||
size: 600,
|
|
||||||
minSize: 350,
|
|
||||||
maxSize: 600
|
|
||||||
})
|
|
||||||
], [colors]);
|
|
||||||
|
|
||||||
const conditionalRowStyles = useMemo(
|
|
||||||
(): IConditionalStyle<IConstituenta>[] => [
|
|
||||||
{
|
|
||||||
when: (cst: IConstituenta) => cst.id === state.prototype?.id,
|
|
||||||
style: {
|
|
||||||
backgroundColor: colors.bgSelected
|
|
||||||
},
|
|
||||||
}
|
|
||||||
], [state.prototype, colors]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col gap-3'>
|
<div className='flex flex-col gap-3'>
|
||||||
|
@ -166,32 +105,13 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) {
|
||||||
onChange={data => partialUpdate({templateID: (data ? data.value : undefined)})}
|
onChange={data => partialUpdate({templateID: (data ? data.value : undefined)})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<ConstituentaPicker
|
||||||
<ConceptSearch
|
value={state.prototype}
|
||||||
value={state.filterText}
|
|
||||||
onChange={newValue => partialUpdate({ filterText: newValue} )}
|
|
||||||
dense
|
|
||||||
/>
|
|
||||||
<div className='border min-h-[17.5rem] max-h-[17.5rem] text-sm overflow-y-auto select-none'>
|
|
||||||
<DataTable
|
|
||||||
data={filteredData}
|
data={filteredData}
|
||||||
columns={columns}
|
onSelectValue={cst => partialUpdate( { prototype: cst } )}
|
||||||
conditionalRowStyles={conditionalRowStyles}
|
prefixID={prefixes.cst_template_ist}
|
||||||
|
rows={9}
|
||||||
dense
|
|
||||||
noHeader
|
|
||||||
|
|
||||||
noDataComponent={
|
|
||||||
<span className='flex flex-col justify-center p-2 text-center min-h-[5rem]'>
|
|
||||||
<p>Список конституент пуст</p>
|
|
||||||
<p>Измените параметры фильтра</p>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowClicked={handleSelectTemplate}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<TextArea id='term'
|
<TextArea id='term'
|
||||||
rows={1}
|
rows={1}
|
||||||
disabled
|
disabled
|
||||||
|
|
|
@ -27,12 +27,10 @@ export enum TabID {
|
||||||
|
|
||||||
function DlgConstituentaTemplate({ hideWindow, schema, onCreate }: DlgConstituentaTemplateProps) {
|
function DlgConstituentaTemplate({ hideWindow, schema, onCreate }: DlgConstituentaTemplateProps) {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
const [ templateData, updateTemplateData ] = usePartialUpdate<ITemplateState>({
|
const [ templateData, updateTemplateData ] = usePartialUpdate<ITemplateState>({});
|
||||||
filterText: ''
|
|
||||||
});
|
|
||||||
const [ argumentsData, updateArgumentsData ] = usePartialUpdate<IArgumentsState>({
|
const [ argumentsData, updateArgumentsData ] = usePartialUpdate<IArgumentsState>({
|
||||||
filterText: '',
|
definition: '',
|
||||||
definition: ''
|
arguments: []
|
||||||
});
|
});
|
||||||
const [cstData, updateCstData] = usePartialUpdate<ICstCreateData>({
|
const [cstData, updateCstData] = usePartialUpdate<ICstCreateData>({
|
||||||
cst_type: CstType.TERM,
|
cst_type: CstType.TERM,
|
||||||
|
@ -80,7 +78,13 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate }: DlgConstituen
|
||||||
});
|
});
|
||||||
updateArgumentsData({
|
updateArgumentsData({
|
||||||
definition: templateData.prototype.definition_formal,
|
definition: templateData.prototype.definition_formal,
|
||||||
arguments: []
|
arguments: templateData.prototype.parse.args.map(
|
||||||
|
arg => ({
|
||||||
|
alias: arg.alias,
|
||||||
|
typification: arg.typification,
|
||||||
|
value: ''
|
||||||
|
})
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [templateData.prototype, updateCstData, updateArgumentsData]);
|
}, [templateData.prototype, updateCstData, updateArgumentsData]);
|
||||||
|
@ -136,6 +140,7 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate }: DlgConstituen
|
||||||
|
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<ArgumentsTab
|
<ArgumentsTab
|
||||||
|
schema={schema}
|
||||||
state={argumentsData}
|
state={argumentsData}
|
||||||
partialUpdate={updateArgumentsData}
|
partialUpdate={updateArgumentsData}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import { createColumnHelper } from '@tanstack/react-table';
|
|
||||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import ConceptSearch from '../../components/Common/ConceptSearch';
|
|
||||||
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||||
import Label from '../../components/Common/Label';
|
import Label from '../../components/Common/Label';
|
||||||
import Modal from '../../components/Common/Modal';
|
import Modal from '../../components/Common/Modal';
|
||||||
import SelectMulti from '../../components/Common/SelectMulti';
|
import SelectMulti from '../../components/Common/SelectMulti';
|
||||||
import TextInput from '../../components/Common/TextInput';
|
import TextInput from '../../components/Common/TextInput';
|
||||||
import DataTable, { IConditionalStyle } from '../../components/DataTable';
|
|
||||||
import ConstituentaTooltip from '../../components/Help/ConstituentaTooltip';
|
|
||||||
import HelpTerminologyControl from '../../components/Help/HelpTerminologyControl';
|
import HelpTerminologyControl from '../../components/Help/HelpTerminologyControl';
|
||||||
import { HelpIcon } from '../../components/Icons';
|
import { HelpIcon } from '../../components/Icons';
|
||||||
import { useConceptTheme } from '../../context/ThemeContext';
|
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
|
||||||
import {
|
import {
|
||||||
getCompatibleGrams, Grammeme,
|
getCompatibleGrams, Grammeme,
|
||||||
parseEntityReference, parseGrammemes,
|
parseEntityReference, parseGrammemes,
|
||||||
|
@ -19,7 +15,6 @@ import {
|
||||||
} from '../../models/language';
|
} from '../../models/language';
|
||||||
import { CstMatchMode } from '../../models/miscelanious';
|
import { CstMatchMode } from '../../models/miscelanious';
|
||||||
import { IConstituenta, matchConstituenta } from '../../models/rsform';
|
import { IConstituenta, matchConstituenta } from '../../models/rsform';
|
||||||
import { colorfgCstStatus } from '../../utils/color';
|
|
||||||
import { prefixes } from '../../utils/constants';
|
import { prefixes } from '../../utils/constants';
|
||||||
import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors';
|
import { compareGrammemeOptions, IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors';
|
||||||
import ReferenceTypeButton from './ReferenceTypeButton';
|
import ReferenceTypeButton from './ReferenceTypeButton';
|
||||||
|
@ -40,20 +35,16 @@ interface DlgEditReferenceProps {
|
||||||
onSave: (newRef: string) => void
|
onSave: (newRef: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const constituentaHelper = createColumnHelper<IConstituenta>();
|
|
||||||
|
|
||||||
function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferenceProps) {
|
function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferenceProps) {
|
||||||
const { colors } = useConceptTheme();
|
|
||||||
|
|
||||||
const [type, setType] = useState<ReferenceType>(ReferenceType.ENTITY);
|
const [type, setType] = useState<ReferenceType>(ReferenceType.ENTITY);
|
||||||
|
|
||||||
const [nominal, setNominal] = useState('');
|
const [nominal, setNominal] = useState('');
|
||||||
const [offset, setOffset] = useState(1);
|
const [offset, setOffset] = useState(1);
|
||||||
|
|
||||||
|
const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined);
|
||||||
const [alias, setAlias] = useState('');
|
const [alias, setAlias] = useState('');
|
||||||
const [term, setTerm] = useState('');
|
const [term, setTerm] = useState('');
|
||||||
const [filter, setFilter] = useState('');
|
|
||||||
const [filteredData, setFilteredData] = useState<IConstituenta[]>([]);
|
|
||||||
const [selectedGrams, setSelectedGrams] = useState<IGrammemeOption[]>([]);
|
const [selectedGrams, setSelectedGrams] = useState<IGrammemeOption[]>([]);
|
||||||
const [gramOptions, setGramOptions] = useState<IGrammemeOption[]>([]);
|
const [gramOptions, setGramOptions] = useState<IGrammemeOption[]>([]);
|
||||||
|
|
||||||
|
@ -105,24 +96,9 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
}
|
}
|
||||||
} else if (initial.text) {
|
} else if (initial.text) {
|
||||||
setNominal(initial.text ?? '');
|
setNominal(initial.text ?? '');
|
||||||
setFilter(initial.text);
|
|
||||||
}
|
}
|
||||||
}, [initial, items]);
|
}, [initial, items]);
|
||||||
|
|
||||||
// Filter constituents
|
|
||||||
useEffect(
|
|
||||||
() => {
|
|
||||||
if (filter === '') {
|
|
||||||
setFilteredData(items.filter(
|
|
||||||
(cst) => cst.term_resolved !== '')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setFilteredData(items.filter(
|
|
||||||
(cst) => matchConstituenta(filter, cst, CstMatchMode.TERM))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [filter, items]);
|
|
||||||
|
|
||||||
// Filter grammemes when input changes
|
// Filter grammemes when input changes
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
|
@ -145,6 +121,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
|
|
||||||
function handleSelectConstituenta(cst: IConstituenta) {
|
function handleSelectConstituenta(cst: IConstituenta) {
|
||||||
setAlias(cst.alias);
|
setAlias(cst.alias);
|
||||||
|
setSelectedCst(cst);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSelectGrams = useCallback(
|
const handleSelectGrams = useCallback(
|
||||||
|
@ -180,49 +157,6 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
</div>);
|
</div>);
|
||||||
}, [handleSelectGrams, selectedGrams]);
|
}, [handleSelectGrams, selectedGrams]);
|
||||||
|
|
||||||
const columnsConstituenta = useMemo(
|
|
||||||
() => [
|
|
||||||
constituentaHelper.accessor('alias', {
|
|
||||||
id: 'alias',
|
|
||||||
size: 65,
|
|
||||||
minSize: 65,
|
|
||||||
cell: props => {
|
|
||||||
const cst = props.row.original;
|
|
||||||
return (<>
|
|
||||||
<div
|
|
||||||
id={`${prefixes.cst_wordform_list}${cst.alias}`}
|
|
||||||
className='min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
|
||||||
style={{
|
|
||||||
borderWidth: '1px',
|
|
||||||
borderColor: colorfgCstStatus(cst.status, colors),
|
|
||||||
color: colorfgCstStatus(cst.status, colors),
|
|
||||||
fontWeight: 600
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cst.alias}
|
|
||||||
</div>
|
|
||||||
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_wordform_list}${cst.alias}`} />
|
|
||||||
</>);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
constituentaHelper.accessor('term_resolved', {
|
|
||||||
id: 'term',
|
|
||||||
size: 600,
|
|
||||||
minSize: 350,
|
|
||||||
maxSize: 600
|
|
||||||
})
|
|
||||||
], [colors]);
|
|
||||||
|
|
||||||
const conditionalRowStyles = useMemo(
|
|
||||||
(): IConditionalStyle<IConstituenta>[] => [
|
|
||||||
{
|
|
||||||
when: (cst: IConstituenta) => cst.alias === alias,
|
|
||||||
style: {
|
|
||||||
backgroundColor: colors.bgSelected
|
|
||||||
},
|
|
||||||
}
|
|
||||||
], [alias, colors]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title='Редактирование ссылки'
|
title='Редактирование ссылки'
|
||||||
|
@ -286,32 +220,17 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
</div>}
|
</div>}
|
||||||
{type === ReferenceType.ENTITY &&
|
{type === ReferenceType.ENTITY &&
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<div>
|
<ConstituentaPicker
|
||||||
<ConceptSearch
|
value={selectedCst}
|
||||||
value={filter}
|
data={items}
|
||||||
onChange={newValue => setFilter(newValue)}
|
onSelectValue={handleSelectConstituenta}
|
||||||
dense
|
prefixID={prefixes.cst_modal_list}
|
||||||
|
describeFunc={cst => cst.term_resolved}
|
||||||
|
matchFunc={(cst, filter) => matchConstituenta(cst, filter, CstMatchMode.TERM)}
|
||||||
|
prefilterFunc={cst => cst.term_resolved !== ''}
|
||||||
|
rows={8}
|
||||||
/>
|
/>
|
||||||
<div className='border min-h-[15.5rem] max-h-[15.5rem] text-sm overflow-y-auto'>
|
|
||||||
<DataTable
|
|
||||||
data={filteredData}
|
|
||||||
columns={columnsConstituenta}
|
|
||||||
conditionalRowStyles={conditionalRowStyles}
|
|
||||||
|
|
||||||
noHeader
|
|
||||||
dense
|
|
||||||
|
|
||||||
noDataComponent={
|
|
||||||
<span className='flex flex-col justify-center p-2 text-center min-h-[5rem]'>
|
|
||||||
<p>Список конституент пуст</p>
|
|
||||||
<p>Измените параметры фильтра</p>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
onRowClicked={handleSelectConstituenta}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex gap-4 flex-start'>
|
<div className='flex gap-4 flex-start'>
|
||||||
<TextInput
|
<TextInput
|
||||||
label='Отсылаемая конституента'
|
label='Отсылаемая конституента'
|
||||||
|
|
|
@ -223,7 +223,7 @@ export function loadRSFormData(schema: IRSFormData): IRSForm {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function matchConstituenta(query: string, target: IConstituenta, mode: CstMatchMode): boolean {
|
export function matchConstituenta(target: IConstituenta, query: string, mode: CstMatchMode): boolean {
|
||||||
const matcher = new TextMatcher(query);
|
const matcher = new TextMatcher(query);
|
||||||
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
|
if ((mode === CstMatchMode.ALL || mode === CstMatchMode.NAME) &&
|
||||||
matcher.test(target.alias)) {
|
matcher.test(target.alias)) {
|
||||||
|
@ -283,6 +283,10 @@ export function inferClass(type: CstType, isTemplate: boolean): CstClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isMockCst(cst: IConstituenta) {
|
||||||
|
return cst.id <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
export function createMockConstituenta(schema: number, id: number, alias: string, type: CstType, comment: string): IConstituenta {
|
export function createMockConstituenta(schema: number, id: number, alias: string, type: CstType, comment: string): IConstituenta {
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
|
|
|
@ -48,8 +48,7 @@ export interface IArgumentInfo {
|
||||||
typification: string
|
typification: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IArgumentValue {
|
export interface IArgumentValue extends IArgumentInfo {
|
||||||
alias: string
|
|
||||||
value?: string
|
value?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
|
||||||
import DataTable, { createColumnHelper, type RowSelectionState,VisibilityState } from '../../components/DataTable';
|
import DataTable, { createColumnHelper, type RowSelectionState,VisibilityState } from '../../components/DataTable';
|
||||||
|
import ConstituentaBadge from '../../components/Shared/ConstituentaBadge';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import { useConceptTheme } from '../../context/ThemeContext';
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
import useWindowSize from '../../hooks/useWindowSize';
|
import useWindowSize from '../../hooks/useWindowSize';
|
||||||
import { CstType, IConstituenta, ICstCreateData, ICstMovetoData } from '../../models/rsform'
|
import { CstType, IConstituenta, ICstCreateData, ICstMovetoData } from '../../models/rsform'
|
||||||
import { colorfgCstStatus } from '../../utils/color';
|
|
||||||
import { prefixes } from '../../utils/constants';
|
import { prefixes } from '../../utils/constants';
|
||||||
import { describeExpressionStatus, labelCstTypification } from '../../utils/labels';
|
import { labelCstTypification } from '../../utils/labels';
|
||||||
import RSItemsMenu from './elements/RSItemsMenu';
|
import RSItemsMenu from './elements/RSItemsMenu';
|
||||||
|
|
||||||
// Window width cutoff for columns
|
// Window width cutoff for columns
|
||||||
|
@ -239,30 +238,13 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst, onTemplates }: Edit
|
||||||
size: 65,
|
size: 65,
|
||||||
minSize: 65,
|
minSize: 65,
|
||||||
maxSize: 65,
|
maxSize: 65,
|
||||||
cell: props => {
|
cell: props =>
|
||||||
const cst = props.row.original;
|
<ConstituentaBadge
|
||||||
return (<>
|
theme={colors}
|
||||||
<div
|
value={props.row.original}
|
||||||
id={`${prefixes.cst_list}${cst.alias}`}
|
prefixID={prefixes.cst_list}
|
||||||
className='w-full min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
shortTooltip
|
||||||
style={{
|
/>
|
||||||
borderWidth: "1px",
|
|
||||||
borderColor: colorfgCstStatus(cst.status, colors),
|
|
||||||
color: colorfgCstStatus(cst.status, colors),
|
|
||||||
fontWeight: 600,
|
|
||||||
backgroundColor: colors.bgInput
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cst.alias}
|
|
||||||
</div>
|
|
||||||
<ConceptTooltip
|
|
||||||
anchorSelect={`#${prefixes.cst_list}${cst.alias}`}
|
|
||||||
place='right'
|
|
||||||
>
|
|
||||||
<p><span className='font-semibold'>Статус</span>: {describeExpressionStatus(cst.status)}</p>
|
|
||||||
</ConceptTooltip>
|
|
||||||
</>);
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(cst => labelCstTypification(cst), {
|
columnHelper.accessor(cst => labelCstTypification(cst), {
|
||||||
id: 'type',
|
id: 'type',
|
||||||
|
|
|
@ -5,6 +5,7 @@ import DropdownButton from '../../../components/Common/DropdownButton';
|
||||||
import SelectorButton from '../../../components/Common/SelectorButton';
|
import SelectorButton from '../../../components/Common/SelectorButton';
|
||||||
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '../../../components/DataTable';
|
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '../../../components/DataTable';
|
||||||
import { CogIcon, FilterIcon, MagnifyingGlassIcon } from '../../../components/Icons';
|
import { CogIcon, FilterIcon, MagnifyingGlassIcon } from '../../../components/Icons';
|
||||||
|
import ConstituentaBadge from '../../../components/Shared/ConstituentaBadge';
|
||||||
import { useRSForm } from '../../../context/RSFormContext';
|
import { useRSForm } from '../../../context/RSFormContext';
|
||||||
import { useConceptTheme } from '../../../context/ThemeContext';
|
import { useConceptTheme } from '../../../context/ThemeContext';
|
||||||
import useDropdown from '../../../hooks/useDropdown';
|
import useDropdown from '../../../hooks/useDropdown';
|
||||||
|
@ -13,16 +14,14 @@ import useWindowSize from '../../../hooks/useWindowSize';
|
||||||
import { DependencyMode as CstSource } from '../../../models/miscelanious';
|
import { DependencyMode as CstSource } from '../../../models/miscelanious';
|
||||||
import { CstMatchMode } from '../../../models/miscelanious';
|
import { CstMatchMode } from '../../../models/miscelanious';
|
||||||
import { applyGraphFilter } from '../../../models/miscelanious';
|
import { applyGraphFilter } from '../../../models/miscelanious';
|
||||||
import { CstType, extractGlobals, IConstituenta, matchConstituenta } from '../../../models/rsform';
|
import { CstType, extractGlobals, IConstituenta, isMockCst, matchConstituenta } from '../../../models/rsform';
|
||||||
import { createMockConstituenta } from '../../../models/rsform';
|
import { createMockConstituenta } from '../../../models/rsform';
|
||||||
import { colorfgCstStatus } from '../../../utils/color';
|
|
||||||
import { prefixes } from '../../../utils/constants';
|
import { prefixes } from '../../../utils/constants';
|
||||||
import {
|
import {
|
||||||
describeConstituenta, describeCstMathchMode,
|
describeConstituenta, describeCstMathchMode,
|
||||||
describeCstSource, labelCstMathchMode,
|
describeCstSource, labelCstMathchMode,
|
||||||
labelCstSource
|
labelCstSource
|
||||||
} from '../../../utils/labels';
|
} from '../../../utils/labels';
|
||||||
import ConstituentaTooltip from '../../../components/Help/ConstituentaTooltip';
|
|
||||||
|
|
||||||
// Height that should be left to accomodate navigation panel + bottom margin
|
// Height that should be left to accomodate navigation panel + bottom margin
|
||||||
const LOCAL_NAVIGATION_H = '2.1rem';
|
const LOCAL_NAVIGATION_H = '2.1rem';
|
||||||
|
@ -37,10 +36,6 @@ interface ViewSideConstituentsProps {
|
||||||
onOpenEdit: (cstID: number) => void
|
onOpenEdit: (cstID: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMockCst(cst: IConstituenta) {
|
|
||||||
return cst.id <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<IConstituenta>();
|
const columnHelper = createColumnHelper<IConstituenta>();
|
||||||
|
|
||||||
function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: ViewSideConstituentsProps) {
|
function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }: ViewSideConstituentsProps) {
|
||||||
|
@ -102,7 +97,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
||||||
filtered = applyGraphFilter(schema, activeID, filterSource);
|
filtered = applyGraphFilter(schema, activeID, filterSource);
|
||||||
}
|
}
|
||||||
if (filterText) {
|
if (filterText) {
|
||||||
filtered = filtered.filter((cst) => matchConstituenta(filterText, cst, filterMatch));
|
filtered = filtered.filter(cst => matchConstituenta(cst, filterText, filterMatch));
|
||||||
}
|
}
|
||||||
setFilteredData(filtered);
|
setFilteredData(filtered);
|
||||||
}, [filterText, setFilteredData, filterSource, expression, schema, filterMatch, activeID]);
|
}, [filterText, setFilteredData, filterSource, expression, schema, filterMatch, activeID]);
|
||||||
|
@ -141,25 +136,12 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
||||||
size: 65,
|
size: 65,
|
||||||
minSize: 65,
|
minSize: 65,
|
||||||
footer: undefined,
|
footer: undefined,
|
||||||
cell: props => {
|
cell: props =>
|
||||||
const cst = props.row.original;
|
<ConstituentaBadge
|
||||||
return (<>
|
theme={colors}
|
||||||
<div
|
value={props.row.original}
|
||||||
id={`${prefixes.cst_list}${cst.alias}`}
|
prefixID={prefixes.cst_list}
|
||||||
className='min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
/>
|
||||||
style={{
|
|
||||||
borderWidth: '1px',
|
|
||||||
borderColor: colorfgCstStatus(cst.status, colors),
|
|
||||||
color: colorfgCstStatus(cst.status, colors),
|
|
||||||
fontWeight: 600,
|
|
||||||
backgroundColor: isMockCst(cst) ? colors.bgWarning : colors.bgInput
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{cst.alias}
|
|
||||||
</div>
|
|
||||||
<ConstituentaTooltip data={cst} anchor={`#${prefixes.cst_list}${cst.alias}`} />
|
|
||||||
</>);
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(cst => describeConstituenta(cst), {
|
columnHelper.accessor(cst => describeConstituenta(cst), {
|
||||||
id: 'description',
|
id: 'description',
|
||||||
|
|
|
@ -34,6 +34,7 @@ export const globalIDs = {
|
||||||
|
|
||||||
export const prefixes = {
|
export const prefixes = {
|
||||||
cst_list: 'cst-list-',
|
cst_list: 'cst-list-',
|
||||||
|
cst_modal_list: 'cst-modal-list-',
|
||||||
cst_template_ist: 'cst-template-list-',
|
cst_template_ist: 'cst-template-list-',
|
||||||
cst_wordform_list: 'cst-wordform-list-',
|
cst_wordform_list: 'cst-wordform-list-',
|
||||||
cst_status_list: 'cst-status-list-',
|
cst_status_list: 'cst-status-list-',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user