mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor UI elements
This commit is contained in:
parent
cf57f975f0
commit
fbf2d0ba4d
|
@ -42,7 +42,7 @@ function Modal({
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className='fixed bottom-1/2 left-1/2 translate-y-1/2 -translate-x-1/2 px-6 py-4 flex flex-col justify-start w-fit max-w-[calc(100vw-2rem)] h-fit z-modal clr-app border shadow-md'
|
className='fixed bottom-1/2 left-1/2 translate-y-1/2 -translate-x-1/2 px-6 py-4 flex flex-col justify-start w-fit max-w-[calc(100vw-2rem)] h-fit z-modal clr-app border shadow-md'
|
||||||
>
|
>
|
||||||
{ title && <h1 className='mb-2 text-xl'>{title}</h1> }
|
{ title && <h1 className='mb-2 text-xl select-none'>{title}</h1> }
|
||||||
<div className='max-h-[calc(100vh-8rem)]'>
|
<div className='max-h-[calc(100vh-8rem)]'>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
66
rsconcept/frontend/src/components/Common/SelectMulti.tsx
Normal file
66
rsconcept/frontend/src/components/Common/SelectMulti.tsx
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import Select, { GroupBase, Props, StylesConfig } from 'react-select';
|
||||||
|
|
||||||
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
|
import { selectDarkT, selectLightT } from '../../utils/color';
|
||||||
|
|
||||||
|
interface SelectMultiProps<
|
||||||
|
Option,
|
||||||
|
Group extends GroupBase<Option> = GroupBase<Option>
|
||||||
|
>
|
||||||
|
extends Omit<Props<Option, true, Group>, 'theme'> {
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectMulti<
|
||||||
|
Option,
|
||||||
|
Group extends GroupBase<Option> = GroupBase<Option>
|
||||||
|
> ({ ...props }: SelectMultiProps<Option, Group>) {
|
||||||
|
const { darkMode, colors } = useConceptTheme();
|
||||||
|
const themeColors = useMemo(
|
||||||
|
() => !darkMode ? selectLightT : selectDarkT
|
||||||
|
, [darkMode]);
|
||||||
|
|
||||||
|
const adjustedStyles: StylesConfig<Option, true, Group> = useMemo(
|
||||||
|
() => ({
|
||||||
|
control: (styles, { isDisabled }) => ({
|
||||||
|
...styles,
|
||||||
|
borderRadius: '0.25rem',
|
||||||
|
cursor: isDisabled ? 'not-allowed' : 'pointer'
|
||||||
|
}),
|
||||||
|
|
||||||
|
option: (styles, { isSelected }) => ({
|
||||||
|
...styles,
|
||||||
|
backgroundColor: isSelected ? colors.bgSelected : styles.backgroundColor,
|
||||||
|
color: isSelected ? colors.fgSelected : styles.color,
|
||||||
|
borderWidth: '1px',
|
||||||
|
borderColor: colors.border
|
||||||
|
}),
|
||||||
|
input: (styles) => ({...styles}),
|
||||||
|
placeholder: (styles) => ({...styles}),
|
||||||
|
multiValue: styles => ({
|
||||||
|
...styles,
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
backgroundColor: colors.bgSelected,
|
||||||
|
}),
|
||||||
|
|
||||||
|
}), [colors]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
noOptionsMessage={() => 'Список пуст'}
|
||||||
|
theme={theme => ({
|
||||||
|
...theme,
|
||||||
|
borderRadius: 0,
|
||||||
|
colors: {
|
||||||
|
...theme.colors,
|
||||||
|
...themeColors
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
isMulti
|
||||||
|
styles={adjustedStyles}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectMulti;
|
|
@ -4,17 +4,17 @@ import Select, { GroupBase, Props, StylesConfig } from 'react-select';
|
||||||
import { useConceptTheme } from '../../context/ThemeContext';
|
import { useConceptTheme } from '../../context/ThemeContext';
|
||||||
import { selectDarkT, selectLightT } from '../../utils/color';
|
import { selectDarkT, selectLightT } from '../../utils/color';
|
||||||
|
|
||||||
interface ConceptSelectSingleProps<
|
interface SelectSingleProps<
|
||||||
Option,
|
Option,
|
||||||
Group extends GroupBase<Option> = GroupBase<Option>
|
Group extends GroupBase<Option> = GroupBase<Option>
|
||||||
>
|
>
|
||||||
extends Omit<Props<Option, false, Group>, 'theme'> {
|
extends Omit<Props<Option, false, Group>, 'theme'> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConceptSelectSingle<
|
function SelectSingle<
|
||||||
Option,
|
Option,
|
||||||
Group extends GroupBase<Option> = GroupBase<Option>
|
Group extends GroupBase<Option> = GroupBase<Option>
|
||||||
> ({ ...props }: ConceptSelectSingleProps<Option, Group>) {
|
> ({ ...props }: SelectSingleProps<Option, Group>) {
|
||||||
const { darkMode, colors } = useConceptTheme();
|
const { darkMode, colors } = useConceptTheme();
|
||||||
const themeColors = useMemo(
|
const themeColors = useMemo(
|
||||||
() => !darkMode ? selectLightT : selectDarkT
|
() => !darkMode ? selectLightT : selectDarkT
|
||||||
|
@ -56,4 +56,4 @@ function ConceptSelectSingle<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ConceptSelectSingle;
|
export default SelectSingle;
|
|
@ -2,8 +2,8 @@ import Label from './Label';
|
||||||
|
|
||||||
interface TextInputProps
|
interface TextInputProps
|
||||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className' | 'title'> {
|
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className' | 'title'> {
|
||||||
id: string
|
id?: string
|
||||||
label: string
|
label?: string
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
widthClass?: string
|
widthClass?: string
|
||||||
colorClass?: string
|
colorClass?: string
|
||||||
|
@ -18,11 +18,11 @@ function TextInput({
|
||||||
}: TextInputProps) {
|
}: TextInputProps) {
|
||||||
return (
|
return (
|
||||||
<div className={`flex [&:not(:first-child)]:mt-3 ${singleRow ? 'items-center gap-4 ' + widthClass : 'flex-col items-start'}`}>
|
<div className={`flex [&:not(:first-child)]:mt-3 ${singleRow ? 'items-center gap-4 ' + widthClass : 'flex-col items-start'}`}>
|
||||||
<Label
|
{label && <Label
|
||||||
text={label}
|
text={label}
|
||||||
required={!props.disabled && required}
|
required={!props.disabled && required}
|
||||||
htmlFor={id}
|
htmlFor={id}
|
||||||
/>
|
/>}
|
||||||
<input id={id}
|
<input id={id}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`px-3 py-2 leading-tight border shadow truncate hover:text-clip clr-outline ${colorClass} ${singleRow ? '' : 'mt-2 ' + widthClass}`}
|
className={`px-3 py-2 leading-tight border shadow truncate hover:text-clip clr-outline ${colorClass} ${singleRow ? '' : 'mt-2 ' + widthClass}`}
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
// Module: Natural language model declarations.
|
// Module: Natural language model declarations.
|
||||||
|
|
||||||
|
|
||||||
// ====== Text morphology ========
|
|
||||||
|
|
||||||
|
|
||||||
// ====== Reference resolution =====
|
// ====== Reference resolution =====
|
||||||
export interface IRefsText {
|
export interface IRefsText {
|
||||||
text: string
|
text: string
|
||||||
|
@ -40,3 +36,103 @@ export interface IReferenceData {
|
||||||
output: string
|
output: string
|
||||||
refs: IResolvedReference[]
|
refs: IResolvedReference[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====== Morphology ========
|
||||||
|
export enum Morpheme {
|
||||||
|
// Части речи
|
||||||
|
NOUN = 'NOUN',
|
||||||
|
ADJF = 'ADJF',
|
||||||
|
ADJS = 'ADJS',
|
||||||
|
COMP = 'COMP',
|
||||||
|
VERB = 'VERB',
|
||||||
|
INFN = 'INFN',
|
||||||
|
PRTF = 'PRTF',
|
||||||
|
PRTS = 'PRTS',
|
||||||
|
GRND = 'GRND',
|
||||||
|
NUMR = 'NUMR',
|
||||||
|
ADVB = 'ADVB',
|
||||||
|
NPRO = 'NPRO',
|
||||||
|
PRED = 'PRED',
|
||||||
|
PREP = 'PREP',
|
||||||
|
CONJ = 'CONJ',
|
||||||
|
PRCL = 'PRCL',
|
||||||
|
INTJ = 'INTJ',
|
||||||
|
PNCT = 'PNCT',
|
||||||
|
|
||||||
|
// Одушевленность
|
||||||
|
anim = 'anim',
|
||||||
|
inan = 'inan',
|
||||||
|
|
||||||
|
// Род
|
||||||
|
masc = 'masc',
|
||||||
|
femn = 'femn',
|
||||||
|
neut = 'neut',
|
||||||
|
|
||||||
|
// Число
|
||||||
|
sing = 'sing',
|
||||||
|
plur = 'plur',
|
||||||
|
|
||||||
|
// Падеж (основные)
|
||||||
|
nomn = 'nomn',
|
||||||
|
gent = 'gent',
|
||||||
|
datv = 'datv',
|
||||||
|
accs = 'accs',
|
||||||
|
ablt = 'ablt',
|
||||||
|
loct = 'loct',
|
||||||
|
|
||||||
|
// Совершенный / несовершенный вид
|
||||||
|
perf = 'perf',
|
||||||
|
impf = 'impf',
|
||||||
|
|
||||||
|
// Переходность
|
||||||
|
tran = 'tran',
|
||||||
|
intr = 'intr',
|
||||||
|
|
||||||
|
// Время
|
||||||
|
pres = 'pres',
|
||||||
|
past = 'past',
|
||||||
|
futr = 'futr',
|
||||||
|
|
||||||
|
// Лицо
|
||||||
|
per1 = '1per',
|
||||||
|
per2 = '2per',
|
||||||
|
per3 = '3per',
|
||||||
|
|
||||||
|
// Наклонение
|
||||||
|
indc = 'indc',
|
||||||
|
impr = 'impr',
|
||||||
|
|
||||||
|
// Включение говорящего в действие
|
||||||
|
incl = 'incl',
|
||||||
|
excl = 'excl',
|
||||||
|
|
||||||
|
// Залог
|
||||||
|
actv = 'actv',
|
||||||
|
pssv = 'pssv',
|
||||||
|
|
||||||
|
// Стиль речи
|
||||||
|
Infr = 'Infr', // Неформальный
|
||||||
|
Slng = 'Slng', // Жаргон
|
||||||
|
Arch = 'Arch', // Устаревший
|
||||||
|
Litr = 'Litr', // Литературный
|
||||||
|
|
||||||
|
// Аббревиатура
|
||||||
|
Abbr = 'Abbr'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PartOfSpeech = [
|
||||||
|
Morpheme.NOUN, Morpheme.ADJF, Morpheme.ADJS, Morpheme.COMP,
|
||||||
|
Morpheme.VERB, Morpheme.INFN, Morpheme.PRTF, Morpheme.PRTS,
|
||||||
|
Morpheme.GRND, Morpheme.ADVB, Morpheme.NPRO, Morpheme.PRED,
|
||||||
|
Morpheme.PREP, Morpheme.CONJ, Morpheme.PRCL, Morpheme.INTJ,
|
||||||
|
Morpheme.PNCT
|
||||||
|
]
|
||||||
|
|
||||||
|
export const Gender = [
|
||||||
|
Morpheme.masc, Morpheme.femn, Morpheme.neut
|
||||||
|
]
|
||||||
|
|
||||||
|
export const Case = [
|
||||||
|
Morpheme.nomn, Morpheme.gent, Morpheme.datv,
|
||||||
|
Morpheme.accs, Morpheme.ablt, Morpheme.loct
|
||||||
|
]
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import ConceptSelectSingle from '../../components/Common/ConceptSelectSingle';
|
|
||||||
import Modal, { ModalProps } from '../../components/Common/Modal';
|
import Modal, { ModalProps } from '../../components/Common/Modal';
|
||||||
|
import SelectSingle from '../../components/Common/SelectSingle';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
import RSInput from '../../components/RSInput';
|
import RSInput from '../../components/RSInput';
|
||||||
import { CstType,ICstCreateData } from '../../models/rsform';
|
import { CstType,ICstCreateData } from '../../models/rsform';
|
||||||
import { CstTypeSelector, getCstTypeLabel } from '../../utils/staticUI';
|
import { SelectorCstType } from '../../utils/selectors';
|
||||||
|
import { getCstTypeLabel } from '../../utils/staticUI';
|
||||||
|
|
||||||
interface DlgCreateCstProps
|
interface DlgCreateCstProps
|
||||||
extends Pick<ModalProps, 'hideWindow'> {
|
extends Pick<ModalProps, 'hideWindow'> {
|
||||||
|
@ -57,9 +58,9 @@ function DlgCreateCst({ hideWindow, initial, onCreate }: DlgCreateCstProps) {
|
||||||
>
|
>
|
||||||
<div className='h-fit w-[35rem] px-2 mb-2 flex flex-col justify-stretch'>
|
<div className='h-fit w-[35rem] px-2 mb-2 flex flex-col justify-stretch'>
|
||||||
<div className='flex justify-center w-full'>
|
<div className='flex justify-center w-full'>
|
||||||
<ConceptSelectSingle
|
<SelectSingle
|
||||||
className='my-2 min-w-[15rem] self-center'
|
className='my-2 min-w-[15rem] self-center'
|
||||||
options={CstTypeSelector}
|
options={SelectorCstType}
|
||||||
placeholder='Выберите тип'
|
placeholder='Выберите тип'
|
||||||
value={selectedType ? { value: selectedType, label: getCstTypeLabel(selectedType) } : null}
|
value={selectedType ? { value: selectedType, label: getCstTypeLabel(selectedType) } : null}
|
||||||
onChange={data => setSelectedType(data?.value ?? CstType.BASE)}
|
onChange={data => setSelectedType(data?.value ?? CstType.BASE)}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import { useLayoutEffect, useState } from 'react';
|
import { useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import Divider from '../../components/Common/Divider';
|
||||||
import Modal from '../../components/Common/Modal';
|
import Modal from '../../components/Common/Modal';
|
||||||
|
import SelectMulti from '../../components/Common/SelectMulti';
|
||||||
import TextArea from '../../components/Common/TextArea';
|
import TextArea from '../../components/Common/TextArea';
|
||||||
|
import TextInput from '../../components/Common/TextInput';
|
||||||
import { IConstituenta } from '../../models/rsform';
|
import { IConstituenta } from '../../models/rsform';
|
||||||
|
import { SelectorGraphLayout } from '../../utils/selectors';
|
||||||
|
|
||||||
interface DlgEditTermProps {
|
interface DlgEditTermProps {
|
||||||
hideWindow: () => void
|
hideWindow: () => void
|
||||||
|
@ -28,19 +32,36 @@ function DlgEditTerm({ hideWindow, target, onSave }: DlgEditTermProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title='Редактирование термина'
|
title='Редактирование словоформ'
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
submitText='Сохранить данные'
|
submitText='Сохранить данные'
|
||||||
canSubmit
|
canSubmit
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
|
<div className='min-w-[40rem]'>
|
||||||
<TextArea id='nominal' label='Начальная форма'
|
<TextArea id='nominal' label='Начальная форма'
|
||||||
placeholder='Начальная форма'
|
placeholder='Начальная форма'
|
||||||
rows={2}
|
rows={2}
|
||||||
|
|
||||||
value={term}
|
value={term}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
spellCheck
|
spellCheck
|
||||||
/>
|
/>
|
||||||
|
<Divider margins='my-4' />
|
||||||
|
<div className='flex items-center justify-start gap-2 w-full'>
|
||||||
|
<SelectMulti
|
||||||
|
className='z-modal-top min-w-[10rem]'
|
||||||
|
options={SelectorGraphLayout}
|
||||||
|
placeholder='Способ расположения'
|
||||||
|
|
||||||
|
// value={null}
|
||||||
|
// onChange={data => handleChangeLayout(data?.value ?? SelectorGraphLayout[0].value)}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { useLayoutEffect, useState } from 'react';
|
import { useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
import ConceptSelectSingle from '../../components/Common/ConceptSelectSingle';
|
|
||||||
import Modal, { ModalProps } from '../../components/Common/Modal';
|
import Modal, { ModalProps } from '../../components/Common/Modal';
|
||||||
|
import SelectSingle from '../../components/Common/SelectSingle';
|
||||||
import TextInput from '../../components/Common/TextInput';
|
import TextInput from '../../components/Common/TextInput';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import { CstType, ICstRenameData } from '../../models/rsform';
|
import { CstType, ICstRenameData } from '../../models/rsform';
|
||||||
import { createAliasFor, CstTypeSelector, getCstTypeLabel, getCstTypePrefix } from '../../utils/staticUI';
|
import { createAliasFor, getCstTypeLabel, getCstTypePrefix } from '../../utils/staticUI';
|
||||||
|
import { SelectorCstType } from '../../utils/selectors';
|
||||||
|
|
||||||
interface DlgRenameCstProps
|
interface DlgRenameCstProps
|
||||||
extends Pick<ModalProps, 'hideWindow'> {
|
extends Pick<ModalProps, 'hideWindow'> {
|
||||||
|
@ -67,9 +68,9 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||||
submitText='Переименовать'
|
submitText='Переименовать'
|
||||||
>
|
>
|
||||||
<div className='flex items-center gap-4 px-2 my-2 h-fit min-w-[25rem]'>
|
<div className='flex items-center gap-4 px-2 my-2 h-fit min-w-[25rem]'>
|
||||||
<ConceptSelectSingle
|
<SelectSingle
|
||||||
className='min-w-[14rem] self-center z-modal-top'
|
className='min-w-[14rem] self-center z-modal-top'
|
||||||
options={CstTypeSelector}
|
options={SelectorCstType}
|
||||||
placeholder='Выберите тип'
|
placeholder='Выберите тип'
|
||||||
value={cstType ? { value: cstType, label: getCstTypeLabel(cstType) } : null}
|
value={cstType ? { value: cstType, label: getCstTypeLabel(cstType) } : null}
|
||||||
onChange={data => setCstType(data?.value ?? CstType.BASE)}
|
onChange={data => setCstType(data?.value ?? CstType.BASE)}
|
||||||
|
|
|
@ -40,7 +40,7 @@ function EditorConstituenta({
|
||||||
onShowAST, onCreateCst, onRenameCst, onOpenEdit, onDeleteCst
|
onShowAST, onCreateCst, onRenameCst, onOpenEdit, onDeleteCst
|
||||||
}: EditorConstituentaProps) {
|
}: EditorConstituentaProps) {
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
const { schema, processing, isEditable, cstUpdate, isForceAdmin } = useRSForm();
|
const { schema, processing, isEditable, cstUpdate } = useRSForm();
|
||||||
|
|
||||||
const [editMode, setEditMode] = useState(EditMode.TEXT);
|
const [editMode, setEditMode] = useState(EditMode.TEXT);
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ function EditorConstituenta({
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{isForceAdmin && <div className='relative'>
|
<div className='relative'>
|
||||||
<div className='absolute left-[3.2rem] top-[0.5rem]'>
|
<div className='absolute left-[3.2rem] top-[0.5rem]'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Редактировать словоформы термина'
|
tooltip='Редактировать словоформы термина'
|
||||||
|
@ -193,7 +193,7 @@ function EditorConstituenta({
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>
|
||||||
<ReferenceInput id='term' label='Термин'
|
<ReferenceInput id='term' label='Термин'
|
||||||
placeholder='Обозначение, используемое в текстовых определениях данной схемы'
|
placeholder='Обозначение, используемое в текстовых определениях данной схемы'
|
||||||
rows={2}
|
rows={2}
|
||||||
|
|
|
@ -5,10 +5,10 @@ import { GraphCanvas, GraphCanvasRef, GraphEdge,
|
||||||
|
|
||||||
import Button from '../../components/Common/Button';
|
import Button from '../../components/Common/Button';
|
||||||
import Checkbox from '../../components/Common/Checkbox';
|
import Checkbox from '../../components/Common/Checkbox';
|
||||||
import ConceptSelectSingle from '../../components/Common/ConceptSelectSingle';
|
|
||||||
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
import ConceptTooltip from '../../components/Common/ConceptTooltip';
|
||||||
import Divider from '../../components/Common/Divider';
|
import Divider from '../../components/Common/Divider';
|
||||||
import MiniButton from '../../components/Common/MiniButton';
|
import MiniButton from '../../components/Common/MiniButton';
|
||||||
|
import SelectSingle from '../../components/Common/SelectSingle';
|
||||||
import HelpTermGraph from '../../components/Help/HelpTermGraph';
|
import HelpTermGraph from '../../components/Help/HelpTermGraph';
|
||||||
import InfoConstituenta from '../../components/Help/InfoConstituenta';
|
import InfoConstituenta from '../../components/Help/InfoConstituenta';
|
||||||
import { ArrowsRotateIcon, DumpBinIcon, FilterCogIcon, HelpIcon, SmallPlusIcon } from '../../components/Icons';
|
import { ArrowsRotateIcon, DumpBinIcon, FilterCogIcon, HelpIcon, SmallPlusIcon } from '../../components/Icons';
|
||||||
|
@ -19,8 +19,9 @@ import { CstType, IConstituenta, ICstCreateData } from '../../models/rsform';
|
||||||
import { graphDarkT, graphLightT, IColorTheme } from '../../utils/color';
|
import { graphDarkT, graphLightT, IColorTheme } from '../../utils/color';
|
||||||
import { prefixes, resources, TIMEOUT_GRAPH_REFRESH } from '../../utils/constants';
|
import { prefixes, resources, TIMEOUT_GRAPH_REFRESH } from '../../utils/constants';
|
||||||
import { Graph } from '../../utils/Graph';
|
import { Graph } from '../../utils/Graph';
|
||||||
|
import { SelectorGraphLayout } from '../../utils/selectors';
|
||||||
|
import { SelectorGraphColoring } from '../../utils/selectors';
|
||||||
import { getCstClassColor, getCstStatusBgColor,
|
import { getCstClassColor, getCstStatusBgColor,
|
||||||
GraphColoringSelector, GraphLayoutSelector,
|
|
||||||
mapColoringLabels, mapLayoutLabels
|
mapColoringLabels, mapLayoutLabels
|
||||||
} from '../../utils/staticUI';
|
} from '../../utils/staticUI';
|
||||||
import DlgGraphOptions from './DlgGraphOptions';
|
import DlgGraphOptions from './DlgGraphOptions';
|
||||||
|
@ -404,23 +405,23 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
|
||||||
widthClass='h-full'
|
widthClass='h-full'
|
||||||
onClick={() => setShowOptions(true)}
|
onClick={() => setShowOptions(true)}
|
||||||
/>
|
/>
|
||||||
<ConceptSelectSingle
|
<SelectSingle
|
||||||
className='min-w-[9.8rem]'
|
className='min-w-[9.8rem]'
|
||||||
options={GraphColoringSelector}
|
options={SelectorGraphColoring}
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
placeholder='Выберите цвет'
|
placeholder='Выберите цвет'
|
||||||
value={coloringScheme ? { value: coloringScheme, label: mapColoringLabels.get(coloringScheme) } : null}
|
value={coloringScheme ? { value: coloringScheme, label: mapColoringLabels.get(coloringScheme) } : null}
|
||||||
onChange={data => setColoringScheme(data?.value ?? GraphColoringSelector[0].value)}
|
onChange={data => setColoringScheme(data?.value ?? SelectorGraphColoring[0].value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<ConceptSelectSingle
|
<SelectSingle
|
||||||
className='w-full mt-1'
|
className='w-full mt-1'
|
||||||
options={GraphLayoutSelector}
|
options={SelectorGraphLayout}
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
placeholder='Способ расположения'
|
placeholder='Способ расположения'
|
||||||
value={layout ? { value: layout, label: mapLayoutLabels.get(layout) } : null}
|
value={layout ? { value: layout, label: mapLayoutLabels.get(layout) } : null}
|
||||||
onChange={data => handleChangeLayout(data?.value ?? GraphLayoutSelector[0].value)}
|
onChange={data => handleChangeLayout(data?.value ?? SelectorGraphLayout[0].value)}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label='Скрыть текст'
|
label='Скрыть текст'
|
||||||
|
|
|
@ -119,7 +119,7 @@ export const selectLightT = {
|
||||||
neutral20: lightT.border,
|
neutral20: lightT.border,
|
||||||
neutral30: lightT.border,
|
neutral30: lightT.border,
|
||||||
neutral40: lightT.fgDisabled,
|
neutral40: lightT.fgDisabled,
|
||||||
neutral50: lightT.fgWarning,
|
neutral50: lightT.fgDisabled, // placeholder
|
||||||
neutral60: lightT.fgDefault,
|
neutral60: lightT.fgDefault,
|
||||||
neutral70: lightT.fgWarning,
|
neutral70: lightT.fgWarning,
|
||||||
neutral80: lightT.fgDefault,
|
neutral80: lightT.fgDefault,
|
||||||
|
@ -141,7 +141,7 @@ export const selectDarkT = {
|
||||||
neutral20: darkT.border,
|
neutral20: darkT.border,
|
||||||
neutral30: darkT.border,
|
neutral30: darkT.border,
|
||||||
neutral40: darkT.fgDisabled,
|
neutral40: darkT.fgDisabled,
|
||||||
neutral50: darkT.fgWarning,
|
neutral50: darkT.fgDisabled, // placeholder
|
||||||
neutral60: darkT.fgDefault,
|
neutral60: darkT.fgDefault,
|
||||||
neutral70: darkT.fgWarning,
|
neutral70: darkT.fgWarning,
|
||||||
neutral80: darkT.fgDefault,
|
neutral80: darkT.fgDefault,
|
||||||
|
|
38
rsconcept/frontend/src/utils/selectors.ts
Normal file
38
rsconcept/frontend/src/utils/selectors.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Module: Selector maps
|
||||||
|
import { LayoutTypes } from 'reagraph';
|
||||||
|
|
||||||
|
import { CstType } from '../models/rsform';
|
||||||
|
import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph';
|
||||||
|
import { getCstTypeLabel } from './staticUI';
|
||||||
|
|
||||||
|
|
||||||
|
export const SelectorGraphLayout: { value: LayoutTypes; label: string; }[] = [
|
||||||
|
{ value: 'treeTd2d', label: 'Граф: ДеревоВ 2D' },
|
||||||
|
{ value: 'treeTd3d', label: 'Граф: ДеревоВ 3D' },
|
||||||
|
{ value: 'forceatlas2', label: 'Граф: Атлас 2D' },
|
||||||
|
{ value: 'forceDirected2d', label: 'Граф: Силы 2D' },
|
||||||
|
{ value: 'forceDirected3d', label: 'Граф: Силы 3D' },
|
||||||
|
{ value: 'treeLr2d', label: 'Граф: ДеревоГ 2D' },
|
||||||
|
{ value: 'treeLr3d', label: 'Граф: ДеревоГ 3D' },
|
||||||
|
{ value: 'radialOut2d', label: 'Граф: Радиальная 2D' },
|
||||||
|
{ value: 'radialOut3d', label: 'Граф: Радиальная 3D' },
|
||||||
|
// { value: 'circular2d', label: 'circular2d'},
|
||||||
|
// { value: 'nooverlap', label: 'nooverlap'},
|
||||||
|
// { value: 'hierarchicalTd', label: 'hierarchicalTd'},
|
||||||
|
// { value: 'hierarchicalLr', label: 'hierarchicalLr'}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const SelectorGraphColoring: { value: ColoringScheme; label: string; }[] = [
|
||||||
|
{ value: 'none', label: 'Цвет: моно' },
|
||||||
|
{ value: 'status', label: 'Цвет: статус' },
|
||||||
|
{ value: 'type', label: 'Цвет: класс' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const SelectorCstType = (
|
||||||
|
Object.values(CstType)).map(
|
||||||
|
typeStr => ({
|
||||||
|
value: typeStr as CstType,
|
||||||
|
label: getCstTypeLabel(typeStr as CstType)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { LayoutTypes } from 'reagraph';
|
|
||||||
|
|
||||||
import { DependencyMode } from '../models/miscelanious';
|
import { DependencyMode } from '../models/miscelanious';
|
||||||
import { HelpTopic } from '../models/miscelanious';
|
import { HelpTopic } from '../models/miscelanious';
|
||||||
|
@ -7,7 +6,6 @@ import { ExpressionStatus } from '../models/rsform';
|
||||||
import { CstClass, CstType, IConstituenta, IRSForm } from '../models/rsform';
|
import { CstClass, CstType, IConstituenta, IRSForm } from '../models/rsform';
|
||||||
import { IFunctionArg, IRSErrorDescription, ISyntaxTreeNode, ParsingStatus, ValueClass } from '../models/rslang';
|
import { IFunctionArg, IRSErrorDescription, ISyntaxTreeNode, ParsingStatus, ValueClass } from '../models/rslang';
|
||||||
import { resolveErrorClass, RSErrorClass, RSErrorType, TokenID } from '../models/rslang';
|
import { resolveErrorClass, RSErrorClass, RSErrorType, TokenID } from '../models/rslang';
|
||||||
import { ColoringScheme } from '../pages/RSFormPage/EditorTermGraph';
|
|
||||||
import { IColorTheme } from './color';
|
import { IColorTheme } from './color';
|
||||||
|
|
||||||
export interface IDescriptor {
|
export interface IDescriptor {
|
||||||
|
@ -242,14 +240,6 @@ export function getCstTypeShortcut(type: CstType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CstTypeSelector = (
|
|
||||||
Object.values(CstType)).map(
|
|
||||||
typeStr => ({
|
|
||||||
value: typeStr as CstType,
|
|
||||||
label: getCstTypeLabel(typeStr as CstType)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
export function getCstCompareLabel(mode: CstMatchMode): string {
|
export function getCstCompareLabel(mode: CstMatchMode): string {
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case CstMatchMode.ALL: return 'везде';
|
case CstMatchMode.ALL: return 'везде';
|
||||||
|
@ -271,22 +261,6 @@ export function getDependencyLabel(mode: DependencyMode): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GraphLayoutSelector: {value: LayoutTypes, label: string}[] = [
|
|
||||||
{ value: 'treeTd2d', label: 'Граф: ДеревоВ 2D'},
|
|
||||||
{ value: 'treeTd3d', label: 'Граф: ДеревоВ 3D'},
|
|
||||||
{ value: 'forceatlas2', label: 'Граф: Атлас 2D'},
|
|
||||||
{ value: 'forceDirected2d', label: 'Граф: Силы 2D'},
|
|
||||||
{ value: 'forceDirected3d', label: 'Граф: Силы 3D'},
|
|
||||||
{ value: 'treeLr2d', label: 'Граф: ДеревоГ 2D'},
|
|
||||||
{ value: 'treeLr3d', label: 'Граф: ДеревоГ 3D'},
|
|
||||||
{ value: 'radialOut2d', label: 'Граф: Радиальная 2D'},
|
|
||||||
{ value: 'radialOut3d', label: 'Граф: Радиальная 3D'},
|
|
||||||
// { value: 'circular2d', label: 'circular2d'},
|
|
||||||
// { value: 'nooverlap', label: 'nooverlap'},
|
|
||||||
// { value: 'hierarchicalTd', label: 'hierarchicalTd'},
|
|
||||||
// { value: 'hierarchicalLr', label: 'hierarchicalLr'}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const mapLayoutLabels: Map<string, string> = new Map([
|
export const mapLayoutLabels: Map<string, string> = new Map([
|
||||||
['forceatlas2', 'Граф: Атлас 2D'],
|
['forceatlas2', 'Граф: Атлас 2D'],
|
||||||
['forceDirected2d', 'Граф: Силы 2D'],
|
['forceDirected2d', 'Граф: Силы 2D'],
|
||||||
|
@ -309,12 +283,6 @@ export const mapColoringLabels: Map<string, string> = new Map([
|
||||||
['type', 'Цвет: класс'],
|
['type', 'Цвет: класс'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const GraphColoringSelector: {value: ColoringScheme, label: string}[] = [
|
|
||||||
{ value: 'none', label: 'Цвет: моно'},
|
|
||||||
{ value: 'status', label: 'Цвет: статус'},
|
|
||||||
{ value: 'type', label: 'Цвет: класс'},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function getCstStatusBgColor(status: ExpressionStatus, colors: IColorTheme): string {
|
export function getCstStatusBgColor(status: ExpressionStatus, colors: IColorTheme): string {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ExpressionStatus.VERIFIED: return colors.bgGreen;
|
case ExpressionStatus.VERIFIED: return colors.bgGreen;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user