mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor and optimize dialogs
This commit is contained in:
parent
38b661f290
commit
eab63814d5
|
@ -9,7 +9,7 @@ extends Omit<React.DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTML
|
||||||
function Label({ text, tooltip, className, ...restProps }: LabelProps) {
|
function Label({ text, tooltip, className, ...restProps }: LabelProps) {
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
className={`text-sm font-semibold ${className} whitespace-nowrap`}
|
className={`text-sm font-semibold whitespace-nowrap ${className}`}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
|
|
|
@ -16,12 +16,13 @@ export interface ModalProps {
|
||||||
onSubmit?: () => void
|
onSubmit?: () => void
|
||||||
onCancel?: () => void
|
onCancel?: () => void
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function Modal({
|
function Modal({
|
||||||
title, hideWindow, onSubmit,
|
title, hideWindow, onSubmit,
|
||||||
readonly, onCancel, canSubmit,
|
readonly, onCancel, canSubmit,
|
||||||
submitInvalidTooltip,
|
submitInvalidTooltip, className,
|
||||||
children,
|
children,
|
||||||
submitText = 'Продолжить'
|
submitText = 'Продолжить'
|
||||||
}: ModalProps) {
|
}: ModalProps) {
|
||||||
|
@ -42,9 +43,9 @@ function Modal({
|
||||||
<>
|
<>
|
||||||
<div className='fixed top-0 left-0 w-full h-full z-navigation clr-modal-backdrop' />
|
<div className='fixed top-0 left-0 w-full h-full z-navigation clr-modal-backdrop' />
|
||||||
<div ref={ref}
|
<div ref={ref}
|
||||||
className='fixed bottom-1/2 left-1/2 translate-y-1/2 -translate-x-1/2 px-6 w-fit max-w-[calc(100vw-2rem)] h-fit z-modal clr-app border shadow-md'
|
className='fixed -translate-x-1/2 translate-y-1/2 border shadow-md bottom-1/2 left-1/2 z-modal clr-app'
|
||||||
>
|
>
|
||||||
<Overlay position='right-[-1rem] top-2' className='text-disabled'>
|
<Overlay position='right-[0.3rem] top-2' className='text-disabled'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Закрыть диалоговое окно [ESC]'
|
tooltip='Закрыть диалоговое окно [ESC]'
|
||||||
icon={<CrossIcon size={5}/>}
|
icon={<CrossIcon size={5}/>}
|
||||||
|
@ -52,25 +53,32 @@ function Modal({
|
||||||
/>
|
/>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
{title ? <h1 className='my-2 text-lg select-none'>{title}</h1> : null}
|
{title ? <h1 className='px-12 py-2 text-lg select-none'>{title}</h1> : null}
|
||||||
|
|
||||||
<div className='max-h-[calc(100vh-8rem)] overflow-auto flex flex-col justify-start '>
|
<div
|
||||||
|
className={`w-full h-fit ${className}`}
|
||||||
|
style={{
|
||||||
|
maxHeight: 'calc(100vh - 8rem)',
|
||||||
|
maxWidth: 'calc(100vw - 2rem)',
|
||||||
|
overflow: 'auto'
|
||||||
|
}}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex justify-center w-full gap-6 my-3 z-modal-controls'>
|
<div className='flex justify-center w-full gap-12 px-6 py-3 z-modal-controls min-w-fit'>
|
||||||
{!readonly ?
|
{!readonly ?
|
||||||
<Button autoFocus
|
<Button autoFocus
|
||||||
text={submitText}
|
text={submitText}
|
||||||
tooltip={!canSubmit ? submitInvalidTooltip: ''}
|
tooltip={!canSubmit ? submitInvalidTooltip: ''}
|
||||||
dimensions='min-w-[8rem] min-h-[2.6rem] w-fit h-fit'
|
dimensions='min-w-[8rem] min-h-[2.6rem]'
|
||||||
colors='clr-btn-primary'
|
colors='clr-btn-primary'
|
||||||
disabled={!canSubmit}
|
disabled={!canSubmit}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
/> : null}
|
/> : null}
|
||||||
<Button
|
<Button
|
||||||
text={readonly ? 'Закрыть' : 'Отмена'}
|
text={readonly ? 'Закрыть' : 'Отмена'}
|
||||||
dimensions='min-w-[8rem] min-h-[2.6rem] w-fit h-fit'
|
dimensions='min-w-[8rem] min-h-[2.6rem]'
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -25,7 +25,8 @@ function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<Option>
|
||||||
control: (styles, { isDisabled }) => ({
|
control: (styles, { isDisabled }) => ({
|
||||||
...styles,
|
...styles,
|
||||||
borderRadius: '0.25rem',
|
borderRadius: '0.25rem',
|
||||||
cursor: isDisabled ? 'not-allowed' : 'pointer'
|
cursor: isDisabled ? 'not-allowed' : 'pointer',
|
||||||
|
boxShadow: 'none'
|
||||||
}),
|
}),
|
||||||
option: (styles, { isSelected }) => ({
|
option: (styles, { isSelected }) => ({
|
||||||
...styles,
|
...styles,
|
||||||
|
|
|
@ -25,7 +25,8 @@ function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase<Option
|
||||||
control: (styles, { isDisabled }) => ({
|
control: (styles, { isDisabled }) => ({
|
||||||
...styles,
|
...styles,
|
||||||
borderRadius: '0.25rem',
|
borderRadius: '0.25rem',
|
||||||
cursor: isDisabled ? 'not-allowed' : 'pointer'
|
cursor: isDisabled ? 'not-allowed' : 'pointer',
|
||||||
|
boxShadow: 'none'
|
||||||
}),
|
}),
|
||||||
menuPortal: (styles) => ({
|
menuPortal: (styles) => ({
|
||||||
...styles,
|
...styles,
|
||||||
|
|
|
@ -87,7 +87,7 @@ function RSInput({
|
||||||
{ tag: tags.literal, color: colors.fgBlue }, // literals
|
{ tag: tags.literal, color: colors.fgBlue }, // literals
|
||||||
{ tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D
|
{ tag: tags.controlKeyword, fontWeight: '500'}, // R | I | D
|
||||||
{ tag: tags.unit, fontSize: '0.75rem' }, // indicies
|
{ tag: tags.unit, fontSize: '0.75rem' }, // indicies
|
||||||
{ tag: tags.brace, color:colors.fgPurple, fontWeight: '500' }, // braces (curly brackets)
|
{ tag: tags.brace, color:colors.fgPurple, fontWeight: '700' }, // braces (curly brackets)
|
||||||
]
|
]
|
||||||
}), [disabled, colors, darkMode]);
|
}), [disabled, colors, darkMode]);
|
||||||
|
|
||||||
|
@ -108,12 +108,14 @@ function RSInput({
|
||||||
if (event.altKey) {
|
if (event.altKey) {
|
||||||
if (text.processAltKey(event.code, event.shiftKey)) {
|
if (text.processAltKey(event.code, event.shiftKey)) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
} else if (!event.ctrlKey) {
|
} else if (!event.ctrlKey) {
|
||||||
const newSymbol = getSymbolSubstitute(event.code, event.shiftKey);
|
const newSymbol = getSymbolSubstitute(event.code, event.shiftKey);
|
||||||
if (newSymbol) {
|
if (newSymbol) {
|
||||||
text.replaceWith(newSymbol);
|
text.replaceWith(newSymbol);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [thisRef]);
|
}, [thisRef]);
|
||||||
|
|
|
@ -60,8 +60,8 @@ function DlgCloneLibraryItem({ hideWindow, base }: DlgCloneLibraryItemProps) {
|
||||||
canSubmit={canSubmit}
|
canSubmit={canSubmit}
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
className='flex flex-col gap-3 px-6 py-2'
|
||||||
>
|
>
|
||||||
<div className='flex flex-col gap-3'>
|
|
||||||
<TextInput
|
<TextInput
|
||||||
label='Полное название'
|
label='Полное название'
|
||||||
value={title}
|
value={title}
|
||||||
|
@ -83,7 +83,6 @@ function DlgCloneLibraryItem({ hideWindow, base }: DlgCloneLibraryItemProps) {
|
||||||
value={common}
|
value={common}
|
||||||
setValue={value => setCommon(value)}
|
setValue={value => setCommon(value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</Modal>);
|
</Modal>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,33 +114,35 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
|
||||||
canSubmit={validated}
|
canSubmit={validated}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
|
className='max-w-[43rem] min-w-[43rem] min-h-[35rem] px-6'
|
||||||
>
|
>
|
||||||
<Tabs defaultFocus forceRenderTabPanel
|
<Tabs defaultFocus forceRenderTabPanel
|
||||||
className='flex flex-col items-center max-w-[40rem] min-w-[40rem] min-h-[35rem] mb-1'
|
|
||||||
selectedTabClassName='clr-selected'
|
selectedTabClassName='clr-selected'
|
||||||
selectedIndex={activeTab}
|
selectedIndex={activeTab}
|
||||||
onSelect={setActiveTab}
|
onSelect={setActiveTab}
|
||||||
>
|
>
|
||||||
<Overlay position='top-0 left-[12.3rem]'>
|
<Overlay position='top-0 right-[6rem]'>
|
||||||
<HelpButton topic={HelpTopic.RSTEMPLATES} dimensions='max-w-[35rem]' />
|
<HelpButton topic={HelpTopic.RSTEMPLATES} dimensions='max-w-[35rem]' />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
<TabList className='flex mb-3 border'>
|
<TabList className='flex justify-center mb-3'>
|
||||||
<ConceptTab
|
<div className='flex border w-fit'>
|
||||||
label='Шаблон'
|
<ConceptTab
|
||||||
tooltip='Выбор шаблона выражения'
|
label='Шаблон'
|
||||||
className='border-r w-[8rem]'
|
tooltip='Выбор шаблона выражения'
|
||||||
/>
|
className='border-r w-[8rem]'
|
||||||
<ConceptTab
|
/>
|
||||||
label='Аргументы'
|
<ConceptTab
|
||||||
tooltip='Подстановка аргументов шаблона'
|
label='Аргументы'
|
||||||
className='border-r w-[8rem]'
|
tooltip='Подстановка аргументов шаблона'
|
||||||
/>
|
className='border-r w-[8rem]'
|
||||||
<ConceptTab
|
/>
|
||||||
label='Конституента'
|
<ConceptTab
|
||||||
tooltip='Редактирование атрибутов конституенты'
|
label='Конституента'
|
||||||
className='w-[8rem]'
|
tooltip='Редактирование атрибутов конституенты'
|
||||||
/>
|
className='w-[8rem]'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</TabList>
|
</TabList>
|
||||||
|
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
|
|
|
@ -20,7 +20,6 @@ extends Pick<ModalProps, 'hideWindow'> {
|
||||||
|
|
||||||
function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstProps) {
|
function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstProps) {
|
||||||
const [validated, setValidated] = useState(false);
|
const [validated, setValidated] = useState(false);
|
||||||
|
|
||||||
const [cstData, updateCstData] = usePartialUpdate(
|
const [cstData, updateCstData] = usePartialUpdate(
|
||||||
initial || {
|
initial || {
|
||||||
cst_type: CstType.BASE,
|
cst_type: CstType.BASE,
|
||||||
|
@ -53,51 +52,51 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
|
||||||
canSubmit={validated}
|
canSubmit={validated}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
|
className='h-fit min-w-[35rem] py-2 flex flex-col justify-stretch gap-3 px-6'
|
||||||
>
|
>
|
||||||
<div className='h-fit w-[35rem] px-2 my-2 flex flex-col justify-stretch gap-3'>
|
|
||||||
<div className='flex justify-center w-full gap-6'>
|
<div className='flex justify-center w-full gap-6'>
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
className='min-w-[15rem] self-center'
|
|
||||||
placeholder='Выберите тип'
|
placeholder='Выберите тип'
|
||||||
|
className='min-w-[15rem] self-center'
|
||||||
options={SelectorCstType}
|
options={SelectorCstType}
|
||||||
value={{ value: cstData.cst_type, label: labelCstType(cstData.cst_type) }}
|
value={{ value: cstData.cst_type, label: labelCstType(cstData.cst_type) }}
|
||||||
onChange={data => updateCstData({ cst_type: data?.value ?? CstType.BASE})}
|
onChange={data => updateCstData({ cst_type: data?.value ?? CstType.BASE})}
|
||||||
/>
|
/>
|
||||||
<TextInput id='alias' label='Имя'
|
<TextInput dense
|
||||||
dense
|
label='Имя'
|
||||||
dimensions='w-[7rem]'
|
dimensions='w-[7rem]'
|
||||||
value={cstData.alias}
|
value={cstData.alias}
|
||||||
onChange={event => updateCstData({ alias: event.target.value})}
|
onChange={event => updateCstData({ alias: event.target.value})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<TextArea id='term' label='Термин'
|
<TextArea spellCheck
|
||||||
|
label='Термин'
|
||||||
placeholder='Схемный или предметный термин, обозначающий данное понятие или утверждение'
|
placeholder='Схемный или предметный термин, обозначающий данное понятие или утверждение'
|
||||||
rows={2}
|
rows={2}
|
||||||
value={cstData.term_raw}
|
value={cstData.term_raw}
|
||||||
spellCheck
|
|
||||||
onChange={event => updateCstData({ term_raw: event.target.value })}
|
onChange={event => updateCstData({ term_raw: event.target.value })}
|
||||||
/>
|
/>
|
||||||
<RSInput id='expression' label='Формальное определение'
|
<RSInput
|
||||||
|
label='Формальное определение'
|
||||||
placeholder='Родоструктурное выражение, задающее формальное определение'
|
placeholder='Родоструктурное выражение, задающее формальное определение'
|
||||||
height='5.1rem'
|
height='5.1rem'
|
||||||
value={cstData.definition_formal}
|
value={cstData.definition_formal}
|
||||||
onChange={value => updateCstData({definition_formal: value})}
|
onChange={value => updateCstData({definition_formal: value})}
|
||||||
/>
|
/>
|
||||||
<TextArea id='definition' label='Текстовое определение'
|
<TextArea spellCheck
|
||||||
|
label='Текстовое определение'
|
||||||
placeholder='Лингвистическая интерпретация формального выражения'
|
placeholder='Лингвистическая интерпретация формального выражения'
|
||||||
rows={2}
|
rows={2}
|
||||||
value={cstData.definition_raw}
|
value={cstData.definition_raw}
|
||||||
spellCheck
|
|
||||||
onChange={event => updateCstData({ definition_raw: event.target.value })}
|
onChange={event => updateCstData({ definition_raw: event.target.value })}
|
||||||
/>
|
/>
|
||||||
<TextArea id='convention' label='Конвенция / Комментарий'
|
<TextArea spellCheck
|
||||||
|
label='Конвенция / Комментарий'
|
||||||
placeholder='Договоренность об интерпретации или пояснение'
|
placeholder='Договоренность об интерпретации или пояснение'
|
||||||
rows={2}
|
rows={2}
|
||||||
value={cstData.convention}
|
value={cstData.convention}
|
||||||
spellCheck
|
|
||||||
onChange={event => updateCstData({ convention: event.target.value })}
|
onChange={event => updateCstData({ convention: event.target.value })}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</Modal>);
|
</Modal>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
import { useMemo, useState } from 'react';
|
|
||||||
|
|
||||||
import Checkbox from '../components/Common/Checkbox';
|
|
||||||
import Modal, { ModalProps } from '../components/Common/Modal';
|
|
||||||
import { useRSForm } from '../context/RSFormContext';
|
|
||||||
import { prefixes } from '../utils/constants';
|
|
||||||
import { labelConstituenta } from '../utils/labels';
|
|
||||||
|
|
||||||
interface DlgDeleteCstProps
|
|
||||||
extends Pick<ModalProps, 'hideWindow'> {
|
|
||||||
selected: number[]
|
|
||||||
onDelete: (items: number[]) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
function DlgDeleteCst({ hideWindow, selected, onDelete }: DlgDeleteCstProps) {
|
|
||||||
const { schema } = useRSForm();
|
|
||||||
|
|
||||||
const [expandOut, setExpandOut] = useState(false);
|
|
||||||
const expansion: number[] = useMemo(() => schema?.graph.expandOutputs(selected) ?? [], [selected, schema?.graph]);
|
|
||||||
|
|
||||||
function handleSubmit() {
|
|
||||||
hideWindow();
|
|
||||||
if (expandOut) {
|
|
||||||
onDelete(selected.concat(expansion));
|
|
||||||
} else {
|
|
||||||
onDelete(selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal canSubmit
|
|
||||||
title='Удаление конституент'
|
|
||||||
submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'}
|
|
||||||
hideWindow={hideWindow}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
>
|
|
||||||
<div className='max-w-[60vw] min-w-[30rem]'>
|
|
||||||
<p>Выбраны к удалению: <b>{selected.length}</b></p>
|
|
||||||
<div className='px-3 border h-[9rem] mt-1 overflow-y-auto whitespace-nowrap'>
|
|
||||||
{selected.map(
|
|
||||||
(id) => {
|
|
||||||
const cst = schema!.items.find(cst => cst.id === id);
|
|
||||||
return (cst ?
|
|
||||||
<p key={`${prefixes.cst_delete_list}${cst.id}`}>
|
|
||||||
{labelConstituenta(cst)}
|
|
||||||
</p> : null);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<p className='mt-4'>Зависимые конституенты: <b>{expansion.length}</b></p>
|
|
||||||
<div className='mt-1 mb-3 px-3 border h-[9rem] overflow-y-auto whitespace-nowrap'>
|
|
||||||
{expansion.map(
|
|
||||||
(id) => {
|
|
||||||
const cst = schema!.items.find(cst => cst.id === id);
|
|
||||||
return (cst ?
|
|
||||||
<p key={`${prefixes.cst_dependant_list}${cst.id}`}>
|
|
||||||
{labelConstituenta(cst)}
|
|
||||||
</p> : null);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<Checkbox
|
|
||||||
label='Удалить зависимые конституенты'
|
|
||||||
value={expandOut}
|
|
||||||
setValue={value => setExpandOut(value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Modal>);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DlgDeleteCst;
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { IConstituenta } from '../../models/rsform';
|
||||||
|
import { labelConstituenta } from '../../utils/labels';
|
||||||
|
|
||||||
|
interface ConstituentsListProps {
|
||||||
|
list: number[]
|
||||||
|
items: IConstituenta[]
|
||||||
|
prefix: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConstituentsList({ list, items, title, prefix }: ConstituentsListProps) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{title ?
|
||||||
|
<p className='pb-1'>
|
||||||
|
{title}: <b>{list.length}</b>
|
||||||
|
</p> : null}
|
||||||
|
<div className='px-3 border h-[9rem] overflow-y-auto whitespace-nowrap'>
|
||||||
|
{list.map(
|
||||||
|
(id) => {
|
||||||
|
const cst = items.find(cst => cst.id === id);
|
||||||
|
return (cst ?
|
||||||
|
<p key={`${prefix}${cst.id}`}>
|
||||||
|
{labelConstituenta(cst)}
|
||||||
|
</p> : null);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConstituentsList;
|
57
rsconcept/frontend/src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx
Normal file
57
rsconcept/frontend/src/dialogs/DlgDeleteCst/DlgDeleteCst.tsx
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import Checkbox from '../../components/Common/Checkbox';
|
||||||
|
import Modal, { ModalProps } from '../../components/Common/Modal';
|
||||||
|
import { IRSForm } from '../../models/rsform';
|
||||||
|
import { prefixes } from '../../utils/constants';
|
||||||
|
import ConstituentsList from './ConstituentsList';
|
||||||
|
|
||||||
|
interface DlgDeleteCstProps
|
||||||
|
extends Pick<ModalProps, 'hideWindow'> {
|
||||||
|
selected: number[]
|
||||||
|
onDelete: (items: number[]) => void
|
||||||
|
schema: IRSForm
|
||||||
|
}
|
||||||
|
|
||||||
|
function DlgDeleteCst({ hideWindow, selected, schema, onDelete }: DlgDeleteCstProps) {
|
||||||
|
const [expandOut, setExpandOut] = useState(false);
|
||||||
|
const expansion: number[] = useMemo(() => schema.graph.expandOutputs(selected), [selected, schema.graph]);
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
hideWindow();
|
||||||
|
if (expandOut) {
|
||||||
|
onDelete(selected.concat(expansion));
|
||||||
|
} else {
|
||||||
|
onDelete(selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal canSubmit
|
||||||
|
title='Удаление конституент'
|
||||||
|
submitText={expandOut ? 'Удалить с зависимыми' : 'Удалить'}
|
||||||
|
hideWindow={hideWindow}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
className='max-w-[60vw] min-w-[30rem] px-6 flex flex-col gap-3'
|
||||||
|
>
|
||||||
|
<ConstituentsList
|
||||||
|
title='Выбраны к удалению'
|
||||||
|
list={selected}
|
||||||
|
items={schema.items}
|
||||||
|
prefix={prefixes.cst_delete_list}
|
||||||
|
/>
|
||||||
|
<ConstituentsList
|
||||||
|
title='Зависимые конституенты'
|
||||||
|
list={expansion}
|
||||||
|
items={schema.items}
|
||||||
|
prefix={prefixes.cst_dependant_list}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
label='Удалить зависимые конституенты'
|
||||||
|
value={expandOut}
|
||||||
|
setValue={value => setExpandOut(value)}
|
||||||
|
/>
|
||||||
|
</Modal>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DlgDeleteCst;
|
1
rsconcept/frontend/src/dialogs/DlgDeleteCst/index.tsx
Normal file
1
rsconcept/frontend/src/dialogs/DlgDeleteCst/index.tsx
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './DlgDeleteCst';
|
|
@ -47,28 +47,30 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
canSubmit={isValid}
|
canSubmit={isValid}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
className='items-center min-w-[40rem] max-w-[40rem] px-6 min-h-[34rem]'
|
||||||
>
|
>
|
||||||
<Tabs defaultFocus
|
<Tabs defaultFocus
|
||||||
className='flex flex-col items-center min-w-[40rem] max-w-[40rem] mb-2 min-h-[34rem]'
|
|
||||||
selectedTabClassName='clr-selected'
|
selectedTabClassName='clr-selected'
|
||||||
selectedIndex={activeTab}
|
selectedIndex={activeTab}
|
||||||
onSelect={setActiveTab}
|
onSelect={setActiveTab}
|
||||||
>
|
>
|
||||||
<Overlay position='top-0 left-[12.2rem]'>
|
<Overlay position='top-0 right-[4rem]'>
|
||||||
<HelpButton topic={HelpTopic.TERM_CONTROL} dimensions='max-w-[38rem]' offset={14} />
|
<HelpButton topic={HelpTopic.TERM_CONTROL} dimensions='max-w-[35rem]' offset={14} />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
<TabList className='flex mb-3 border'>
|
<TabList className='flex justify-center mb-3'>
|
||||||
<ConceptTab
|
<div className='flex border w-fit'>
|
||||||
label={labelReferenceType(ReferenceType.ENTITY)}
|
<ConceptTab
|
||||||
tooltip='Отсылка на термин в заданной словоформе'
|
label={labelReferenceType(ReferenceType.ENTITY)}
|
||||||
className='w-[12rem] border-r-2'
|
tooltip='Отсылка на термин в заданной словоформе'
|
||||||
/>
|
className='w-[12rem] border-r-2'
|
||||||
<ConceptTab
|
/>
|
||||||
label={labelReferenceType(ReferenceType.SYNTACTIC)}
|
<ConceptTab
|
||||||
tooltip='Установление синтаксической связи с отсылкой на термин'
|
label={labelReferenceType(ReferenceType.SYNTACTIC)}
|
||||||
className='w-[12rem]'
|
tooltip='Установление синтаксической связи с отсылкой на термин'
|
||||||
/>
|
className='w-[12rem]'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</TabList>
|
</TabList>
|
||||||
|
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
|
|
|
@ -10,15 +10,14 @@ interface WordformButtonProps {
|
||||||
|
|
||||||
function WordformButton({ text, example, grams, onSelectGrams, isSelected, ...restProps }: WordformButtonProps) {
|
function WordformButton({ text, example, grams, onSelectGrams, isSelected, ...restProps }: WordformButtonProps) {
|
||||||
return (
|
return (
|
||||||
<button type='button' tabIndex={-1}
|
<button type='button' tabIndex={-1}
|
||||||
onClick={() => onSelectGrams(grams)}
|
onClick={() => onSelectGrams(grams)}
|
||||||
className={`min-w-[6rem] p-1 border rounded-none cursor-pointer clr-btn-clear clr-hover ${isSelected ? 'clr-selected': ''}`}
|
className={`min-w-[6rem] p-1 border rounded-none cursor-pointer clr-btn-clear clr-hover ${isSelected ? 'clr-selected': ''}`}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
<p className='font-semibold'>{text}</p>
|
<p className='font-semibold'>{text}</p>
|
||||||
<p>{example}</p>
|
<p>{example}</p>
|
||||||
</button>
|
</button>);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WordformButton;
|
export default WordformButton;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import Label from '../components/Common/Label';
|
||||||
import MiniButton from '../components/Common/MiniButton';
|
import MiniButton from '../components/Common/MiniButton';
|
||||||
import Modal from '../components/Common/Modal';
|
import Modal from '../components/Common/Modal';
|
||||||
import Overlay from '../components/Common/Overlay';
|
import Overlay from '../components/Common/Overlay';
|
||||||
|
@ -210,28 +211,28 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
submitText='Сохранить'
|
submitText='Сохранить'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
className='min-w-[40rem] max-w-[40rem] px-6'
|
||||||
>
|
>
|
||||||
<div className='min-w-[40rem] max-w-[40rem]'>
|
|
||||||
<Overlay position='top-[-0.2rem] left-[7.5rem]'>
|
<Overlay position='top-[-0.2rem] left-[7.5rem]'>
|
||||||
<HelpButton topic={HelpTopic.TERM_CONTROL} dimensions='max-w-[38rem]' offset={3} />
|
<HelpButton topic={HelpTopic.TERM_CONTROL} dimensions='max-w-[38rem]' offset={3} />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
||||||
<TextArea disabled spellCheck
|
<TextArea disabled spellCheck
|
||||||
label='Начальная форма'
|
label='Начальная форма'
|
||||||
placeholder='Начальная форма'
|
placeholder='Термин в начальной форме'
|
||||||
rows={1}
|
rows={1}
|
||||||
value={term}
|
value={term}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='mt-3 mb-2 text-sm font-semibold'>
|
<div className='mt-3 mb-2'>
|
||||||
Параметры словоформы
|
<Label text='Параметры словоформы' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex items-start justify-between w-full'>
|
<div className='flex items-start justify-between w-full'>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
<TextArea
|
<TextArea
|
||||||
placeholder='Введите текст'
|
placeholder='Введите текст'
|
||||||
dimensions='min-w-[18rem] w-full min-h-[4.2rem]'
|
dimensions='min-w-[18rem] w-full min-h-[5rem]'
|
||||||
rows={2}
|
rows={2}
|
||||||
value={inputText}
|
value={inputText}
|
||||||
onChange={event => setInputText(event.target.value)}
|
onChange={event => setInputText(event.target.value)}
|
||||||
|
@ -309,7 +310,6 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
|
||||||
onRowClicked={handleRowClicked}
|
onRowClicked={handleRowClicked}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Modal>);
|
</Modal>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ function DlgGraphParams({ hideWindow, initial, onConfirm } : DlgGraphParamsProps
|
||||||
title='Настройки графа термов'
|
title='Настройки графа термов'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Применить'
|
submitText='Применить'
|
||||||
|
className='flex gap-12 px-6 py-2'
|
||||||
>
|
>
|
||||||
<div className='flex gap-6 my-2'>
|
|
||||||
<div className='flex flex-col gap-1'>
|
<div className='flex flex-col gap-1'>
|
||||||
<h1>Преобразования</h1>
|
<h1 className='mb-2'>Преобразования</h1>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label='Скрыть текст'
|
label='Скрыть текст'
|
||||||
tooltip='Не отображать термины'
|
tooltip='Не отображать термины'
|
||||||
|
@ -55,7 +55,7 @@ function DlgGraphParams({ hideWindow, initial, onConfirm } : DlgGraphParamsProps
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col gap-1'>
|
<div className='flex flex-col gap-1'>
|
||||||
<h1>Типы конституент</h1>
|
<h1 className='mb-2'>Типы конституент</h1>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={labelCstType(CstType.BASE)}
|
label={labelCstType(CstType.BASE)}
|
||||||
value={params.allowBase}
|
value={params.allowBase}
|
||||||
|
@ -97,7 +97,6 @@ function DlgGraphParams({ hideWindow, initial, onConfirm } : DlgGraphParamsProps
|
||||||
setValue={value => updateParams({ allowTheorem: value})}
|
setValue={value => updateParams({ allowTheorem: value})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Modal>);
|
</Modal>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
canSubmit={validated}
|
canSubmit={validated}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
className='flex justify-center items-center gap-6 w-full min-w-[24rem] py-6 px-6'
|
||||||
>
|
>
|
||||||
<div className='flex justify-center items-center gap-6 w-full min-w-[22rem] my-3'>
|
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
placeholder='Выберите тип'
|
placeholder='Выберите тип'
|
||||||
className='min-w-[14rem] self-center'
|
className='min-w-[14rem] self-center'
|
||||||
|
@ -67,7 +67,6 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||||
onChange={event => updateData({alias: event.target.value})}
|
onChange={event => updateData({alias: event.target.value})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Modal>);
|
</Modal>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,9 @@ function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) {
|
||||||
, []);
|
, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal readonly
|
||||||
hideWindow={hideWindow}
|
hideWindow={hideWindow}
|
||||||
readonly
|
className='px-6'
|
||||||
>
|
>
|
||||||
<div className='w-full my-2 text-lg text-center'>
|
<div className='w-full my-2 text-lg text-center'>
|
||||||
{!hoverNode ? expression : null}
|
{!hoverNode ? expression : null}
|
||||||
|
|
|
@ -44,20 +44,20 @@ function DlgUploadRSForm({ hideWindow }: DlgUploadRSFormProps) {
|
||||||
canSubmit={!!file}
|
canSubmit={!!file}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Загрузить'
|
submitText='Загрузить'
|
||||||
|
className='w-[20rem] px-6'
|
||||||
>
|
>
|
||||||
<div className='flex flex-col items-start min-w-[20rem] max-w-[20rem]'>
|
<FileInput
|
||||||
<FileInput
|
label='Выбрать файл'
|
||||||
label='Выбрать файл'
|
dimensions='w-full flex items-center'
|
||||||
acceptType={EXTEOR_TRS_FILE}
|
acceptType={EXTEOR_TRS_FILE}
|
||||||
onChange={handleFile}
|
onChange={handleFile}
|
||||||
/>
|
/>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label='Загружать название и комментарий'
|
label='Загружать название и комментарий'
|
||||||
dimensions='w-fit pb-2'
|
dimensions='w-fit py-2'
|
||||||
value={loadMetadata}
|
value={loadMetadata}
|
||||||
setValue={value => setLoadMetadata(value)}
|
setValue={value => setLoadMetadata(value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</Modal>);
|
</Modal>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,6 +362,7 @@ function RSTabs() {
|
||||||
/> : null}
|
/> : null}
|
||||||
{showDeleteCst ?
|
{showDeleteCst ?
|
||||||
<DlgDeleteCst
|
<DlgDeleteCst
|
||||||
|
schema={schema!}
|
||||||
hideWindow={() => setShowDeleteCst(false)}
|
hideWindow={() => setShowDeleteCst(false)}
|
||||||
onDelete={handleDeleteCst}
|
onDelete={handleDeleteCst}
|
||||||
selected={toBeDeleted}
|
selected={toBeDeleted}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user